veza/veza_design_system_v4.html
2026-01-04 01:44:23 +01:00

2485 lines
81 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="fr" data-theme="dark">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>VEZA × TALAS — Design System v4 · NEON_REFINED</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;600&family=Bebas+Neue&display=swap" rel="stylesheet">
<style>
/* ═══════════════════════════════════════════════════════════════════════════
VEZA × TALAS — DESIGN SYSTEM v4 · NEON_REFINED
Épuré · Uniforme · Composants Avancés · Production Ready
═══════════════════════════════════════════════════════════════════════════ */
/* ─────────────────────────────────────────────────────────────────────────
1. DESIGN TOKENS
───────────────────────────────────────────────────────────────────────── */
:root {
/* === PALETTE CORE === */
--black: #08080c;
--black-light: #0e0e14;
--surface: #14141c;
--surface-light: #1a1a24;
--border: #252530;
--border-light: #32323f;
/* === NEON ACCENTS === */
--cyan: #00e5ff;
--cyan-muted: #00b8cc;
--cyan-glow: rgba(0, 229, 255, 0.4);
--magenta: #ff0080;
--magenta-muted: #cc0066;
--magenta-glow: rgba(255, 0, 128, 0.4);
--green: #00ff88;
--green-muted: #00cc6a;
--green-glow: rgba(0, 255, 136, 0.4);
--orange: #ff6600;
--yellow: #ffcc00;
--red: #ff3355;
/* === TEXT === */
--text: #f0f0f5;
--text-secondary: #a0a0b0;
--text-muted: #606070;
/* === TYPOGRAPHY === */
--font-display: 'Bebas Neue', 'Space Grotesk', sans-serif;
--font-body: 'Space Grotesk', system-ui, sans-serif;
--font-mono: 'JetBrains Mono', monospace;
/* === SPACING === */
--sp-1: 0.25rem;
--sp-2: 0.5rem;
--sp-3: 0.75rem;
--sp-4: 1rem;
--sp-5: 1.25rem;
--sp-6: 1.5rem;
--sp-8: 2rem;
--sp-10: 2.5rem;
--sp-12: 3rem;
--sp-16: 4rem;
--sp-20: 5rem;
/* === EFFECTS === */
--radius-sm: 4px;
--radius-md: 8px;
--radius-lg: 12px;
--radius-xl: 16px;
--radius-full: 9999px;
--shadow: 0 4px 20px rgba(0, 0, 0, 0.5);
--shadow-lg: 0 8px 40px rgba(0, 0, 0, 0.6);
--transition: 200ms ease;
--transition-fast: 120ms ease;
}
/* ─────────────────────────────────────────────────────────────────────────
2. RESET & BASE
───────────────────────────────────────────────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html { font-size: 16px; scroll-behavior: smooth; }
body {
font-family: var(--font-body);
font-size: 14px;
line-height: 1.6;
color: var(--text);
background: var(--black);
-webkit-font-smoothing: antialiased;
}
::selection { background: var(--cyan); color: var(--black); }
a { color: inherit; text-decoration: none; }
ul, ol { list-style: none; }
img, svg { max-width: 100%; display: block; }
button { font: inherit; cursor: pointer; background: none; border: none; color: inherit; }
input, textarea { font: inherit; }
.sr-only {
position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
overflow: hidden; clip: rect(0,0,0,0); border: 0;
}
/* ─────────────────────────────────────────────────────────────────────────
3. LAYOUT
───────────────────────────────────────────────────────────────────────── */
.page {
min-height: 100vh;
background:
radial-gradient(ellipse 80% 60% at 70% 10%, rgba(0, 229, 255, 0.03), transparent),
radial-gradient(ellipse 60% 50% at 20% 80%, rgba(255, 0, 128, 0.02), transparent),
var(--black);
}
.container {
width: 100%;
max-width: 1200px;
margin: 0 auto;
padding: 0 var(--sp-6);
}
.grid { display: grid; gap: var(--sp-6); }
.grid-2 { grid-template-columns: repeat(2, 1fr); }
.grid-3 { grid-template-columns: repeat(3, 1fr); }
.grid-4 { grid-template-columns: repeat(4, 1fr); }
.grid-auto { grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); }
@media (max-width: 768px) {
.grid-2, .grid-3, .grid-4 { grid-template-columns: 1fr; }
}
/* ─────────────────────────────────────────────────────────────────────────
4. HEADER
───────────────────────────────────────────────────────────────────────── */
.header {
position: sticky;
top: 0;
z-index: 100;
background: rgba(8, 8, 12, 0.9);
backdrop-filter: blur(20px);
border-bottom: 1px solid var(--border);
}
.header__inner {
display: flex;
align-items: center;
justify-content: space-between;
height: 64px;
}
.brand {
display: flex;
align-items: center;
gap: var(--sp-3);
}
.brand__icon {
width: 36px;
height: 36px;
background: conic-gradient(from 180deg, var(--cyan), var(--magenta), var(--cyan));
border-radius: var(--radius-full);
display: flex;
align-items: center;
justify-content: center;
animation: icon-rotate 10s linear infinite;
}
.brand__icon::before {
content: "";
width: 26px;
height: 26px;
background: var(--black);
border-radius: var(--radius-full);
}
@keyframes icon-rotate { to { transform: rotate(360deg); } }
.brand__text {
font-family: var(--font-display);
font-size: 1.5rem;
letter-spacing: 0.1em;
}
.brand__text span:first-child { color: var(--cyan); }
.brand__text span:last-child { color: var(--magenta); }
.nav { display: flex; align-items: center; gap: var(--sp-6); }
.nav__link {
font-family: var(--font-mono);
font-size: 12px;
color: var(--text-secondary);
padding: var(--sp-2) 0;
position: relative;
transition: color var(--transition);
}
.nav__link::after {
content: "";
position: absolute;
bottom: 0;
left: 0;
width: 0;
height: 1px;
background: var(--cyan);
transition: width var(--transition);
}
.nav__link:hover { color: var(--text); }
.nav__link:hover::after { width: 100%; }
.nav__link--active { color: var(--cyan); }
.nav__link--active::after { width: 100%; }
/* ─────────────────────────────────────────────────────────────────────────
5. BUTTONS
───────────────────────────────────────────────────────────────────────── */
.btn {
display: inline-flex;
align-items: center;
justify-content: center;
gap: var(--sp-2);
font-family: var(--font-body);
font-weight: 600;
font-size: 13px;
letter-spacing: 0.02em;
padding: var(--sp-3) var(--sp-5);
border-radius: var(--radius-md);
border: 1px solid transparent;
transition: all var(--transition);
position: relative;
overflow: hidden;
}
.btn::before {
content: "";
position: absolute;
inset: 0;
background: linear-gradient(135deg, rgba(255,255,255,0.1), transparent);
opacity: 0;
transition: opacity var(--transition);
}
.btn:hover::before { opacity: 1; }
.btn:disabled { opacity: 0.4; pointer-events: none; }
/* Sizes */
.btn--sm { font-size: 12px; padding: var(--sp-2) var(--sp-4); }
.btn--lg { font-size: 14px; padding: var(--sp-4) var(--sp-6); }
.btn--xl { font-size: 15px; padding: var(--sp-5) var(--sp-8); }
/* Variants */
.btn--primary {
background: var(--cyan);
color: var(--black);
box-shadow: 0 0 20px var(--cyan-glow);
}
.btn--primary:hover {
background: #fff;
box-shadow: 0 0 30px var(--cyan-glow);
transform: translateY(-1px);
}
.btn--secondary {
background: transparent;
border-color: var(--border-light);
color: var(--text);
}
.btn--secondary:hover {
border-color: var(--cyan);
color: var(--cyan);
}
.btn--ghost {
background: transparent;
color: var(--text-secondary);
}
.btn--ghost:hover {
background: var(--surface);
color: var(--text);
}
.btn--danger {
background: var(--red);
color: #fff;
}
.btn--magenta {
background: var(--magenta);
color: #fff;
box-shadow: 0 0 20px var(--magenta-glow);
}
/* Icon button */
.btn--icon {
width: 40px;
height: 40px;
padding: 0;
border-radius: var(--radius-full);
}
.btn--icon.btn--sm { width: 32px; height: 32px; }
.btn--icon.btn--lg { width: 48px; height: 48px; }
/* ─────────────────────────────────────────────────────────────────────────
6. INPUTS
───────────────────────────────────────────────────────────────────────── */
.form-group {
display: flex;
flex-direction: column;
gap: var(--sp-2);
}
.label {
font-family: var(--font-mono);
font-size: 11px;
font-weight: 500;
color: var(--text-secondary);
text-transform: uppercase;
letter-spacing: 0.05em;
}
.input {
font-size: 14px;
padding: var(--sp-3) var(--sp-4);
background: var(--surface);
border: 1px solid var(--border);
border-radius: var(--radius-md);
color: var(--text);
transition: all var(--transition);
outline: none;
}
.input::placeholder { color: var(--text-muted); }
.input:hover { border-color: var(--border-light); }
.input:focus {
border-color: var(--cyan);
box-shadow: 0 0 0 3px rgba(0, 229, 255, 0.1);
}
.input--error { border-color: var(--red); }
.input--error:focus { box-shadow: 0 0 0 3px rgba(255, 51, 85, 0.1); }
.input--success { border-color: var(--green); }
.input-message {
font-size: 12px;
display: flex;
align-items: center;
gap: var(--sp-1);
}
.input-message--error { color: var(--red); }
.input-message--success { color: var(--green); }
/* Search Input */
.search-input {
position: relative;
}
.search-input__icon {
position: absolute;
left: var(--sp-4);
top: 50%;
transform: translateY(-50%);
color: var(--text-muted);
width: 16px;
height: 16px;
}
.search-input .input {
padding-left: calc(var(--sp-4) + 16px + var(--sp-3));
}
/* ─────────────────────────────────────────────────────────────────────────
7. CARDS
───────────────────────────────────────────────────────────────────────── */
.card {
background: var(--surface);
border: 1px solid var(--border);
border-radius: var(--radius-lg);
overflow: hidden;
transition: all var(--transition);
}
.card:hover {
border-color: var(--border-light);
transform: translateY(-2px);
box-shadow: var(--shadow);
}
.card--interactive { cursor: pointer; }
.card--glow-cyan:hover {
border-color: var(--cyan);
box-shadow: 0 0 30px rgba(0, 229, 255, 0.1);
}
.card--glow-magenta:hover {
border-color: var(--magenta);
box-shadow: 0 0 30px rgba(255, 0, 128, 0.1);
}
.card__header {
padding: var(--sp-4) var(--sp-5);
border-bottom: 1px solid var(--border);
display: flex;
align-items: center;
justify-content: space-between;
}
.card__title {
font-family: var(--font-body);
font-size: 14px;
font-weight: 600;
}
.card__body { padding: var(--sp-5); }
.card__footer {
padding: var(--sp-4) var(--sp-5);
border-top: 1px solid var(--border);
background: var(--black-light);
}
/* ─────────────────────────────────────────────────────────────────────────
8. BADGES & TAGS
───────────────────────────────────────────────────────────────────────── */
.badge {
display: inline-flex;
align-items: center;
gap: var(--sp-1);
font-family: var(--font-mono);
font-size: 10px;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.05em;
padding: var(--sp-1) var(--sp-2);
border-radius: var(--radius-sm);
}
.badge--default { background: var(--surface-light); color: var(--text-secondary); }
.badge--cyan { background: rgba(0, 229, 255, 0.15); color: var(--cyan); }
.badge--magenta { background: rgba(255, 0, 128, 0.15); color: var(--magenta); }
.badge--green { background: rgba(0, 255, 136, 0.15); color: var(--green); }
.badge--orange { background: rgba(255, 102, 0, 0.15); color: var(--orange); }
.badge--red { background: rgba(255, 51, 85, 0.15); color: var(--red); }
.badge__dot {
width: 6px;
height: 6px;
border-radius: var(--radius-full);
background: currentColor;
}
.badge--pulse .badge__dot {
animation: pulse 2s ease infinite;
}
@keyframes pulse {
0%, 100% { opacity: 1; }
50% { opacity: 0.4; }
}
/* Tag */
.tag {
display: inline-flex;
align-items: center;
gap: var(--sp-2);
font-size: 12px;
padding: var(--sp-1) var(--sp-3);
background: var(--surface);
border: 1px solid var(--border);
border-radius: var(--radius-full);
transition: all var(--transition);
}
.tag:hover { border-color: var(--cyan); }
.tag--active {
background: var(--cyan);
border-color: var(--cyan);
color: var(--black);
}
.tag__remove {
width: 14px;
height: 14px;
display: flex;
align-items: center;
justify-content: center;
border-radius: var(--radius-full);
background: rgba(0, 0, 0, 0.2);
font-size: 10px;
cursor: pointer;
}
/* ─────────────────────────────────────────────────────────────────────────
9. AVATAR
───────────────────────────────────────────────────────────────────────── */
.avatar {
position: relative;
display: inline-flex;
align-items: center;
justify-content: center;
background: linear-gradient(135deg, var(--cyan), var(--magenta));
border-radius: var(--radius-full);
font-weight: 600;
color: var(--black);
flex-shrink: 0;
}
.avatar--xs { width: 24px; height: 24px; font-size: 10px; }
.avatar--sm { width: 32px; height: 32px; font-size: 12px; }
.avatar--md { width: 40px; height: 40px; font-size: 14px; }
.avatar--lg { width: 48px; height: 48px; font-size: 16px; }
.avatar--xl { width: 64px; height: 64px; font-size: 20px; }
.avatar--2xl { width: 96px; height: 96px; font-size: 28px; }
.avatar__image {
width: 100%;
height: 100%;
object-fit: cover;
border-radius: inherit;
}
.avatar__status {
position: absolute;
bottom: 0;
right: 0;
width: 25%;
height: 25%;
min-width: 8px;
min-height: 8px;
border-radius: var(--radius-full);
border: 2px solid var(--surface);
}
.avatar__status--online { background: var(--green); box-shadow: 0 0 8px var(--green-glow); }
.avatar__status--away { background: var(--yellow); }
.avatar__status--busy { background: var(--red); }
.avatar__status--offline { background: var(--text-muted); }
/* ─────────────────────────────────────────────────────────────────────────
10. AUDIO PLAYER — ADVANCED
───────────────────────────────────────────────────────────────────────── */
.player {
background: var(--surface);
border: 1px solid var(--border);
border-radius: var(--radius-xl);
overflow: hidden;
}
/* Player Header */
.player__header {
display: flex;
align-items: center;
gap: var(--sp-4);
padding: var(--sp-5);
border-bottom: 1px solid var(--border);
}
.player__artwork {
width: 80px;
height: 80px;
border-radius: var(--radius-md);
background: linear-gradient(135deg, var(--magenta), var(--orange));
display: flex;
align-items: center;
justify-content: center;
font-size: 32px;
flex-shrink: 0;
position: relative;
overflow: hidden;
}
.player__artwork::after {
content: "";
position: absolute;
inset: 0;
background: radial-gradient(circle at 30% 30%, rgba(255,255,255,0.2), transparent 60%);
}
.player__info { flex: 1; min-width: 0; }
.player__title {
font-size: 16px;
font-weight: 600;
margin-bottom: var(--sp-1);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.player__artist {
font-size: 13px;
color: var(--text-secondary);
margin-bottom: var(--sp-2);
}
.player__meta {
display: flex;
gap: var(--sp-3);
}
/* Waveform - Interactive */
.player__waveform {
padding: var(--sp-4) var(--sp-5);
background: var(--black-light);
}
.waveform {
display: flex;
align-items: center;
height: 64px;
gap: 2px;
cursor: pointer;
}
.waveform__bar {
flex: 1;
background: var(--border-light);
border-radius: 1px;
transition: background var(--transition-fast);
min-width: 2px;
}
.waveform__bar--played {
background: var(--cyan);
}
.waveform__bar--buffered {
background: var(--border-light);
opacity: 0.6;
}
.waveform:hover .waveform__bar {
opacity: 0.8;
}
.waveform:hover .waveform__bar--played {
opacity: 1;
background: var(--cyan);
box-shadow: 0 0 4px var(--cyan-glow);
}
/* Controls */
.player__controls {
display: flex;
align-items: center;
justify-content: space-between;
padding: var(--sp-4) var(--sp-5);
}
.player__controls-main {
display: flex;
align-items: center;
gap: var(--sp-3);
}
.player__btn {
width: 40px;
height: 40px;
display: flex;
align-items: center;
justify-content: center;
border-radius: var(--radius-full);
color: var(--text-secondary);
transition: all var(--transition);
}
.player__btn:hover {
color: var(--text);
background: var(--surface-light);
}
.player__btn--play {
width: 56px;
height: 56px;
background: var(--cyan);
color: var(--black);
font-size: 20px;
}
.player__btn--play:hover {
background: #fff;
transform: scale(1.05);
box-shadow: 0 0 30px var(--cyan-glow);
}
.player__btn--active {
color: var(--cyan);
}
/* Volume */
.player__volume {
display: flex;
align-items: center;
gap: var(--sp-2);
}
.volume-slider {
width: 80px;
height: 4px;
background: var(--border);
border-radius: var(--radius-full);
position: relative;
cursor: pointer;
}
.volume-slider__fill {
height: 100%;
background: var(--cyan);
border-radius: var(--radius-full);
}
.volume-slider__handle {
position: absolute;
top: 50%;
transform: translate(-50%, -50%);
width: 12px;
height: 12px;
background: var(--text);
border-radius: var(--radius-full);
opacity: 0;
transition: opacity var(--transition);
}
.volume-slider:hover .volume-slider__handle {
opacity: 1;
}
/* Time */
.player__time {
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 var(--sp-5) var(--sp-4);
font-family: var(--font-mono);
font-size: 11px;
color: var(--text-muted);
}
/* Equalizer */
.player__eq {
display: flex;
align-items: flex-end;
gap: 3px;
height: 20px;
padding: 0 var(--sp-2);
}
.eq-bar {
width: 3px;
background: var(--cyan);
border-radius: 1px;
animation: eq-bounce 0.8s ease infinite;
}
.eq-bar:nth-child(1) { animation-delay: 0s; height: 40%; }
.eq-bar:nth-child(2) { animation-delay: 0.1s; height: 70%; }
.eq-bar:nth-child(3) { animation-delay: 0.2s; height: 50%; }
.eq-bar:nth-child(4) { animation-delay: 0.3s; height: 90%; }
.eq-bar:nth-child(5) { animation-delay: 0.15s; height: 60%; }
@keyframes eq-bounce {
0%, 100% { transform: scaleY(1); }
50% { transform: scaleY(0.4); }
}
/* Queue */
.player__queue {
border-top: 1px solid var(--border);
max-height: 200px;
overflow-y: auto;
}
.queue-item {
display: flex;
align-items: center;
gap: var(--sp-3);
padding: var(--sp-3) var(--sp-5);
transition: background var(--transition);
cursor: pointer;
}
.queue-item:hover { background: var(--surface-light); }
.queue-item--active { background: var(--black-light); }
.queue-item__number {
font-family: var(--font-mono);
font-size: 11px;
color: var(--text-muted);
width: 20px;
}
.queue-item__artwork {
width: 36px;
height: 36px;
border-radius: var(--radius-sm);
background: var(--border);
}
.queue-item__info { flex: 1; min-width: 0; }
.queue-item__title {
font-size: 13px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.queue-item__artist {
font-size: 11px;
color: var(--text-muted);
}
.queue-item__duration {
font-family: var(--font-mono);
font-size: 11px;
color: var(--text-muted);
}
/* Mini Player */
.player--mini {
display: flex;
align-items: center;
gap: var(--sp-4);
padding: var(--sp-3) var(--sp-4);
border-radius: var(--radius-lg);
}
.player--mini .player__artwork {
width: 48px;
height: 48px;
font-size: 20px;
}
.player--mini .player__btn--play {
width: 40px;
height: 40px;
font-size: 16px;
}
.player--mini .player__progress {
flex: 1;
height: 4px;
background: var(--border);
border-radius: var(--radius-full);
overflow: hidden;
}
.player--mini .player__progress-fill {
height: 100%;
background: var(--cyan);
}
/* ─────────────────────────────────────────────────────────────────────────
11. LOADERS — ADVANCED
───────────────────────────────────────────────────────────────────────── */
/* === Spinner === */
.spinner {
display: inline-block;
border: 2px solid var(--border);
border-top-color: var(--cyan);
border-radius: var(--radius-full);
animation: spin 0.8s linear infinite;
}
.spinner--sm { width: 16px; height: 16px; }
.spinner--md { width: 24px; height: 24px; }
.spinner--lg { width: 32px; height: 32px; }
.spinner--xl { width: 48px; height: 48px; border-width: 3px; }
@keyframes spin { to { transform: rotate(360deg); } }
/* === Dots Loader === */
.loader-dots {
display: flex;
gap: var(--sp-2);
}
.loader-dots__dot {
width: 8px;
height: 8px;
background: var(--cyan);
border-radius: var(--radius-full);
animation: dots-bounce 1.4s ease-in-out infinite;
}
.loader-dots__dot:nth-child(1) { animation-delay: 0s; }
.loader-dots__dot:nth-child(2) { animation-delay: 0.16s; }
.loader-dots__dot:nth-child(3) { animation-delay: 0.32s; }
@keyframes dots-bounce {
0%, 80%, 100% { transform: scale(0.6); opacity: 0.5; }
40% { transform: scale(1); opacity: 1; }
}
/* === Bar Loader === */
.loader-bar {
width: 100%;
height: 4px;
background: var(--border);
border-radius: var(--radius-full);
overflow: hidden;
}
.loader-bar__fill {
height: 100%;
background: linear-gradient(90deg, var(--cyan), var(--magenta));
border-radius: var(--radius-full);
animation: bar-indeterminate 1.5s ease-in-out infinite;
transform-origin: left;
}
@keyframes bar-indeterminate {
0% { transform: translateX(-100%) scaleX(0.3); }
50% { transform: translateX(0%) scaleX(0.5); }
100% { transform: translateX(100%) scaleX(0.3); }
}
/* === Progress Bar (Determinate) === */
.progress-bar {
width: 100%;
height: 8px;
background: var(--surface);
border-radius: var(--radius-full);
overflow: hidden;
position: relative;
}
.progress-bar__fill {
height: 100%;
background: linear-gradient(90deg, var(--cyan), var(--green));
border-radius: var(--radius-full);
transition: width 0.3s ease;
position: relative;
}
.progress-bar__fill::after {
content: "";
position: absolute;
inset: 0;
background: linear-gradient(90deg, transparent, rgba(255,255,255,0.2), transparent);
animation: progress-shine 2s ease-in-out infinite;
}
@keyframes progress-shine {
0% { transform: translateX(-100%); }
100% { transform: translateX(100%); }
}
.progress-bar__label {
position: absolute;
right: var(--sp-2);
top: 50%;
transform: translateY(-50%);
font-family: var(--font-mono);
font-size: 10px;
color: var(--black);
font-weight: 600;
}
.progress-bar--lg { height: 16px; }
.progress-bar--lg .progress-bar__label { font-size: 11px; }
/* === Circular Progress === */
.progress-circle {
position: relative;
display: inline-flex;
align-items: center;
justify-content: center;
}
.progress-circle__svg {
transform: rotate(-90deg);
}
.progress-circle__bg {
fill: none;
stroke: var(--border);
}
.progress-circle__fill {
fill: none;
stroke: var(--cyan);
stroke-linecap: round;
transition: stroke-dashoffset 0.3s ease;
}
.progress-circle__label {
position: absolute;
font-family: var(--font-mono);
font-size: 14px;
font-weight: 600;
}
/* === Skeleton === */
.skeleton {
background: linear-gradient(90deg, var(--surface) 0%, var(--surface-light) 50%, var(--surface) 100%);
background-size: 200% 100%;
animation: skeleton-shimmer 1.5s ease-in-out infinite;
border-radius: var(--radius-md);
}
@keyframes skeleton-shimmer {
0% { background-position: 200% 0; }
100% { background-position: -200% 0; }
}
.skeleton--text { height: 14px; border-radius: var(--radius-sm); }
.skeleton--title { height: 20px; width: 60%; }
.skeleton--avatar { border-radius: var(--radius-full); }
.skeleton--card { border-radius: var(--radius-lg); }
/* === Glitch Loader === */
.loader-glitch {
font-family: var(--font-mono);
font-size: 14px;
color: var(--cyan);
position: relative;
}
.loader-glitch::before,
.loader-glitch::after {
content: attr(data-text);
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
.loader-glitch::before {
color: var(--magenta);
animation: glitch-1 2s infinite linear alternate-reverse;
clip-path: polygon(0 0, 100% 0, 100% 35%, 0 35%);
}
.loader-glitch::after {
color: var(--green);
animation: glitch-2 3s infinite linear alternate-reverse;
clip-path: polygon(0 65%, 100% 65%, 100% 100%, 0 100%);
}
@keyframes glitch-1 {
0%, 100% { transform: translate(0); }
20% { transform: translate(-2px, 1px); }
40% { transform: translate(2px, -1px); }
60% { transform: translate(-1px, 2px); }
80% { transform: translate(1px, -2px); }
}
@keyframes glitch-2 {
0%, 100% { transform: translate(0); }
20% { transform: translate(2px, -1px); }
40% { transform: translate(-2px, 1px); }
60% { transform: translate(1px, -2px); }
80% { transform: translate(-1px, 2px); }
}
/* === Pulse Loader === */
.loader-pulse {
width: 48px;
height: 48px;
position: relative;
}
.loader-pulse__ring {
position: absolute;
inset: 0;
border: 2px solid var(--cyan);
border-radius: var(--radius-full);
animation: pulse-ring 1.5s ease-out infinite;
}
.loader-pulse__ring:nth-child(2) { animation-delay: 0.5s; }
.loader-pulse__center {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 12px;
height: 12px;
background: var(--cyan);
border-radius: var(--radius-full);
}
@keyframes pulse-ring {
0% { transform: scale(0.5); opacity: 1; }
100% { transform: scale(1.5); opacity: 0; }
}
/* ─────────────────────────────────────────────────────────────────────────
12. CHAT
───────────────────────────────────────────────────────────────────────── */
.chat {
background: var(--surface);
border: 1px solid var(--border);
border-radius: var(--radius-lg);
display: flex;
flex-direction: column;
height: 400px;
}
.chat__header {
display: flex;
align-items: center;
justify-content: space-between;
padding: var(--sp-4) var(--sp-5);
border-bottom: 1px solid var(--border);
}
.chat__title {
display: flex;
align-items: center;
gap: var(--sp-2);
font-weight: 600;
}
.chat__messages {
flex: 1;
padding: var(--sp-4) var(--sp-5);
overflow-y: auto;
display: flex;
flex-direction: column;
gap: var(--sp-4);
}
/* Message */
.message {
display: flex;
gap: var(--sp-3);
max-width: 80%;
}
.message--sent {
flex-direction: row-reverse;
align-self: flex-end;
}
.message__avatar {
flex-shrink: 0;
}
.message__content {
display: flex;
flex-direction: column;
gap: var(--sp-1);
}
.message--sent .message__content {
align-items: flex-end;
}
.message__bubble {
padding: var(--sp-3) var(--sp-4);
border-radius: var(--radius-lg);
font-size: 13px;
line-height: 1.5;
}
.message--received .message__bubble {
background: var(--surface-light);
border-bottom-left-radius: var(--radius-sm);
}
.message--sent .message__bubble {
background: var(--cyan);
color: var(--black);
border-bottom-right-radius: var(--radius-sm);
}
.message__meta {
display: flex;
align-items: center;
gap: var(--sp-2);
font-size: 11px;
color: var(--text-muted);
}
/* Typing Indicator */
.typing {
display: flex;
align-items: center;
gap: var(--sp-2);
padding: var(--sp-2) var(--sp-3);
background: var(--surface-light);
border-radius: var(--radius-lg);
border-bottom-left-radius: var(--radius-sm);
width: fit-content;
}
.typing__dot {
width: 6px;
height: 6px;
background: var(--text-muted);
border-radius: var(--radius-full);
animation: typing 1.4s ease-in-out infinite;
}
.typing__dot:nth-child(2) { animation-delay: 0.2s; }
.typing__dot:nth-child(3) { animation-delay: 0.4s; }
@keyframes typing {
0%, 60%, 100% { transform: translateY(0); }
30% { transform: translateY(-4px); }
}
/* Chat Input */
.chat__input {
display: flex;
align-items: center;
gap: var(--sp-3);
padding: var(--sp-4) var(--sp-5);
border-top: 1px solid var(--border);
}
.chat__input .input {
flex: 1;
}
/* ─────────────────────────────────────────────────────────────────────────
13. MODAL
───────────────────────────────────────────────────────────────────────── */
.modal-overlay {
position: fixed;
inset: 0;
background: rgba(8, 8, 12, 0.9);
backdrop-filter: blur(8px);
display: flex;
align-items: center;
justify-content: center;
padding: var(--sp-6);
z-index: 1000;
animation: fade-in 0.2s ease;
}
@keyframes fade-in { from { opacity: 0; } }
.modal {
background: var(--surface);
border: 1px solid var(--border);
border-radius: var(--radius-xl);
width: 100%;
max-width: 480px;
max-height: 90vh;
overflow: hidden;
animation: modal-in 0.3s ease;
}
@keyframes modal-in {
from { opacity: 0; transform: scale(0.95) translateY(10px); }
}
.modal--lg { max-width: 640px; }
.modal--xl { max-width: 800px; }
.modal__header {
display: flex;
align-items: center;
justify-content: space-between;
padding: var(--sp-5) var(--sp-6);
border-bottom: 1px solid var(--border);
}
.modal__title {
font-size: 18px;
font-weight: 600;
}
.modal__close {
width: 32px;
height: 32px;
display: flex;
align-items: center;
justify-content: center;
border-radius: var(--radius-full);
color: var(--text-muted);
transition: all var(--transition);
}
.modal__close:hover {
background: var(--surface-light);
color: var(--text);
}
.modal__body {
padding: var(--sp-6);
overflow-y: auto;
}
.modal__footer {
display: flex;
justify-content: flex-end;
gap: var(--sp-3);
padding: var(--sp-4) var(--sp-6);
border-top: 1px solid var(--border);
background: var(--black-light);
}
/* ─────────────────────────────────────────────────────────────────────────
14. TOAST
───────────────────────────────────────────────────────────────────────── */
.toast-container {
position: fixed;
bottom: var(--sp-6);
right: var(--sp-6);
display: flex;
flex-direction: column;
gap: var(--sp-3);
z-index: 1100;
}
.toast {
display: flex;
align-items: flex-start;
gap: var(--sp-3);
padding: var(--sp-4);
background: var(--surface);
border: 1px solid var(--border);
border-radius: var(--radius-lg);
min-width: 320px;
max-width: 420px;
box-shadow: var(--shadow-lg);
animation: toast-in 0.3s ease;
}
@keyframes toast-in {
from { opacity: 0; transform: translateX(100%); }
}
.toast__icon {
width: 20px;
height: 20px;
flex-shrink: 0;
display: flex;
align-items: center;
justify-content: center;
border-radius: var(--radius-full);
font-size: 12px;
}
.toast--success .toast__icon { background: var(--green); color: var(--black); }
.toast--error .toast__icon { background: var(--red); color: #fff; }
.toast--warning .toast__icon { background: var(--yellow); color: var(--black); }
.toast--info .toast__icon { background: var(--cyan); color: var(--black); }
.toast__content { flex: 1; }
.toast__title {
font-size: 13px;
font-weight: 600;
margin-bottom: var(--sp-1);
}
.toast__message {
font-size: 12px;
color: var(--text-secondary);
}
.toast__close {
color: var(--text-muted);
padding: var(--sp-1);
}
.toast__close:hover { color: var(--text); }
.toast__progress {
position: absolute;
bottom: 0;
left: 0;
height: 2px;
background: var(--cyan);
animation: toast-progress 5s linear forwards;
}
@keyframes toast-progress { to { width: 0; } }
/* ─────────────────────────────────────────────────────────────────────────
15. TABS
───────────────────────────────────────────────────────────────────────── */
.tabs {
display: flex;
flex-direction: column;
gap: var(--sp-6);
}
.tabs__list {
display: flex;
gap: var(--sp-1);
border-bottom: 1px solid var(--border);
}
.tabs__trigger {
padding: var(--sp-3) var(--sp-5);
font-size: 13px;
font-weight: 500;
color: var(--text-secondary);
border-bottom: 2px solid transparent;
margin-bottom: -1px;
transition: all var(--transition);
}
.tabs__trigger:hover {
color: var(--text);
}
.tabs__trigger--active {
color: var(--cyan);
border-bottom-color: var(--cyan);
}
.tabs__panel {
animation: fade-in 0.2s ease;
}
/* ─────────────────────────────────────────────────────────────────────────
16. TABLE
───────────────────────────────────────────────────────────────────────── */
.table-container {
overflow-x: auto;
border: 1px solid var(--border);
border-radius: var(--radius-lg);
}
.table {
width: 100%;
border-collapse: collapse;
}
.table th,
.table td {
padding: var(--sp-4);
text-align: left;
}
.table th {
font-family: var(--font-mono);
font-size: 11px;
font-weight: 500;
text-transform: uppercase;
letter-spacing: 0.05em;
color: var(--text-muted);
background: var(--surface);
border-bottom: 1px solid var(--border);
}
.table td {
font-size: 13px;
border-bottom: 1px solid var(--border);
}
.table tbody tr {
transition: background var(--transition);
}
.table tbody tr:hover {
background: var(--surface);
}
.table tbody tr:last-child td {
border-bottom: none;
}
/* ─────────────────────────────────────────────────────────────────────────
17. SECTIONS
───────────────────────────────────────────────────────────────────────── */
.section {
padding: var(--sp-16) 0;
}
.section__header {
margin-bottom: var(--sp-10);
}
.section__label {
font-family: var(--font-mono);
font-size: 11px;
color: var(--cyan);
text-transform: uppercase;
letter-spacing: 0.1em;
margin-bottom: var(--sp-2);
}
.section__title {
font-family: var(--font-display);
font-size: clamp(2rem, 4vw, 3rem);
letter-spacing: 0.02em;
margin-bottom: var(--sp-3);
}
.section__description {
font-size: 15px;
color: var(--text-secondary);
max-width: 600px;
}
/* Component Preview Box */
.preview-box {
background: var(--black-light);
border: 1px solid var(--border);
border-radius: var(--radius-lg);
padding: var(--sp-6);
}
.preview-box__label {
font-family: var(--font-mono);
font-size: 10px;
color: var(--text-muted);
text-transform: uppercase;
letter-spacing: 0.1em;
margin-bottom: var(--sp-4);
}
.preview-box__content {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: var(--sp-4);
}
.preview-box__content--col {
flex-direction: column;
align-items: stretch;
}
/* ─────────────────────────────────────────────────────────────────────────
18. HERO
───────────────────────────────────────────────────────────────────────── */
.hero {
padding: var(--sp-20) 0;
position: relative;
}
.hero__badge {
display: inline-flex;
align-items: center;
gap: var(--sp-2);
padding: var(--sp-2) var(--sp-4);
background: var(--surface);
border: 1px solid var(--border);
border-radius: var(--radius-full);
font-family: var(--font-mono);
font-size: 12px;
margin-bottom: var(--sp-6);
}
.hero__badge-dot {
width: 6px;
height: 6px;
background: var(--green);
border-radius: var(--radius-full);
animation: pulse 2s infinite;
}
.hero__title {
font-family: var(--font-display);
font-size: clamp(3rem, 8vw, 6rem);
letter-spacing: 0.02em;
line-height: 1;
margin-bottom: var(--sp-6);
}
.hero__title span {
display: block;
}
.hero__title .line-1 { color: var(--cyan); }
.hero__title .line-2 { color: var(--magenta); }
.hero__title .line-3 { color: var(--text); }
.hero__description {
font-size: 18px;
color: var(--text-secondary);
max-width: 500px;
margin-bottom: var(--sp-8);
line-height: 1.7;
}
.hero__actions {
display: flex;
flex-wrap: wrap;
gap: var(--sp-4);
margin-bottom: var(--sp-12);
}
.hero__stats {
display: flex;
gap: var(--sp-10);
}
.hero__stat {
display: flex;
flex-direction: column;
}
.hero__stat-value {
font-family: var(--font-display);
font-size: 2.5rem;
color: var(--cyan);
}
.hero__stat-label {
font-family: var(--font-mono);
font-size: 11px;
color: var(--text-muted);
text-transform: uppercase;
letter-spacing: 0.05em;
}
/* ─────────────────────────────────────────────────────────────────────────
19. FOOTER
───────────────────────────────────────────────────────────────────────── */
.footer {
padding: var(--sp-8) 0;
border-top: 1px solid var(--border);
}
.footer__inner {
display: flex;
align-items: center;
justify-content: space-between;
flex-wrap: wrap;
gap: var(--sp-4);
}
.footer__copy {
font-family: var(--font-mono);
font-size: 12px;
color: var(--text-muted);
}
.footer__links {
display: flex;
gap: var(--sp-6);
font-size: 12px;
color: var(--text-muted);
}
.footer__links span::before {
content: "•";
margin-right: var(--sp-2);
color: var(--cyan);
}
/* ─────────────────────────────────────────────────────────────────────────
20. COLOR SWATCHES
───────────────────────────────────────────────────────────────────────── */
.swatch {
display: flex;
flex-direction: column;
overflow: hidden;
border-radius: var(--radius-lg);
border: 1px solid var(--border);
}
.swatch__color {
height: 80px;
}
.swatch__info {
padding: var(--sp-3);
background: var(--surface);
}
.swatch__name {
font-size: 12px;
font-weight: 600;
margin-bottom: var(--sp-1);
}
.swatch__value {
font-family: var(--font-mono);
font-size: 11px;
color: var(--text-muted);
}
/* ─────────────────────────────────────────────────────────────────────────
21. UTILITIES
───────────────────────────────────────────────────────────────────────── */
.flex { display: flex; }
.flex-col { flex-direction: column; }
.items-center { align-items: center; }
.items-start { align-items: flex-start; }
.justify-between { justify-content: space-between; }
.justify-center { justify-content: center; }
.gap-2 { gap: var(--sp-2); }
.gap-3 { gap: var(--sp-3); }
.gap-4 { gap: var(--sp-4); }
.gap-6 { gap: var(--sp-6); }
.gap-8 { gap: var(--sp-8); }
.mt-2 { margin-top: var(--sp-2); }
.mt-4 { margin-top: var(--sp-4); }
.mt-6 { margin-top: var(--sp-6); }
.mt-8 { margin-top: var(--sp-8); }
.mb-4 { margin-bottom: var(--sp-4); }
.mb-6 { margin-bottom: var(--sp-6); }
.text-cyan { color: var(--cyan); }
.text-magenta { color: var(--magenta); }
.text-green { color: var(--green); }
.text-muted { color: var(--text-muted); }
@media (max-width: 768px) {
.hero__title { font-size: 2.5rem; }
.hero__stats { flex-direction: column; gap: var(--sp-6); }
.nav { display: none; }
}
</style>
</head>
<body>
<div class="page">
<!-- HEADER -->
<header class="header">
<div class="container">
<div class="header__inner">
<a href="#" class="brand">
<div class="brand__icon"></div>
<div class="brand__text">
<span>VEZA</span><span>×TALAS</span>
</div>
</a>
<nav class="nav">
<a href="#tokens" class="nav__link nav__link--active">Tokens</a>
<a href="#components" class="nav__link">Components</a>
<a href="#loaders" class="nav__link">Loaders</a>
<a href="#player" class="nav__link">Audio</a>
<a href="#chat" class="nav__link">Chat</a>
</nav>
<button class="btn btn--primary btn--sm">Get Started</button>
</div>
</div>
</header>
<main>
<!-- HERO -->
<section class="hero">
<div class="container">
<div class="hero__badge">
<span class="hero__badge-dot"></span>
<span>Design System v4.0</span>
</div>
<h1 class="hero__title">
<span class="line-1">NEON</span>
<span class="line-2">REFINED</span>
<span class="line-3">DESIGN</span>
</h1>
<p class="hero__description">
Un système de design épuré et cohérent. L'essence du style urbain-tech
distillée en composants production-ready.
</p>
<div class="hero__actions">
<button class="btn btn--primary btn--lg">Explorer</button>
<button class="btn btn--secondary btn--lg">Documentation</button>
</div>
<div class="hero__stats">
<div class="hero__stat">
<span class="hero__stat-value">250+</span>
<span class="hero__stat-label">Components</span>
</div>
<div class="hero__stat">
<span class="hero__stat-value">AAA</span>
<span class="hero__stat-label">WCAG</span>
</div>
<div class="hero__stat">
<span class="hero__stat-value">60fps</span>
<span class="hero__stat-label">Animations</span>
</div>
</div>
</div>
</section>
<!-- TOKENS -->
<section id="tokens" class="section">
<div class="container">
<div class="section__header">
<div class="section__label">01 / Design Tokens</div>
<h2 class="section__title">Color System</h2>
<p class="section__description">
Une palette néon raffinée pour des interfaces qui se démarquent tout en restant lisibles.
</p>
</div>
<div class="grid grid-4">
<div class="swatch">
<div class="swatch__color" style="background: #00e5ff;"></div>
<div class="swatch__info">
<div class="swatch__name">Cyan</div>
<div class="swatch__value">#00e5ff</div>
</div>
</div>
<div class="swatch">
<div class="swatch__color" style="background: #ff0080;"></div>
<div class="swatch__info">
<div class="swatch__name">Magenta</div>
<div class="swatch__value">#ff0080</div>
</div>
</div>
<div class="swatch">
<div class="swatch__color" style="background: #00ff88;"></div>
<div class="swatch__info">
<div class="swatch__name">Green</div>
<div class="swatch__value">#00ff88</div>
</div>
</div>
<div class="swatch">
<div class="swatch__color" style="background: #ff6600;"></div>
<div class="swatch__info">
<div class="swatch__name">Orange</div>
<div class="swatch__value">#ff6600</div>
</div>
</div>
<div class="swatch">
<div class="swatch__color" style="background: #08080c;"></div>
<div class="swatch__info">
<div class="swatch__name">Black</div>
<div class="swatch__value">#08080c</div>
</div>
</div>
<div class="swatch">
<div class="swatch__color" style="background: #14141c;"></div>
<div class="swatch__info">
<div class="swatch__name">Surface</div>
<div class="swatch__value">#14141c</div>
</div>
</div>
<div class="swatch">
<div class="swatch__color" style="background: #f0f0f5;"></div>
<div class="swatch__info">
<div class="swatch__name">Text</div>
<div class="swatch__value">#f0f0f5</div>
</div>
</div>
<div class="swatch">
<div class="swatch__color" style="background: linear-gradient(135deg, #00e5ff, #ff0080);"></div>
<div class="swatch__info">
<div class="swatch__name">Gradient</div>
<div class="swatch__value">Cyan → Magenta</div>
</div>
</div>
</div>
</div>
</section>
<!-- COMPONENTS -->
<section id="components" class="section">
<div class="container">
<div class="section__header">
<div class="section__label">02 / Components</div>
<h2 class="section__title">UI Elements</h2>
<p class="section__description">
Des composants essentiels, raffinés et prêts pour la production.
</p>
</div>
<div class="grid grid-2">
<!-- Buttons -->
<div class="preview-box">
<div class="preview-box__label">Buttons</div>
<div class="preview-box__content">
<button class="btn btn--primary">Primary</button>
<button class="btn btn--secondary">Secondary</button>
<button class="btn btn--ghost">Ghost</button>
<button class="btn btn--danger">Danger</button>
<button class="btn btn--magenta">Magenta</button>
</div>
<div class="preview-box__content mt-4">
<button class="btn btn--primary btn--sm">Small</button>
<button class="btn btn--primary">Medium</button>
<button class="btn btn--primary btn--lg">Large</button>
<button class="btn btn--primary btn--icon">+</button>
</div>
</div>
<!-- Badges -->
<div class="preview-box">
<div class="preview-box__label">Badges & Tags</div>
<div class="preview-box__content">
<span class="badge badge--default">Default</span>
<span class="badge badge--cyan"><span class="badge__dot"></span>Cyan</span>
<span class="badge badge--magenta">Magenta</span>
<span class="badge badge--green badge--pulse"><span class="badge__dot"></span>Live</span>
<span class="badge badge--orange">Warning</span>
<span class="badge badge--red">Error</span>
</div>
<div class="preview-box__content mt-4">
<span class="tag">Tag</span>
<span class="tag tag--active">Active</span>
<span class="tag">With Remove<span class="tag__remove">×</span></span>
</div>
</div>
<!-- Inputs -->
<div class="preview-box">
<div class="preview-box__label">Form Inputs</div>
<div class="preview-box__content preview-box__content--col">
<div class="form-group">
<label class="label">Username</label>
<input type="text" class="input" placeholder="Enter username...">
</div>
<div class="form-group">
<label class="label">With Error</label>
<input type="text" class="input input--error" value="Invalid value">
<span class="input-message input-message--error">✕ This field is required</span>
</div>
<div class="form-group">
<label class="label">Success</label>
<input type="text" class="input input--success" value="Valid input">
<span class="input-message input-message--success">✓ Looks good!</span>
</div>
</div>
</div>
<!-- Avatars -->
<div class="preview-box">
<div class="preview-box__label">Avatars</div>
<div class="preview-box__content">
<div class="avatar avatar--xs">V</div>
<div class="avatar avatar--sm">V</div>
<div class="avatar avatar--md">V</div>
<div class="avatar avatar--lg">
V
<span class="avatar__status avatar__status--online"></span>
</div>
<div class="avatar avatar--xl">
T
<span class="avatar__status avatar__status--away"></span>
</div>
<div class="avatar avatar--2xl">
N
<span class="avatar__status avatar__status--busy"></span>
</div>
</div>
</div>
<!-- Cards -->
<div class="preview-box">
<div class="preview-box__label">Cards</div>
<div class="preview-box__content preview-box__content--col">
<div class="card card--glow-cyan card--interactive">
<div class="card__header">
<span class="card__title">Card Title</span>
<span class="badge badge--cyan">New</span>
</div>
<div class="card__body">
<p class="text-muted">Card body content with description text.</p>
</div>
</div>
</div>
</div>
<!-- Toast -->
<div class="preview-box">
<div class="preview-box__label">Toast Notifications</div>
<div class="preview-box__content preview-box__content--col gap-3">
<div class="toast toast--success" style="position: relative; animation: none;">
<span class="toast__icon"></span>
<div class="toast__content">
<div class="toast__title">Success</div>
<div class="toast__message">Your changes have been saved.</div>
</div>
</div>
<div class="toast toast--error" style="position: relative; animation: none;">
<span class="toast__icon"></span>
<div class="toast__content">
<div class="toast__title">Error</div>
<div class="toast__message">Something went wrong.</div>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
<!-- LOADERS -->
<section id="loaders" class="section">
<div class="container">
<div class="section__header">
<div class="section__label">03 / Loaders</div>
<h2 class="section__title">Loading States</h2>
<p class="section__description">
Des indicateurs de chargement variés pour chaque situation.
</p>
</div>
<div class="grid grid-3">
<!-- Spinner -->
<div class="preview-box">
<div class="preview-box__label">Spinners</div>
<div class="preview-box__content">
<div class="spinner spinner--sm"></div>
<div class="spinner spinner--md"></div>
<div class="spinner spinner--lg"></div>
<div class="spinner spinner--xl"></div>
</div>
</div>
<!-- Dots -->
<div class="preview-box">
<div class="preview-box__label">Dots Loader</div>
<div class="preview-box__content justify-center">
<div class="loader-dots">
<span class="loader-dots__dot"></span>
<span class="loader-dots__dot"></span>
<span class="loader-dots__dot"></span>
</div>
</div>
</div>
<!-- Pulse -->
<div class="preview-box">
<div class="preview-box__label">Pulse Loader</div>
<div class="preview-box__content justify-center">
<div class="loader-pulse">
<div class="loader-pulse__ring"></div>
<div class="loader-pulse__ring"></div>
<div class="loader-pulse__center"></div>
</div>
</div>
</div>
<!-- Bar -->
<div class="preview-box">
<div class="preview-box__label">Indeterminate Bar</div>
<div class="preview-box__content preview-box__content--col">
<div class="loader-bar">
<div class="loader-bar__fill"></div>
</div>
</div>
</div>
<!-- Progress -->
<div class="preview-box">
<div class="preview-box__label">Progress Bar</div>
<div class="preview-box__content preview-box__content--col gap-4">
<div class="progress-bar">
<div class="progress-bar__fill" style="width: 35%;"></div>
</div>
<div class="progress-bar">
<div class="progress-bar__fill" style="width: 68%;"></div>
</div>
<div class="progress-bar progress-bar--lg">
<div class="progress-bar__fill" style="width: 85%;">
<span class="progress-bar__label">85%</span>
</div>
</div>
</div>
</div>
<!-- Circular -->
<div class="preview-box">
<div class="preview-box__label">Circular Progress</div>
<div class="preview-box__content justify-center">
<div class="progress-circle">
<svg class="progress-circle__svg" width="80" height="80">
<circle class="progress-circle__bg" cx="40" cy="40" r="34" stroke-width="6"/>
<circle class="progress-circle__fill" cx="40" cy="40" r="34" stroke-width="6"
stroke-dasharray="213.6" stroke-dashoffset="64"/>
</svg>
<span class="progress-circle__label text-cyan">70%</span>
</div>
</div>
</div>
<!-- Glitch -->
<div class="preview-box">
<div class="preview-box__label">Glitch Text</div>
<div class="preview-box__content justify-center">
<span class="loader-glitch" data-text="LOADING...">LOADING...</span>
</div>
</div>
<!-- Skeleton -->
<div class="preview-box" style="grid-column: span 2;">
<div class="preview-box__label">Skeleton Loaders</div>
<div class="preview-box__content">
<div class="flex gap-4 items-start" style="width: 100%;">
<div class="skeleton skeleton--avatar" style="width: 48px; height: 48px;"></div>
<div class="flex-col gap-2" style="flex: 1;">
<div class="skeleton skeleton--title"></div>
<div class="skeleton skeleton--text" style="width: 80%;"></div>
<div class="skeleton skeleton--text" style="width: 60%;"></div>
</div>
</div>
<div class="skeleton skeleton--card" style="width: 200px; height: 120px;"></div>
</div>
</div>
</div>
</div>
</section>
<!-- AUDIO PLAYER -->
<section id="player" class="section">
<div class="container">
<div class="section__header">
<div class="section__label">04 / Audio Player</div>
<h2 class="section__title">Advanced Player</h2>
<p class="section__description">
Un lecteur audio complet avec waveform interactive, queue et equalizer.
</p>
</div>
<div class="grid grid-2">
<!-- Full Player -->
<div class="player">
<div class="player__header">
<div class="player__artwork"></div>
<div class="player__info">
<div class="player__title">Neon Streets</div>
<div class="player__artist">CyberWave • 2024</div>
<div class="player__meta">
<span class="badge badge--cyan"><span class="badge__dot"></span>HQ</span>
<span class="badge badge--default">320kbps</span>
</div>
</div>
<div class="player__eq">
<div class="eq-bar"></div>
<div class="eq-bar"></div>
<div class="eq-bar"></div>
<div class="eq-bar"></div>
<div class="eq-bar"></div>
</div>
</div>
<div class="player__waveform">
<div class="waveform" id="waveform">
<!-- Generated by JS -->
</div>
</div>
<div class="player__time">
<span>1:24</span>
<span>3:45</span>
</div>
<div class="player__controls">
<div class="player__controls-main">
<button class="player__btn"></button>
<button class="player__btn"></button>
<button class="player__btn player__btn--play"></button>
<button class="player__btn"></button>
<button class="player__btn player__btn--active"></button>
</div>
<div class="player__volume">
<button class="player__btn btn--sm">🔊</button>
<div class="volume-slider">
<div class="volume-slider__fill" style="width: 70%;"></div>
<div class="volume-slider__handle" style="left: 70%;"></div>
</div>
</div>
</div>
<div class="player__queue">
<div class="queue-item queue-item--active">
<span class="queue-item__number">1</span>
<div class="queue-item__artwork" style="background: linear-gradient(135deg, var(--magenta), var(--orange));"></div>
<div class="queue-item__info">
<div class="queue-item__title">Neon Streets</div>
<div class="queue-item__artist">CyberWave</div>
</div>
<span class="queue-item__duration">3:45</span>
</div>
<div class="queue-item">
<span class="queue-item__number">2</span>
<div class="queue-item__artwork" style="background: linear-gradient(135deg, var(--cyan), var(--green));"></div>
<div class="queue-item__info">
<div class="queue-item__title">Digital Dreams</div>
<div class="queue-item__artist">SynthMaster</div>
</div>
<span class="queue-item__duration">4:12</span>
</div>
<div class="queue-item">
<span class="queue-item__number">3</span>
<div class="queue-item__artwork" style="background: linear-gradient(135deg, var(--orange), var(--yellow));"></div>
<div class="queue-item__info">
<div class="queue-item__title">Midnight Run</div>
<div class="queue-item__artist">NightDriver</div>
</div>
<span class="queue-item__duration">3:28</span>
</div>
</div>
</div>
<!-- Mini Players -->
<div class="flex-col gap-6">
<div class="preview-box">
<div class="preview-box__label">Mini Player</div>
<div class="player player--mini">
<div class="player__artwork"></div>
<div class="player__info" style="flex: 0 0 auto;">
<div class="player__title" style="font-size: 13px;">Neon Streets</div>
<div class="player__artist" style="font-size: 11px;">CyberWave</div>
</div>
<div class="player__progress">
<div class="player__progress-fill" style="width: 35%;"></div>
</div>
<button class="player__btn player__btn--play"></button>
</div>
</div>
<div class="preview-box">
<div class="preview-box__label">Compact Controls</div>
<div class="preview-box__content">
<button class="player__btn"></button>
<button class="player__btn player__btn--play" style="width: 48px; height: 48px;"></button>
<button class="player__btn"></button>
<button class="player__btn"></button>
<button class="player__btn player__btn--active"></button>
<button class="player__btn"></button>
</div>
</div>
<div class="preview-box">
<div class="preview-box__label">Volume Controls</div>
<div class="preview-box__content flex-col gap-4">
<div class="player__volume" style="width: 100%;">
<button class="player__btn btn--sm">🔇</button>
<div class="volume-slider" style="flex: 1;">
<div class="volume-slider__fill" style="width: 0%;"></div>
</div>
</div>
<div class="player__volume" style="width: 100%;">
<button class="player__btn btn--sm">🔈</button>
<div class="volume-slider" style="flex: 1;">
<div class="volume-slider__fill" style="width: 30%;"></div>
</div>
</div>
<div class="player__volume" style="width: 100%;">
<button class="player__btn btn--sm">🔊</button>
<div class="volume-slider" style="flex: 1;">
<div class="volume-slider__fill" style="width: 100%;"></div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
<!-- CHAT -->
<section id="chat" class="section">
<div class="container">
<div class="section__header">
<div class="section__label">05 / Chat</div>
<h2 class="section__title">Messaging</h2>
<p class="section__description">
Interface de chat moderne et épurée.
</p>
</div>
<div class="grid grid-2">
<div class="chat">
<div class="chat__header">
<div class="chat__title">
<span class="text-cyan">#</span>
general
</div>
<span class="badge badge--green badge--pulse"><span class="badge__dot"></span>3 online</span>
</div>
<div class="chat__messages">
<div class="message message--received">
<div class="avatar avatar--sm message__avatar">N</div>
<div class="message__content">
<div class="message__bubble">Hey! Le nouveau pack de samples est dispo 🔥</div>
<div class="message__meta">
<span>NeonBeats</span>
<span>14:32</span>
</div>
</div>
</div>
<div class="message message--received">
<div class="avatar avatar--sm message__avatar">C</div>
<div class="message__content">
<div class="message__bubble">Nice! Les kicks sont vraiment massifs cette fois</div>
<div class="message__meta">
<span>CyberWave</span>
<span>14:33</span>
</div>
</div>
</div>
<div class="message message--sent">
<div class="message__content">
<div class="message__bubble">Je teste ça tout de suite, vous avez le link?</div>
<div class="message__meta">
<span>Sent</span>
<span>14:34</span>
</div>
</div>
</div>
<div class="message message--received">
<div class="avatar avatar--sm message__avatar">N</div>
<div class="message__content">
<div class="typing">
<span class="typing__dot"></span>
<span class="typing__dot"></span>
<span class="typing__dot"></span>
</div>
</div>
</div>
</div>
<div class="chat__input">
<input type="text" class="input" placeholder="Type a message...">
<button class="btn btn--primary btn--icon"></button>
</div>
</div>
<!-- Chat Components -->
<div class="flex-col gap-6">
<div class="preview-box">
<div class="preview-box__label">Message States</div>
<div class="preview-box__content preview-box__content--col gap-3">
<div class="message message--received" style="max-width: 100%;">
<div class="avatar avatar--sm message__avatar">U</div>
<div class="message__content">
<div class="message__bubble">Received message</div>
</div>
</div>
<div class="message message--sent" style="max-width: 100%;">
<div class="message__content">
<div class="message__bubble">Sent message</div>
</div>
</div>
</div>
</div>
<div class="preview-box">
<div class="preview-box__label">Typing Indicator</div>
<div class="preview-box__content">
<div class="typing">
<span class="typing__dot"></span>
<span class="typing__dot"></span>
<span class="typing__dot"></span>
</div>
</div>
</div>
<div class="preview-box">
<div class="preview-box__label">Online Status</div>
<div class="preview-box__content gap-6">
<div class="flex items-center gap-2">
<div class="avatar avatar--md">
U
<span class="avatar__status avatar__status--online"></span>
</div>
<span>Online</span>
</div>
<div class="flex items-center gap-2">
<div class="avatar avatar--md">
U
<span class="avatar__status avatar__status--away"></span>
</div>
<span>Away</span>
</div>
<div class="flex items-center gap-2">
<div class="avatar avatar--md">
U
<span class="avatar__status avatar__status--busy"></span>
</div>
<span>Busy</span>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
</main>
<!-- FOOTER -->
<footer class="footer">
<div class="container">
<div class="footer__inner">
<div class="footer__copy">© 2025 VEZA × TALAS — Design System v4.0</div>
<div class="footer__links">
<span>Dark Mode</span>
<span>WCAG AAA</span>
<span>Production Ready</span>
</div>
</div>
</div>
</footer>
</div>
<script>
// Generate waveform bars
const waveform = document.getElementById('waveform');
const barCount = 80;
const playedBars = 25;
for (let i = 0; i < barCount; i++) {
const bar = document.createElement('div');
bar.className = 'waveform__bar';
if (i < playedBars) bar.classList.add('waveform__bar--played');
// Random height with some pattern
const baseHeight = 20 + Math.random() * 60;
const variation = Math.sin(i * 0.3) * 15;
bar.style.height = `${Math.max(10, baseHeight + variation)}%`;
waveform.appendChild(bar);
}
// Interactive waveform
waveform.addEventListener('click', (e) => {
const rect = waveform.getBoundingClientRect();
const clickX = e.clientX - rect.left;
const percentage = clickX / rect.width;
const newPlayedBars = Math.floor(barCount * percentage);
document.querySelectorAll('.waveform__bar').forEach((bar, i) => {
if (i < newPlayedBars) {
bar.classList.add('waveform__bar--played');
} else {
bar.classList.remove('waveform__bar--played');
}
});
});
// Smooth scroll
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
anchor.addEventListener('click', function(e) {
e.preventDefault();
const target = document.querySelector(this.getAttribute('href'));
if (target) {
target.scrollIntoView({ behavior: 'smooth', block: 'start' });
}
});
});
</script>
</body>
</html>