Skip to content

Commit d721c36

Browse files
committed
docs: add design.md
1 parent 8144ebf commit d721c36

1 file changed

Lines changed: 340 additions & 0 deletions

File tree

design.md

Lines changed: 340 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,340 @@
1+
# PBCTF — Landing Page Design System
2+
3+
Design context for the PBCTF landing page. Use this as the reference when building new
4+
sections, components, or marketing surfaces so they stay visually consistent.
5+
6+
The aesthetic has **two intertwined layers**:
7+
8+
1. **Synthwave / cyberpunk world** — near-black space, a single neon-green accent, a starfield,
9+
scanlines, CRT flicker, and a perspective synthwave grid. This is the *atmosphere*.
10+
2. **Retro hardware devices** — most content sections are physically modeled gadgets: CRT
11+
monitors, a Game Boy, a radio tuner, hardware-chassis cards with screws, LEDs, beveled
12+
plastic, and tactile press states. This is the *furniture* sitting inside the world.
13+
14+
Everything is dark, green-accented, glowing, and skeuomorphic-retro. Premium and restrained
15+
on color (one hue), maximal on tactile detail.
16+
17+
All landing styles live under `components/landing/`, are scoped to the `.pbctf-landing`
18+
wrapper, and are authored as plain component CSS (one `.css` per component folder), **not**
19+
Tailwind. The token source of truth is `components/landing/landing.css` (`:root`).
20+
21+
---
22+
23+
## 1. Color
24+
25+
| Token | Value | Use |
26+
|---|---|---|
27+
| `--bg` | `#050505` | Page background |
28+
| `--bg-elevated` | `#0A0A0A` | Raised surfaces |
29+
| `--bg-card` | `#0D0D0D` | Card background |
30+
| `--bg-card-hover` | `#111111` | Card hover |
31+
| `--secondary` | `#0B0B0B` | Secondary dark fill |
32+
| `--primary` | `#00FF88` | **Primary neon green** — the brand accent |
33+
| `--primary-dim` | `rgba(0,255,136,0.15)` | Tints, faint fills |
34+
| `--primary-glow` | `rgba(0,255,136,0.4)` | Glow shadows |
35+
| `--accent-gold` | `#8CFF00` | Lime/chartreuse secondary accent |
36+
| `--accent-gold-dim` | `rgba(140,255,0,0.15)` | Lime tints |
37+
| `--accent-gold-glow` | `rgba(140,255,0,0.4)` | Lime glow |
38+
| `--text` | `#FFFFFF` | Primary text |
39+
| `--text-secondary` | `#E0E0E0` | Secondary text |
40+
| `--muted` | `#A0A0A0` | Body/muted copy |
41+
| `--muted-dark` | `#666666` | Disabled, hints |
42+
| `--border` | `rgba(255,255,255,0.06)` | Default hairline border |
43+
| `--border-hover` | `rgba(255,255,255,0.12)` | Border on hover |
44+
45+
**Off-palette literals used inside hardware components** (intentional, for skeuomorphism — keep
46+
consistent if you build new gadgets):
47+
48+
- **Chassis / plastic darks:** `#1f2723``#0d120f` (device gradient), `#1d221e`, `#2a352f`,
49+
`#282f2a`, `#2a2c30` (Game Boy body), `#222`/`#111`/`#1a1a1a` (buttons/D-pad).
50+
- **CRT screen darks:** `#010603`, `#050806`, `#030604`, `#081a10` (Game Boy green screen).
51+
- **Screws:** `#0a0e0c` with `inset 0 1px 2px rgba(0,0,0,1), 0 1px 0 rgba(255,255,255,0.1)`.
52+
- **Inactive LED red:** `#440000` / `#550000` / `#3a1e1e`; Game Boy power LED active `#ff0044`.
53+
- **Muted secondary green** (2nd/3rd place, non-hero devices): `#A0E0B0` / `rgba(160,224,176,*)`.
54+
- **macOS window dots:** `#ff5f56` / `#ffbd2e` / `#27c93f`.
55+
56+
**Rules**
57+
- One brand accent. Green (`--primary`) leads; lime (`--accent-gold`) is the only secondary and
58+
is used sparingly. Don't add new brand hues — the only "extra" colors allowed are the
59+
skeuomorphic device literals above.
60+
- Backgrounds are near-black, layered by elevation (`--bg``--bg-elevated``--bg-card`).
61+
- Borders are white at very low opacity, never solid gray.
62+
- Signature gradients: device chassis `linear-gradient(145deg, #1f2723 0%, #0d120f 100%)`;
63+
CTA/lime `linear-gradient(135deg, var(--accent-gold), #7BE800)`; hero sun
64+
`#8CFF00 → #00FF88 → #000000`; glass card `linear-gradient(145deg, rgba(13,20,16,.7), rgba(8,13,10,.9))`.
65+
66+
---
67+
68+
## 2. Typography
69+
70+
Loaded in `app/layout.tsx` via Google Fonts (`display=swap`):
71+
72+
| Token | Family | Use |
73+
|---|---|---|
74+
| `--font-body` / `--font-heading` | **Lexend** | Body copy and all headings |
75+
| `--font-hero` | **Space Grotesk** | Hero headline (big display) |
76+
| `--font-mono` | Lexend (mono role) | Eyebrow labels, taglines, technical/screen text |
77+
78+
> **JetBrains Mono** is also preloaded and is the right pick for genuinely monospaced terminal/
79+
> screen readouts (CRT text, barcodes, badges). `--font-mono` currently maps to Lexend for the label role.
80+
81+
**Type scale:** `--text-xs` `0.75rem``--text-6xl` `4rem`, plus `--text-hero`
82+
`clamp(2.5rem,6vw,5rem)`. Section titles `clamp(2rem,4vw,3.25rem)`; hero headline
83+
`clamp(4.5rem,9.5vw,7.5rem)` @800.
84+
85+
- Headings: weight 600–700, `line-height: 1.15`, `letter-spacing: -0.02em` (tight).
86+
- Body: weight 400, `line-height: 1.6`.
87+
- **Eyebrow/section labels** are the one intentional ALL-CAPS + wide-tracking place: mono,
88+
`--text-xs`, `letter-spacing: 0.2em`, uppercase, green, with a 24px green leading rule
89+
(`.section__label`). Deliberate CTF/terminal motif.
90+
- **Screen/badge text** inside devices: mono, small (`8px–14px`), often `letter-spacing: 0.1em–0.2em`,
91+
uppercase, in green with a faint `text-shadow`.
92+
93+
---
94+
95+
## 3. Spacing, layout, radius
96+
97+
- **Spacing scale:** `--space-1` (0.25rem) → `--space-40` (10rem), 4px-based.
98+
- **Containers:** `--container-max` 1200px, `--container-wide` 1400px (`.container`, `.container--wide`).
99+
- **Sections:** `.section`, vertical rhythm `--section-padding-y` `clamp(5rem,10vh,8rem)`
100+
(reduced on mobile), horizontal `--section-padding-x` `clamp(1.25rem,4vw,2.5rem)`.
101+
- **Radius:** `--radius-sm` 6px (buttons), `--radius-md` 10px, `--radius-lg` 16px (cards),
102+
`--radius-xl` 24px, `--radius-full`. Device chassis use bespoke larger radii (12–30px) and
103+
asymmetric corners (e.g. Game Boy `12px 12px 60px 12px`).
104+
105+
---
106+
107+
## 4. Core shared components
108+
109+
### Buttons (`.btn`)
110+
- Base: inline-flex, uppercase, weight 600, `letter-spacing: 0.04em`, `--radius-sm`,
111+
padding `--space-4 --space-8`.
112+
- `.btn--primary`: solid green on dark; hover lifts 1px + green glow
113+
`0 0 30px var(--primary-glow), 0 0 60px rgba(0,255,136,0.15)`.
114+
- `.btn--secondary`: transparent + hairline border; hover → green border + green text.
115+
- `.btn--gold`: lime gradient fill; hover lime glow.
116+
- "Pill" CTA variant (Sponsors): `border-radius: 999px`, faint green gradient fill, hover
117+
brightens + `0 0 30px rgba(0,255,136,0.12)` + lift 2px.
118+
119+
### Section header pattern
120+
`.section__label` (green mono eyebrow + rule) → `.section__title` (large, 700) →
121+
`.section__subtitle` (muted, `--text-lg`, max 600px). Reuse this trio for every new section.
122+
123+
### Glass card (used by Categories, Sponsors, Venue, About)
124+
- Background `linear-gradient(145deg, rgba(13,20,16,.7), rgba(8,13,10,.8–.95))` +
125+
`backdrop-filter: blur(10–12px)`.
126+
- Border `1px solid rgba(0,255,136,0.05–0.15)` (or low-opacity white); radius 12–20px.
127+
- Optional top accent line via `::before`: `height:1–2px; background: linear-gradient(90deg,
128+
transparent, var(--primary), transparent)`, `opacity:0``1` on hover.
129+
- Hover: `translateY(-4px to -6px)`, border brightens to `rgba(0,255,136,0.15–0.25)`, soft
130+
green-tinted shadow `0 10–20px 40–60px -10px rgba(0,255,136,0.06–0.1)`.
131+
132+
### Plain `.card`
133+
`--bg-card`, hairline `--border`, `--radius-lg`, padding `--space-8`. Hover brightens border +
134+
background. No colored left-accent stripes.
135+
136+
---
137+
138+
## 5. The retro hardware-device language (the defining motif)
139+
140+
Most sections are modeled as physical gadgets. When building a new "device" section, compose
141+
from this kit so it reads as the same hardware family:
142+
143+
**Chassis**
144+
- Body gradient `linear-gradient(145deg, #1f2723 0%, #0d120f 100%)`, border `1px solid #2a352f`
145+
with a thicker (`4px`) bottom border for depth.
146+
- Layered shadow recipe: `0 15px 35px rgba(0,0,0,0.6)` (drop) + `inset 0 2px 5px rgba(255,255,255,0.05)`
147+
(top highlight). Bigger devices add `0 10px 0 0 #121513` (hard bottom edge) and
148+
`0 25px 50px rgba(0,0,0,0.85)`.
149+
150+
**Screws**`6px` circle, `#0a0e0c`, `inset 0 1px 2px rgba(0,0,0,1), 0 1px 0 rgba(255,255,255,0.1)`,
151+
placed in chassis corners (`top/left: 8px`, etc.).
152+
153+
**LED indicator** — small rounded rect/dot. Inactive `#440000`/`#550000` with inset shadow;
154+
active `var(--primary)` (or `#A0E0B0` for secondary devices, `#ff0044` for Game Boy power) with
155+
`box-shadow: 0 0 10px <color>`. Often animated with a 2s pulse.
156+
157+
**CRT screen** — inset dark panel (`#050806`/`#010603`), `border-radius: 6–8px`,
158+
`box-shadow: inset 0 0 20–40px rgba(0,0,0,0.8)`, green border when "on"
159+
(`rgba(0,255,136,0.4–0.5)` + inner green glow). Always overlaid with **scanlines**:
160+
`repeating-linear-gradient(... rgba(0,0,0,0.25) 50%)`, `background-size: 100% 4px`, `opacity ~0.6`.
161+
Screen text is mono green with `text-shadow`.
162+
163+
**Tactile press** — interactive hardware (power buttons, action buttons, play button) uses a
164+
fast `~0.1–0.15s ease` transition and presses *into* the chassis on `:active`:
165+
`transform: translateY(1.5–3px)` with the box-shadow swapping outer drop-shadow for inset.
166+
167+
**macOS window chrome** — terminal/window panels get three 8px dots `#ff5f56 / #ffbd2e / #27c93f`.
168+
169+
**Barcodes / tech badges** — decorative `repeating-linear-gradient` barcode strips and mono
170+
`font-size:8–11px` uppercase badges with wide tracking, green on hero devices.
171+
172+
---
173+
174+
## 6. Section-by-section aesthetic catalog
175+
176+
**Header** — fixed nav, transparent → on scroll glassy `rgba(5,5,5,0.75)` + `blur(20px)` +
177+
faint green border + `0 10px 40px rgba(0,0,0,0.5)`. Logo is gradient text
178+
`linear-gradient(135deg, var(--text), var(--primary))` with green drop-shadow; hover rotates the
179+
mark `90deg`. Uppercase nav links (13px, weight 600) glow white on hover. Mobile: full-screen
180+
overlay `rgba(5,5,5,0.95)` with a corner green radial; animated hamburger (lines 24/14/20px → X).
181+
182+
**Loader** (first visit only, gated by `sessionStorage` `pbctf_loader_seen`) — full-screen
183+
`#030604`, panning 40px green grid (`bg-pan` 20s), vignette, thin green progress bar with
184+
`0 0 10px` glow + a blurred glow layer beneath, pulsing brand wordmark (`pulse-glow` 2s,
185+
text-shadow 10px→30px), tabular-nums percentage. Exits with `translateY(-40px) scale(1.02)` fade.
186+
187+
**Hero** — synthwave scene: black→green vertical sky, a circular "sun" (green→lime→black) sliced
188+
by horizontal scanlines, a glowing neon horizon line (`0 0 35px #00FF88`), and a perspective grid
189+
`rotateX(55deg)` scrolling toward the viewer (`grid-scroll-straight` 2.5s). Centered headline in
190+
Space Grotesk 800 with multi-layer neon `text-shadow`; mono uppercase tagline; bouncing scroll
191+
chevron; cinematic letterbox bars.
192+
193+
**MissionBrief** — a full **CRT monitor on a stand** (beveled `30px`-radius housing, neck + base),
194+
with a power button, knobs, LED, and a playable Flappy-Bird-style minigame on a green phosphor
195+
screen. Power on/off plays CRT distortion animations (`crt-power-on` 0.35s flash; `crt-power-off`
196+
0.45s collapse to a line then a dot). Blinking cursor terminal text.
197+
198+
**Timeline** — vertical spine with a glowing green progress line driven by scroll
199+
(`linear-gradient(to bottom, dim, primary)` + glow). Each event is a small **CRT-screen device**
200+
(chassis + screws + LED + scanline screen). Active node pulses (`pulse-shadow` 2s ring), its
201+
screen flickers on activate (`screen-flicker` 0.4s) and lifts `translateY(-4px)`. Desktop:
202+
alternating left/right around center; mobile: single left-aligned rail.
203+
204+
**Categories** — a **cyber-database UI**: glass container split into a left matrix nav sidebar
205+
(320px) and a right readout panel with a radial green wash + scanlines. Animated dual **orbital
206+
rings** around a 48px line-drawn icon (`rotate-slow` 10s / 15s reverse), an **audio-wave** equalizer
207+
(`audio-wave` 1.2s, staggered bars with green glow), blinking nav indicators, difficulty pips,
208+
and a green underline divider with glow.
209+
210+
**Prizes** — three **hardware-device podium cards** (desktop order 2nd/1st/3rd, align-end for a
211+
podium; mobile 1st/2nd/3rd stacked). Each is a chassis with screws, LED, and an inset scanline
212+
screen showing the amount. 1st place is hero-sized (380px) with full neon green glow; 2nd/3rd use
213+
muted `#A0E0B0` green. Barcode strip + tech badges. Total prize headline `clamp(2.5rem,6vw,4rem)`
214+
@800 in green with `0 0 30px` glow and a fading green divider.
215+
216+
**Sponsors** — radial green wash background; horizontal **glass logo cards** (260×120) with a
217+
spring hover (`cubic-bezier(0.34,1.56,0.64,1)`, lift + `scale(1.03)`) and a one-shot diagonal
218+
**shimmer** sweep (`sponsors-shimmer` 0.65s). A masked **marquee ticker** of names
219+
(`ticker-scroll` 28s linear, pauses on hover) with 4px dot separators. "Become a sponsor" glass
220+
CTA block with a top accent line and a pill button.
221+
222+
**AboutPointBlank** — centered glass content box (`blur(10px)`, green border, inner green glow,
223+
masked radial vignette) with a video modal. Hardware-style circular **play button** (`#222`
224+
casing, layered inset shadows, green icon with drop-shadow) that presses in on `:active`
225+
(`translateY(2px)`). 16:9 video wrapper with green border; close button hovers red `#ff4444`.
226+
227+
**Venue** — glass venue cards (radius 20px, `blur(12px)`) with 16/10 map images
228+
(`scale(1.05)` on hover, bottom gradient scrim) and a top green accent line on hover. Includes a
229+
**retro radio-tuner module**: a 3D **knob** (60px, layered inset/outset shadows, green indicator
230+
dot, `cursor: grab`), a pulsing green status readout (`pulse-status` 2s), and a volume-bar
231+
equalizer (rising 8→24px bars, active bars green-glowing).
232+
233+
**FAQ** — a classic **Game Boy**: dark matte body `#2a2c30` with the signature
234+
`12px 12px 60px 12px` corner notch and heavy layered shadows, a `#111` bezel, and a retro-green
235+
screen `#081a10` with green text `#00FF88`, scanlines, a styled green scrollbar, and accordion
236+
items (green-bordered, brighten when open). Functional **D-pad** (cross of `#111` bars) and
237+
circular green **action buttons** (press in `translateY(3px)`), angled **speaker slits**, and a
238+
red power light (`#ff0044` glow when active).
239+
240+
**FinalCTA** — centered headline `clamp(2rem,5vw,3.5rem)` @700 + muted description over a
241+
breathing radial glow (`radial-gradient(ellipse, var(--accent-gold-dim), transparent 70%)`,
242+
`cta-pulse` 4s alternate opacity 0.3↔0.6) and the primary/secondary button group.
243+
244+
**Footer** — minimal bar on `--bg-card` with a top accent gradient line; 36px square social
245+
icons (hairline border) that lift `translateY(-2px)` and turn green on hover; muted xs legal
246+
links; faded brand logo. Desktop grid `1fr auto 1fr`.
247+
248+
**StarsBackground** — fixed full-viewport `<canvas>` starfield, `opacity: 0.8`, `z-index: -5`,
249+
`pointer-events: none`. JS-animated.
250+
251+
**GridScan** — uses the webcam (`face-api.js`): a small mirrored (`scaleX(-1)`) camera preview
252+
window (220×132, bottom-right, `pointer-events: none`) with a blurred badge label. A canvas
253+
scanning effect; non-interactive overlay.
254+
255+
---
256+
257+
## 7. Motion & keyframe library
258+
259+
Libraries: **GSAP + ScrollTrigger** (scroll reveals, hero grid, timeline progress) and
260+
**Framer Motion** (`MotionConfig reducedMotion="user"`).
261+
262+
- **Easing tokens:** `--ease-out` `cubic-bezier(0.16,1,0.3,1)` (entrances, the house curve),
263+
`--ease-in-out` `cubic-bezier(0.65,0,0.35,1)`. Spring hover (cards): `cubic-bezier(0.34,1.56,0.64,1)`.
264+
Loader exit: `cubic-bezier(0.77,0,0.175,1)`.
265+
- **Durations:** `--duration-fast` 150ms, `--duration-normal` 300ms, `--duration-slow` 500ms.
266+
Tactile hardware uses ~100–150ms; hover transitions use `--duration-normal var(--ease-out)`.
267+
268+
Named keyframes already in use (reuse rather than reinvent):
269+
270+
| Animation | What it does | Timing |
271+
|---|---|---|
272+
| `grid-scroll-straight` | Hero synthwave grid scrolls toward viewer | 2.5s linear ∞ |
273+
| `hero-bounce` | Scroll-indicator chevron bob | 2s ∞ |
274+
| `crt-flicker-anim` | Global CRT opacity jitter | 0.15s ∞ |
275+
| `bg-pan` | Loader grid pan | 20s linear ∞ |
276+
| `pulse-glow` | Loader brand text-shadow breathe | 2s ease-in-out ∞ alt |
277+
| `crt-power-on` / `crt-power-off` | MissionBrief monitor on/off distortion | 0.35s / 0.45s |
278+
| `cursor-blink` | Terminal cursor | 1s step-end ∞ |
279+
| `power-glow` | Power LED breathe | 2s alt ∞ |
280+
| `rotate-slow` | Categories orbital rings (one reversed) | 10s / 15s linear ∞ |
281+
| `draw-icon` | Categories SVG stroke draw-on | 1.5s ease-out |
282+
| `audio-wave` | Categories equalizer bars | 1.2s ease-in-out ∞ (staggered) |
283+
| `blink` | Nav/indicator blink | 1s step-end ∞ |
284+
| `pulse-shadow` | Timeline active node ring pulse | 2s ∞ |
285+
| `screen-flicker` | Timeline screen flicker on activate | 0.4s ease-out |
286+
| `sponsors-shimmer` | Sponsor card diagonal shimmer sweep | 0.65s ease (hover) |
287+
| `ticker-scroll` | Sponsor marquee | 28s linear ∞ (pause on hover) |
288+
| `pulse-status` | Venue radio status opacity pulse | 2s ∞ |
289+
| `cta-pulse` | FinalCTA glow breathe | 4s ease-in-out ∞ alt |
290+
291+
**Always honor `prefers-reduced-motion`**`landing.css` already kills animations/transitions
292+
under it, and `MotionConfig` respects it. New animations must degrade gracefully.
293+
294+
---
295+
296+
## 8. Global atmosphere overlays & z-index
297+
298+
Applied in `LandingPage.tsx` over the whole page:
299+
300+
- **Starfield** (`StarsBackground`, `z-index: -5`) behind everything.
301+
- **Cyber grid** (`.cyber-grid`): faint fixed 40px green grid, `z-index: -2`.
302+
- **Scanlines** (`.scanlines`): fixed full-screen 4px repeating dark gradient,
303+
`z-index: 9999`, `pointer-events: none`.
304+
- **CRT flicker** (`.crt-flicker`): tiny opacity oscillation.
305+
- **Cinematic letterbox** + glitch **Loader**: first-visit intro framing.
306+
- **Custom scrollbar & selection**: 6px green thumb (hover lime); green text selection.
307+
308+
**Z-index scale:** `--z-3d:0` · `--z-content:1` · `--z-header:100` · `--z-overlay:200` ·
309+
`--z-modal:300`. Texture overlays intentionally sit at `9999`; background canvases use negative
310+
z-index. The `.pbctf-landing` wrapper sets `isolation: isolate` so the starfield paints correctly.
311+
312+
---
313+
314+
## 9. Page composition
315+
316+
`LandingPage.tsx` order: `StarsBackground` → scanlines → (`Loader`) → fixed `Header`
317+
`main`( `Hero``MissionBrief``Timeline``Categories``Prizes``Sponsors`
318+
`AboutPointBlank``Venue``FAQ``FinalCTA` ) → `Footer`. Each section is a folder with
319+
`.jsx` + scoped `.css`.
320+
321+
---
322+
323+
## 10. Conventions & guardrails
324+
325+
- **Scope everything to `.pbctf-landing`.** All selectors are prefixed so landing styles never
326+
leak into the app/dashboard. Keep new landing CSS prefixed.
327+
- **Tokens over literals** for brand color/spacing/radius — add a token in `landing.css` rather
328+
than hardcoding. The only sanctioned literals are the skeuomorphic device colors in §1/§5.
329+
- **One CSS file per component**, colocated in the component folder.
330+
- **New "device" sections** must reuse the hardware kit (§5): chassis gradient, screws, LED,
331+
scanline screen, tactile press. Don't invent a different gadget visual language.
332+
- **Mobile**: primary breakpoint `max-width: 768px` (some components use 640/800/480/1024).
333+
Devices scale chassis/screen/control dimensions down proportionally and stack to single column.
334+
- **Accessibility**: keep reduced-motion fallbacks; reserve glow for display/screen type and use
335+
`--text`/`--text-secondary` for readable body copy on the dark ground.
336+
- **Brand note:** the neon-green-on-black, ALL-CAPS-mono labels, glow, scanlines, synthwave grid,
337+
and retro-hardware skeuomorphism are the *intended* brand for this landing surface. The general
338+
"avoid AI design tells" guidance (no glows, no uppercase eyebrows, no glassmorphism) does **not**
339+
override it here — but keep it tasteful, consistent, and performance-conscious.
340+
</content>

0 commit comments

Comments
 (0)