website_designs

Glitch Art Design Reference

Glitch Art is a digital aesthetic rooted in the deliberate exploitation of technological errors, data corruption, and signal malfunction to produce visually striking compositions. Emerging from net art and new media art communities in the mid-2000s – with theoretical grounding established by Rosa Menkman’s Glitch Studies Manifesto (2010) and The Glitch Moment(um) (2011) – it celebrates the beauty found in broken data, pixel sorting, datamoshing, and RGB channel separation. Predecessors include early video feedback experiments and data-bent photography, but the movement crystallized as a distinct genre around 2006-2009, accelerated by social sharing and DIY datamoshing tutorials. In web and UI design, Glitch Art translates to RGB split text effects, scan line overlays, noise grain textures, corrupted grid layouts, distorted imagery, and animations that simulate signal interference. The core philosophy treats the glitch not as failure but as revelation – exposing the hidden mechanics of digital systems and challenging the assumption that technology should always appear seamless and polished.


Visual Characteristics

Core Design Traits

Design Principles


Color Palette

Glitch Art palettes draw from the RGB color model itself – the raw channels of digital displays – combined with neon accents that evoke CRT phosphors, VHS artifacts, and corrupted data streams. Deep black backgrounds maximize the luminosity of channel-split colors.

Color Name Hex Role / Usage
Void Black #0D0D0D Primary background, deepest canvas surface
Screen Dark #1A1A2E Secondary background, dark panels with subtle blue cast
Static Gray #2A2A2A Tertiary surfaces, noise texture base
Channel Red #FF0040 RGB red channel, primary split offset color
Channel Green #00FF41 RGB green channel, terminal/matrix accent
Channel Blue #0080FF RGB blue channel, secondary split offset color
Glitch Cyan #00FFFF High-energy accent, scan line tint, hyperlinks
Glitch Magenta #FF00FF High-energy accent, chromatic aberration highlight
Corrupt Pink #FF2E97 Hot accent for buttons, alert states, key UI elements
Signal Yellow #F5F500 Warning accents, data highlight, hover state feedback
Data White #E0E0E0 Primary text, readable body content
Phosphor White #FFFFFF Display headings, maximum-contrast elements
Artifact Purple #7B2FBE Decorative gradients, secondary data visualization
Noise Mid #444444 Muted borders, disabled states, subtle separators
Codec Orange #FF6B2B Tertiary accent, compression artifact visualization

CSS Custom Properties

:root {
  /* Backgrounds */
  --glitch-void: #0d0d0d;
  --glitch-screen-dark: #1a1a2e;
  --glitch-static-gray: #2a2a2a;

  /* RGB Channels */
  --glitch-red: #ff0040;
  --glitch-green: #00ff41;
  --glitch-blue: #0080ff;

  /* Neon Accents */
  --glitch-cyan: #00ffff;
  --glitch-magenta: #ff00ff;
  --glitch-pink: #ff2e97;
  --glitch-yellow: #f5f500;
  --glitch-purple: #7b2fbe;
  --glitch-orange: #ff6b2b;

  /* Neutrals */
  --glitch-white: #ffffff;
  --glitch-text: #e0e0e0;
  --glitch-muted: #444444;

  /* Functional Tokens */
  --glitch-bg: var(--glitch-void);
  --glitch-surface: var(--glitch-screen-dark);
  --glitch-border: var(--glitch-muted);
  --glitch-accent: var(--glitch-cyan);
  --glitch-accent-alt: var(--glitch-pink);
  --glitch-link: var(--glitch-cyan);
  --glitch-link-hover: var(--glitch-magenta);
}

Typography

Glitch Art typography favors monospaced, technical, and geometric typefaces that reference code editors, terminal displays, and early computing. Display text is often treated as a surface for corruption effects – split, distorted, and layered – while body text prioritizes legibility against noisy backgrounds.

Font Weight(s) Usage Link
Share Tech Mono 400 Body text, data displays, code-like content fonts.google.com/specimen/Share+Tech+Mono
VT323 400 Display text, retro terminal headings, pixel-style accents fonts.google.com/specimen/VT323
Space Mono 400, 700 Body text, UI labels, technical content fonts.google.com/specimen/Space+Mono
Orbitron 400, 500, 700, 900 Headlines, display text, futuristic titles fonts.google.com/specimen/Orbitron
IBM Plex Mono 400, 500, 700 Body text, metadata, system-inspired interfaces fonts.google.com/specimen/IBM+Plex+Mono
Press Start 2P 400 Pixel-art accents, retro labels, 8-bit references fonts.google.com/specimen/Press+Start+2P
Major Mono Display 400 Display headlines, abstract title treatments fonts.google.com/specimen/Major+Mono+Display
Russo One 400 Bold geometric headlines, impactful display text fonts.google.com/specimen/Russo+One

Font Pairing Suggestions

Heading Body Vibe
Orbitron (700) Share Tech Mono Futuristic authority meets clean terminal readability; ideal for tech-forward glitch layouts
Russo One IBM Plex Mono Bold geometric impact paired with professional monospace; balances chaos with legibility
VT323 Space Mono Retro pixel nostalgia meets modern monospace precision; perfect for CRT-inspired interfaces
Major Mono Display Share Tech Mono Abstract, deconstructed headlines with grounded technical body text; maximizes the digital-error feel
Orbitron (900) IBM Plex Mono (400) Heavy futuristic display with readable IBM technical prose; suitable for data-driven glitch dashboards

CSS Example

@import url('https://fonts.googleapis.com/css2?family=Orbitron:wght@400;700;900&family=Share+Tech+Mono&family=VT323&display=swap');

/* === Base Typography === */
body {
  font-family: 'Share Tech Mono', 'Courier New', Courier, monospace;
  font-size: 16px;
  line-height: 1.7;
  color: var(--glitch-text);
  background-color: var(--glitch-bg);
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4, h5, h6 {
  font-family: 'Orbitron', 'Arial Black', sans-serif;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  line-height: 1.1;
  color: var(--glitch-white);
  margin: 0 0 0.5em 0;
}

h1 {
  font-size: clamp(2.5rem, 7vw, 6rem);
  font-weight: 900;
}

h2 {
  font-size: clamp(1.8rem, 4vw, 3rem);
  font-weight: 700;
}

h3 {
  font-size: clamp(1.2rem, 2.5vw, 1.8rem);
  font-weight: 700;
}

a {
  color: var(--glitch-link);
  text-decoration: none;
  border-bottom: 1px solid transparent;
  transition: color 0.15s ease, border-color 0.15s ease;
}

a:hover {
  color: var(--glitch-link-hover);
  border-bottom-color: var(--glitch-link-hover);
}

code, pre {
  font-family: 'Share Tech Mono', 'Courier New', monospace;
  background-color: var(--glitch-static-gray);
  border: 1px solid var(--glitch-muted);
  padding: 0.2em 0.5em;
  color: var(--glitch-green);
}

pre {
  padding: 1.25em;
  overflow-x: auto;
  white-space: pre;
  border-left: 3px solid var(--glitch-cyan);
}

::selection {
  background-color: var(--glitch-magenta);
  color: var(--glitch-white);
}

Layout Principles


CSS / Design Techniques

Glitch Card Component

A content card with scan line overlay, subtle RGB offset on hover, and a corrupted-data border treatment.

.glitch-card {
  position: relative;
  background-color: var(--glitch-surface);
  border: 1px solid var(--glitch-muted);
  padding: 2rem;
  overflow: hidden;
  transition: transform 0.2s ease, border-color 0.3s ease;
}

/* Scan line overlay */
.glitch-card::before {
  content: '';
  position: absolute;
  inset: 0;
  background: repeating-linear-gradient(
    0deg,
    transparent,
    transparent 2px,
    rgba(0, 0, 0, 0.15) 2px,
    rgba(0, 0, 0, 0.15) 4px
  );
  pointer-events: none;
  z-index: 1;
}

.glitch-card:hover {
  border-color: var(--glitch-cyan);
  transform: translate(-2px, -1px);
  box-shadow:
    2px 0 0 var(--glitch-red),
    -2px 0 0 var(--glitch-blue);
}

.glitch-card h3 {
  position: relative;
  z-index: 2;
  font-family: 'Orbitron', sans-serif;
  font-size: 1.1rem;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--glitch-cyan);
  margin-bottom: 0.75rem;
}

.glitch-card p {
  position: relative;
  z-index: 2;
  font-size: 0.9rem;
  line-height: 1.6;
  color: var(--glitch-text);
}

.glitch-card .tag {
  display: inline-block;
  position: relative;
  z-index: 2;
  font-family: 'Share Tech Mono', monospace;
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  padding: 0.25rem 0.6rem;
  border: 1px solid var(--glitch-muted);
  color: var(--glitch-green);
  margin-right: 0.25rem;
  margin-top: 0.75rem;
}

Glitch Button Component

A button with animated RGB split on hover, using pseudo-elements to create the chromatic aberration effect.

.glitch-btn {
  position: relative;
  display: inline-block;
  font-family: 'Orbitron', sans-serif;
  font-size: 0.85rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.15em;
  padding: 0.9rem 2rem;
  border: 1px solid var(--glitch-cyan);
  background-color: transparent;
  color: var(--glitch-cyan);
  cursor: pointer;
  text-decoration: none;
  overflow: hidden;
  transition: background-color 0.2s ease, color 0.2s ease;
}

.glitch-btn::before,
.glitch-btn::after {
  content: attr(data-text);
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0.9rem 2rem;
  opacity: 0;
  pointer-events: none;
}

.glitch-btn::before {
  color: var(--glitch-red);
  z-index: -1;
}

.glitch-btn::after {
  color: var(--glitch-blue);
  z-index: -1;
}

.glitch-btn:hover {
  background-color: var(--glitch-cyan);
  color: var(--glitch-void);
  animation: btn-glitch 0.3s ease forwards;
}

.glitch-btn:hover::before {
  opacity: 0.7;
  animation: rgb-shift-left 0.4s infinite;
}

.glitch-btn:hover::after {
  opacity: 0.7;
  animation: rgb-shift-right 0.4s infinite;
}

@keyframes btn-glitch {
  0% { transform: translate(0); }
  20% { transform: translate(-3px, 2px); }
  40% { transform: translate(2px, -1px); }
  60% { transform: translate(-1px, 1px); }
  80% { transform: translate(1px, -2px); }
  100% { transform: translate(0); }
}

@keyframes rgb-shift-left {
  0%, 100% { transform: translate(-2px, 0); }
  50% { transform: translate(-4px, 1px); }
}

@keyframes rgb-shift-right {
  0%, 100% { transform: translate(2px, 0); }
  50% { transform: translate(4px, -1px); }
}

Glitch Navigation Bar

A top navigation with a subtle interference band and scan line texture, featuring glitch-styled hover states.

.glitch-nav {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 1rem 2rem;
  background-color: var(--glitch-void);
  border-bottom: 1px solid var(--glitch-muted);
  z-index: 100;
}

/* Bottom interference line */
.glitch-nav::after {
  content: '';
  position: absolute;
  bottom: 0;
  left: 0;
  width: 100%;
  height: 2px;
  background: linear-gradient(
    90deg,
    var(--glitch-cyan) 0%,
    var(--glitch-magenta) 33%,
    var(--glitch-green) 66%,
    var(--glitch-cyan) 100%
  );
  background-size: 200% 100%;
  animation: interference-scan 3s linear infinite;
}

@keyframes interference-scan {
  0% { background-position: 0% 0%; }
  100% { background-position: 200% 0%; }
}

.glitch-nav .logo {
  font-family: 'Orbitron', sans-serif;
  font-size: 1.1rem;
  font-weight: 900;
  text-transform: uppercase;
  letter-spacing: 0.2em;
  color: var(--glitch-white);
  text-decoration: none;
}

.glitch-nav ul {
  list-style: none;
  display: flex;
  gap: 0;
  margin: 0;
  padding: 0;
}

.glitch-nav a {
  display: block;
  padding: 0.5rem 1.25rem;
  font-family: 'Share Tech Mono', monospace;
  font-size: 0.8rem;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--glitch-text);
  text-decoration: none;
  border: none;
  position: relative;
  transition: color 0.15s ease;
}

.glitch-nav a:hover {
  color: var(--glitch-cyan);
  text-shadow:
    2px 0 var(--glitch-red),
    -2px 0 var(--glitch-blue);
}

.glitch-nav a::after {
  content: '';
  position: absolute;
  bottom: 0;
  left: 50%;
  width: 0;
  height: 1px;
  background-color: var(--glitch-cyan);
  transition: width 0.2s ease, left 0.2s ease;
}

.glitch-nav a:hover::after {
  width: 100%;
  left: 0;
}

Glitch Hero Section

A full-viewport hero with animated RGB-split headline text, scan line overlay, and noise texture background.

.glitch-hero {
  position: relative;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: 4rem 3rem;
  background-color: var(--glitch-void);
  overflow: hidden;
}

/* Noise texture layer */
.glitch-hero::before {
  content: '';
  position: absolute;
  inset: -50%;
  width: 200%;
  height: 200%;
  background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noise'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noise)' opacity='0.04'/%3E%3C/svg%3E");
  pointer-events: none;
  z-index: 1;
}

/* Scan line overlay */
.glitch-hero::after {
  content: '';
  position: absolute;
  inset: 0;
  background: repeating-linear-gradient(
    0deg,
    transparent,
    transparent 2px,
    rgba(0, 0, 0, 0.12) 2px,
    rgba(0, 0, 0, 0.12) 4px
  );
  pointer-events: none;
  z-index: 2;
}

.glitch-hero__content {
  position: relative;
  z-index: 3;
  max-width: 900px;
}

.glitch-hero__title {
  font-family: 'Orbitron', sans-serif;
  font-size: clamp(3rem, 9vw, 8rem);
  font-weight: 900;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  line-height: 0.95;
  color: var(--glitch-white);
  position: relative;
}

.glitch-hero__subtitle {
  font-family: 'Share Tech Mono', monospace;
  font-size: clamp(0.9rem, 1.5vw, 1.2rem);
  color: var(--glitch-text);
  max-width: 50ch;
  margin-top: 1.5rem;
  line-height: 1.7;
}

.glitch-hero__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
  margin-top: 2.5rem;
}

RGB Split Text Effect

An animated chromatic aberration effect on text using pseudo-elements, where red and blue copies of the text are offset and blended to create the signature glitch look.

.rgb-split {
  position: relative;
  display: inline-block;
  color: var(--glitch-white);
  font-family: 'Orbitron', sans-serif;
  font-weight: 900;
  text-transform: uppercase;
}

.rgb-split::before,
.rgb-split::after {
  content: attr(data-text);
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  overflow: hidden;
}

.rgb-split::before {
  color: var(--glitch-red);
  mix-blend-mode: screen;
  animation: rgb-split-red 3s infinite;
  clip-path: inset(0 0 0 0);
}

.rgb-split::after {
  color: var(--glitch-blue);
  mix-blend-mode: screen;
  animation: rgb-split-blue 3s infinite;
  clip-path: inset(0 0 0 0);
}

@keyframes rgb-split-red {
  0%, 100% { transform: translate(-2px, 0); }
  25% { transform: translate(2px, 1px); clip-path: inset(30% 0 40% 0); }
  50% { transform: translate(-1px, -1px); clip-path: inset(0 0 0 0); }
  75% { transform: translate(3px, 0); clip-path: inset(60% 0 10% 0); }
}

@keyframes rgb-split-blue {
  0%, 100% { transform: translate(2px, 0); }
  25% { transform: translate(-3px, -1px); clip-path: inset(50% 0 20% 0); }
  50% { transform: translate(1px, 1px); clip-path: inset(0 0 0 0); }
  75% { transform: translate(-2px, 0); clip-path: inset(10% 0 70% 0); }
}

/* Reduced motion variant */
@media (prefers-reduced-motion: reduce) {
  .rgb-split::before {
    animation: none;
    transform: translate(-2px, 0);
  }
  .rgb-split::after {
    animation: none;
    transform: translate(2px, 0);
  }
}

Scan Line Overlay

A reusable overlay component that applies CRT-style scan lines to any container, with optional animated flicker.

.scanlines {
  position: relative;
  overflow: hidden;
}

.scanlines::after {
  content: '';
  position: absolute;
  inset: 0;
  background: repeating-linear-gradient(
    0deg,
    transparent 0px,
    transparent 2px,
    rgba(0, 0, 0, 0.2) 2px,
    rgba(0, 0, 0, 0.2) 4px
  );
  pointer-events: none;
  z-index: 10;
}

/* Animated variant with vertical scan bar */
.scanlines--animated::before {
  content: '';
  position: absolute;
  top: -100%;
  left: 0;
  width: 100%;
  height: 30%;
  background: linear-gradient(
    180deg,
    transparent 0%,
    rgba(0, 255, 255, 0.03) 50%,
    transparent 100%
  );
  pointer-events: none;
  z-index: 11;
  animation: scan-sweep 4s linear infinite;
}

@keyframes scan-sweep {
  0% { top: -30%; }
  100% { top: 130%; }
}

/* CRT screen curvature (optional enhancement) */
.scanlines--crt {
  border-radius: 12px;
  box-shadow:
    inset 0 0 60px rgba(0, 0, 0, 0.4),
    inset 0 0 10px rgba(0, 0, 0, 0.3);
}

@media (prefers-reduced-motion: reduce) {
  .scanlines--animated::before {
    animation: none;
    display: none;
  }
}

Datamosh / Corrupted Image Treatment

A CSS treatment that simulates datamoshing on images using blend modes, clip-path slicing, and color channel manipulation.

.datamosh {
  position: relative;
  overflow: hidden;
  display: block;
}

.datamosh img {
  display: block;
  width: 100%;
  height: auto;
  filter: contrast(1.1) saturate(1.3);
}

/* Red channel ghost */
.datamosh::before {
  content: '';
  position: absolute;
  inset: 0;
  background: inherit;
  mix-blend-mode: multiply;
  opacity: 0.6;
  background-color: var(--glitch-red);
  clip-path: polygon(0 20%, 100% 15%, 100% 45%, 0 50%);
  transform: translate(8px, 0);
  z-index: 2;
}

/* Blue channel ghost */
.datamosh::after {
  content: '';
  position: absolute;
  inset: 0;
  background: inherit;
  mix-blend-mode: screen;
  opacity: 0.5;
  background-color: var(--glitch-blue);
  clip-path: polygon(0 55%, 100% 60%, 100% 80%, 0 75%);
  transform: translate(-6px, 0);
  z-index: 2;
}

/* Animated variant */
.datamosh--animated::before {
  animation: mosh-slice-a 2.5s steps(1) infinite;
}

.datamosh--animated::after {
  animation: mosh-slice-b 3s steps(1) infinite;
}

@keyframes mosh-slice-a {
  0% { clip-path: polygon(0 20%, 100% 15%, 100% 45%, 0 50%); transform: translate(8px, 0); }
  25% { clip-path: polygon(0 50%, 100% 55%, 100% 70%, 0 65%); transform: translate(-5px, 0); }
  50% { clip-path: polygon(0 10%, 100% 5%, 100% 25%, 0 30%); transform: translate(10px, 0); }
  75% { clip-path: polygon(0 70%, 100% 75%, 100% 90%, 0 85%); transform: translate(-3px, 0); }
}

@keyframes mosh-slice-b {
  0% { clip-path: polygon(0 55%, 100% 60%, 100% 80%, 0 75%); transform: translate(-6px, 0); }
  33% { clip-path: polygon(0 30%, 100% 25%, 100% 50%, 0 55%); transform: translate(7px, 0); }
  66% { clip-path: polygon(0 80%, 100% 85%, 100% 95%, 0 90%); transform: translate(-9px, 0); }
}

@media (prefers-reduced-motion: reduce) {
  .datamosh--animated::before,
  .datamosh--animated::after {
    animation: none;
  }
}

Noise Texture Background

A pure CSS animated noise background using SVG filters, creating a subtle static grain effect across any element.

.noise-bg {
  position: relative;
  isolation: isolate;
}

.noise-bg::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  opacity: 0.06;
  background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 512 512' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noiseFilter'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.8' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noiseFilter)'/%3E%3C/svg%3E");
  background-repeat: repeat;
  pointer-events: none;
}

/* Animated grain variant */
.noise-bg--animated::before {
  animation: noise-shift 0.5s steps(4) infinite;
}

@keyframes noise-shift {
  0% { transform: translate(0, 0); }
  25% { transform: translate(-5%, -5%); }
  50% { transform: translate(5%, 2%); }
  75% { transform: translate(-2%, 5%); }
  100% { transform: translate(0, 0); }
}

@media (prefers-reduced-motion: reduce) {
  .noise-bg--animated::before {
    animation: none;
  }
}

Design Do’s and Don’ts

Do’s

Don’ts


Aesthetic Relationship
Cyberpunk Shares the neon-on-dark palette and dystopian digital atmosphere; Cyberpunk builds narrative worlds while Glitch Art focuses on the material breakdown of the medium itself
Vaporwave Both reference digital artifacts and retro technology, but Vaporwave uses pastels and ironic nostalgia where Glitch Art embraces raw, aggressive corruption
Y2K Futurism Both celebrate digital technology as a visual subject; Y2K looks forward with optimism while Glitch Art exposes the fragility behind the polished interface
Terminal CLI Aesthetic Shares monospaced typography and the foregrounding of digital infrastructure; Terminal is ordered and systematic while Glitch Art breaks those systems apart
Weirdcore Both create unsettling digital imagery through distortion and corruption, but Weirdcore targets surreal emotional discomfort while Glitch Art celebrates technical materiality
Low Poly Both foreground the building blocks of digital graphics (polygons vs. pixels); Low Poly is geometric and controlled, Glitch Art is chaotic and deconstructive

Quick-Start HTML Template

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Glitch Art Template</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=Orbitron:wght@400;700;900&family=Share+Tech+Mono&family=VT323&display=swap" rel="stylesheet">
  <style>
    /* --- Custom Properties --- */
    :root {
      --glitch-void: #0d0d0d;
      --glitch-screen-dark: #1a1a2e;
      --glitch-static-gray: #2a2a2a;
      --glitch-red: #ff0040;
      --glitch-green: #00ff41;
      --glitch-blue: #0080ff;
      --glitch-cyan: #00ffff;
      --glitch-magenta: #ff00ff;
      --glitch-pink: #ff2e97;
      --glitch-yellow: #f5f500;
      --glitch-purple: #7b2fbe;
      --glitch-orange: #ff6b2b;
      --glitch-white: #ffffff;
      --glitch-text: #e0e0e0;
      --glitch-muted: #444444;
    }

    /* --- Reset --- */
    *, *::before, *::after {
      box-sizing: border-box;
      margin: 0;
      padding: 0;
    }

    body {
      font-family: 'Share Tech Mono', 'Courier New', Courier, monospace;
      font-size: 16px;
      line-height: 1.7;
      color: var(--glitch-text);
      background-color: var(--glitch-void);
      -webkit-font-smoothing: antialiased;
      overflow-x: hidden;
    }

    h1, h2, h3, h4 {
      font-family: 'Orbitron', 'Arial Black', sans-serif;
      text-transform: uppercase;
      letter-spacing: 0.08em;
      line-height: 1.1;
      color: var(--glitch-white);
    }

    a {
      color: var(--glitch-cyan);
      text-decoration: none;
      transition: color 0.15s ease;
    }

    a:hover {
      color: var(--glitch-magenta);
    }

    ::selection {
      background-color: var(--glitch-magenta);
      color: var(--glitch-white);
    }

    /* --- Navigation --- */
    .nav {
      position: relative;
      display: flex;
      align-items: center;
      justify-content: space-between;
      padding: 1rem 2rem;
      background-color: var(--glitch-void);
      border-bottom: 1px solid var(--glitch-muted);
    }

    .nav::after {
      content: '';
      position: absolute;
      bottom: 0;
      left: 0;
      width: 100%;
      height: 2px;
      background: linear-gradient(
        90deg,
        var(--glitch-cyan),
        var(--glitch-magenta),
        var(--glitch-green),
        var(--glitch-cyan)
      );
      background-size: 200% 100%;
      animation: interference-line 3s linear infinite;
    }

    @keyframes interference-line {
      0% { background-position: 0% 0%; }
      100% { background-position: 200% 0%; }
    }

    .nav .logo {
      font-family: 'Orbitron', sans-serif;
      font-size: 1rem;
      font-weight: 900;
      text-transform: uppercase;
      letter-spacing: 0.25em;
      color: var(--glitch-white);
    }

    .nav ul {
      list-style: none;
      display: flex;
      gap: 0;
    }

    .nav a {
      display: block;
      padding: 0.5rem 1.2rem;
      font-size: 0.78rem;
      text-transform: uppercase;
      letter-spacing: 0.12em;
      color: var(--glitch-text);
    }

    .nav a:hover {
      color: var(--glitch-cyan);
      text-shadow:
        2px 0 var(--glitch-red),
        -2px 0 var(--glitch-blue);
    }

    /* --- Hero --- */
    .hero {
      position: relative;
      min-height: 100vh;
      display: flex;
      flex-direction: column;
      justify-content: center;
      padding: 4rem 3rem;
      overflow: hidden;
    }

    /* Scan lines */
    .hero::after {
      content: '';
      position: absolute;
      inset: 0;
      background: repeating-linear-gradient(
        0deg,
        transparent 0px,
        transparent 2px,
        rgba(0, 0, 0, 0.12) 2px,
        rgba(0, 0, 0, 0.12) 4px
      );
      pointer-events: none;
      z-index: 2;
    }

    .hero-content {
      position: relative;
      z-index: 3;
      max-width: 900px;
    }

    /* RGB Split Headline */
    .hero-title {
      font-size: clamp(3rem, 9vw, 8rem);
      font-weight: 900;
      line-height: 0.95;
      position: relative;
      display: inline-block;
    }

    .hero-title::before,
    .hero-title::after {
      content: attr(data-text);
      position: absolute;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;
      overflow: hidden;
    }

    .hero-title::before {
      color: var(--glitch-red);
      mix-blend-mode: screen;
      animation: glitch-r 3s infinite;
    }

    .hero-title::after {
      color: var(--glitch-blue);
      mix-blend-mode: screen;
      animation: glitch-b 3s infinite;
    }

    @keyframes glitch-r {
      0%, 100% { transform: translate(-2px, 0); clip-path: inset(0 0 0 0); }
      20% { transform: translate(3px, 1px); clip-path: inset(25% 0 55% 0); }
      40% { transform: translate(-1px, -1px); clip-path: inset(0 0 0 0); }
      60% { transform: translate(4px, 0); clip-path: inset(60% 0 5% 0); }
      80% { transform: translate(-2px, 1px); clip-path: inset(0 0 0 0); }
    }

    @keyframes glitch-b {
      0%, 100% { transform: translate(2px, 0); clip-path: inset(0 0 0 0); }
      20% { transform: translate(-3px, -1px); clip-path: inset(50% 0 20% 0); }
      40% { transform: translate(1px, 1px); clip-path: inset(0 0 0 0); }
      60% { transform: translate(-4px, 0); clip-path: inset(10% 0 70% 0); }
      80% { transform: translate(2px, -1px); clip-path: inset(0 0 0 0); }
    }

    .hero-sub {
      font-size: clamp(0.9rem, 1.5vw, 1.15rem);
      max-width: 50ch;
      margin-top: 1.5rem;
      color: var(--glitch-text);
      line-height: 1.8;
    }

    .hero-sub span {
      color: var(--glitch-cyan);
    }

    .hero-actions {
      display: flex;
      flex-wrap: wrap;
      gap: 1rem;
      margin-top: 2.5rem;
    }

    /* --- Buttons --- */
    .btn {
      position: relative;
      display: inline-block;
      font-family: 'Orbitron', sans-serif;
      font-size: 0.78rem;
      font-weight: 700;
      text-transform: uppercase;
      letter-spacing: 0.15em;
      padding: 0.85rem 2rem;
      border: 1px solid var(--glitch-cyan);
      background-color: transparent;
      color: var(--glitch-cyan);
      cursor: pointer;
      text-decoration: none;
      overflow: hidden;
      transition: background-color 0.2s ease, color 0.2s ease;
    }

    .btn:hover {
      background-color: var(--glitch-cyan);
      color: var(--glitch-void);
      animation: btn-shake 0.3s ease;
    }

    @keyframes btn-shake {
      0% { transform: translate(0); }
      20% { transform: translate(-3px, 2px); }
      40% { transform: translate(2px, -1px); }
      60% { transform: translate(-1px, 1px); }
      80% { transform: translate(1px, -2px); }
      100% { transform: translate(0); }
    }

    .btn--alt {
      border-color: var(--glitch-pink);
      color: var(--glitch-pink);
    }

    .btn--alt:hover {
      background-color: var(--glitch-pink);
      color: var(--glitch-void);
    }

    /* --- Section --- */
    .section {
      position: relative;
      padding: 5rem 3rem;
      border-top: 1px solid var(--glitch-muted);
    }

    .section h2 {
      font-size: clamp(1.8rem, 4vw, 3rem);
      margin-bottom: 1rem;
      color: var(--glitch-cyan);
    }

    .section > p {
      max-width: 65ch;
      margin-bottom: 2rem;
      line-height: 1.8;
    }

    /* Section label */
    .section-label {
      font-family: 'Share Tech Mono', monospace;
      font-size: 0.7rem;
      text-transform: uppercase;
      letter-spacing: 0.25em;
      color: var(--glitch-muted);
      margin-bottom: 0.5rem;
      display: block;
    }

    /* --- Card Grid --- */
    .card-grid {
      display: grid;
      grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
      gap: 1px;
      background-color: var(--glitch-muted);
      border: 1px solid var(--glitch-muted);
    }

    .card {
      position: relative;
      background-color: var(--glitch-screen-dark);
      padding: 2rem;
      overflow: hidden;
      transition: transform 0.15s ease;
    }

    /* Scan lines on cards */
    .card::before {
      content: '';
      position: absolute;
      inset: 0;
      background: repeating-linear-gradient(
        0deg,
        transparent 0px,
        transparent 2px,
        rgba(0, 0, 0, 0.1) 2px,
        rgba(0, 0, 0, 0.1) 4px
      );
      pointer-events: none;
      z-index: 1;
    }

    .card:hover {
      transform: translate(-2px, -1px);
      box-shadow:
        3px 0 0 var(--glitch-red),
        -3px 0 0 var(--glitch-blue);
    }

    .card h3 {
      position: relative;
      z-index: 2;
      font-size: 1rem;
      letter-spacing: 0.1em;
      color: var(--glitch-cyan);
      margin-bottom: 0.75rem;
    }

    .card p {
      position: relative;
      z-index: 2;
      font-size: 0.88rem;
      line-height: 1.7;
      margin-bottom: 1rem;
    }

    .card .tag {
      display: inline-block;
      position: relative;
      z-index: 2;
      font-size: 0.68rem;
      text-transform: uppercase;
      letter-spacing: 0.12em;
      padding: 0.2rem 0.5rem;
      border: 1px solid var(--glitch-muted);
      color: var(--glitch-green);
      margin-right: 0.3rem;
      margin-bottom: 0.3rem;
    }

    /* --- Data Table --- */
    .data-table {
      width: 100%;
      border-collapse: collapse;
      font-size: 0.85rem;
    }

    .data-table th,
    .data-table td {
      border: 1px solid var(--glitch-muted);
      padding: 0.75rem 1rem;
      text-align: left;
    }

    .data-table th {
      background-color: var(--glitch-screen-dark);
      color: var(--glitch-cyan);
      font-family: 'Orbitron', sans-serif;
      font-size: 0.72rem;
      text-transform: uppercase;
      letter-spacing: 0.15em;
      font-weight: 700;
    }

    .data-table tr:hover td {
      background-color: rgba(0, 255, 255, 0.04);
    }

    .data-table td:first-child {
      color: var(--glitch-white);
    }

    /* --- Corrupted Divider --- */
    .divider {
      position: relative;
      height: 4px;
      background: var(--glitch-muted);
      margin: 0;
      overflow: hidden;
    }

    .divider::before {
      content: '';
      position: absolute;
      inset: 0;
      background: linear-gradient(
        90deg,
        var(--glitch-cyan) 0%,
        var(--glitch-pink) 25%,
        var(--glitch-void) 30%,
        var(--glitch-void) 45%,
        var(--glitch-green) 50%,
        var(--glitch-void) 55%,
        var(--glitch-void) 70%,
        var(--glitch-magenta) 75%,
        var(--glitch-cyan) 100%
      );
      animation: divider-scan 4s linear infinite;
      background-size: 200% 100%;
    }

    @keyframes divider-scan {
      0% { background-position: 0% 0%; }
      100% { background-position: 200% 0%; }
    }

    /* --- Signal Interference Banner --- */
    .interference {
      position: relative;
      padding: 2.5rem 3rem;
      background-color: var(--glitch-screen-dark);
      border-top: 1px solid var(--glitch-muted);
      border-bottom: 1px solid var(--glitch-muted);
      overflow: hidden;
      text-align: center;
    }

    .interference::before {
      content: '';
      position: absolute;
      top: 0;
      left: -100%;
      width: 300%;
      height: 100%;
      background: repeating-linear-gradient(
        90deg,
        transparent 0px,
        transparent 3px,
        rgba(0, 255, 255, 0.03) 3px,
        rgba(0, 255, 255, 0.03) 6px
      );
      animation: h-scan 2s linear infinite;
      pointer-events: none;
    }

    @keyframes h-scan {
      0% { transform: translateX(0); }
      100% { transform: translateX(33.33%); }
    }

    .interference .display-text {
      font-family: 'VT323', monospace;
      font-size: clamp(1.5rem, 3vw, 2.5rem);
      color: var(--glitch-green);
      letter-spacing: 0.15em;
      text-transform: uppercase;
      position: relative;
      z-index: 2;
    }

    /* --- Footer --- */
    .footer {
      padding: 2.5rem 3rem;
      border-top: 1px solid var(--glitch-muted);
      display: flex;
      justify-content: space-between;
      align-items: center;
      flex-wrap: wrap;
      gap: 1rem;
    }

    .footer p {
      font-size: 0.78rem;
      color: var(--glitch-muted);
    }

    .footer a {
      color: var(--glitch-text);
      margin-left: 1.5rem;
      font-size: 0.78rem;
      letter-spacing: 0.08em;
      text-transform: uppercase;
    }

    .footer a:hover {
      color: var(--glitch-cyan);
    }

    /* --- Utilities --- */
    .mt-1 { margin-top: 1rem; }
    .mt-2 { margin-top: 2rem; }
    .text-cyan { color: var(--glitch-cyan); }
    .text-pink { color: var(--glitch-pink); }
    .text-green { color: var(--glitch-green); }

    /* --- Reduced Motion --- */
    @media (prefers-reduced-motion: reduce) {
      .hero-title::before,
      .hero-title::after {
        animation: none;
        transform: translate(0);
        clip-path: inset(0 0 0 0);
      }
      .hero-title::before { transform: translate(-2px, 0); }
      .hero-title::after { transform: translate(2px, 0); }
      .nav::after { animation: none; }
      .divider::before { animation: none; }
      .interference::before { animation: none; }
      .btn:hover { animation: none; }
    }

    /* --- Responsive --- */
    @media (max-width: 768px) {
      .hero {
        min-height: 80vh;
        padding: 3rem 1.5rem;
      }
      .section {
        padding: 3rem 1.5rem;
      }
      .nav {
        flex-direction: column;
        align-items: flex-start;
        gap: 0.75rem;
        padding: 1rem 1.5rem;
      }
      .nav ul {
        flex-wrap: wrap;
      }
      .card-grid {
        grid-template-columns: 1fr;
      }
      .footer {
        flex-direction: column;
        align-items: flex-start;
        padding: 2rem 1.5rem;
      }
      .footer a {
        margin-left: 0;
        margin-right: 1rem;
      }
    }
  </style>
</head>
<body>

  <!-- NAVIGATION -->
  <nav class="nav">
    <span class="logo">GL//TCH</span>
    <ul>
      <li><a href="#about">About</a></li>
      <li><a href="#projects">Projects</a></li>
      <li><a href="#data">Data</a></li>
      <li><a href="#signal">Signal</a></li>
      <li><a href="#contact">Contact</a></li>
    </ul>
  </nav>

  <!-- HERO -->
  <section class="hero">
    <div class="hero-content">
      <h1 class="hero-title" data-text="Glitch Art">Glitch Art</h1>
      <p class="hero-sub">
        The beauty of <span>broken data</span>. We find aesthetics in
        technological failure -- pixel corruption, signal interference,
        and the hidden structures revealed when digital systems malfunction.
        This is not an error. This is the message.
      </p>
      <div class="hero-actions">
        <a href="#projects" class="btn">Explore Projects</a>
        <a href="#data" class="btn btn--alt">View Data</a>
      </div>
    </div>
  </section>

  <!-- CORRUPTED DIVIDER -->
  <div class="divider"></div>

  <!-- ABOUT -->
  <section class="section" id="about">
    <span class="section-label">// 001 &mdash; About</span>
    <h2>Error as Aesthetic</h2>
    <p>
      Glitch Art transforms technological failure into a creative medium.
      By deliberately inducing or capturing malfunctions in digital systems,
      we expose the hidden mechanics of the tools we use every day.
      Datamoshing, pixel sorting, RGB channel splitting, and data bending
      are not bugs to be fixed -- they are the raw material of a new
      visual language.
    </p>
  </section>

  <!-- PROJECTS -->
  <section class="section" id="projects">
    <span class="section-label">// 002 &mdash; Projects</span>
    <h2>Projects</h2>
    <p>
      Each project explores a different facet of digital disruption.
      Hover to corrupt.
    </p>
    <div class="card-grid mt-2">
      <div class="card">
        <h3>Datamosh Engine</h3>
        <p>A real-time video corruption tool that removes I-frames from compressed video streams, producing the flowing, painterly distortions of datamoshing in the browser.</p>
        <span class="tag">Video</span>
        <span class="tag">WebCodecs</span>
        <span class="tag">Real-time</span>
      </div>
      <div class="card">
        <h3>Hex Painter</h3>
        <p>Open any image file as raw hexadecimal data and paint directly into the byte stream. Watch the image reconstruct with each corrupted edit.</p>
        <span class="tag">Data Bending</span>
        <span class="tag">Canvas</span>
      </div>
      <div class="card">
        <h3>Channel Drift</h3>
        <p>An interactive installation that separates the red, green, and blue channels of a live webcam feed and maps each to independent mouse-controlled offsets.</p>
        <span class="tag">RGB Split</span>
        <span class="tag">WebGL</span>
        <span class="tag">Interactive</span>
      </div>
      <div class="card">
        <h3>Signal Decay</h3>
        <p>Generative compositions that simulate electromagnetic interference, scan line degradation, and VHS tracking errors using pure CSS and SVG filters.</p>
        <span class="tag">Generative</span>
        <span class="tag">CSS</span>
        <span class="tag">SVG</span>
      </div>
      <div class="card">
        <h3>Codec Autopsy</h3>
        <p>A visual explainer that deconstructs JPEG, PNG, and WebP compression in real time, revealing the block artifacts and quantization tables hidden inside every image.</p>
        <span class="tag">Compression</span>
        <span class="tag">Education</span>
      </div>
      <div class="card">
        <h3>Pixel Sort Lab</h3>
        <p>Upload an image and apply pixel sorting algorithms -- by brightness, hue, or saturation -- to create the cascading, waterfall-like distortions of sorted pixel rows.</p>
        <span class="tag">Pixel Sorting</span>
        <span class="tag">WASM</span>
      </div>
    </div>
  </section>

  <!-- SIGNAL INTERFERENCE BANNER -->
  <div class="interference" id="signal">
    <div class="display-text">&#x2588;&#x2588; Signal Acquired &mdash; Corruption Level: 87% &#x2588;&#x2588;</div>
  </div>

  <!-- DATA TABLE -->
  <section class="section" id="data">
    <span class="section-label">// 003 &mdash; Data</span>
    <h2>Corruption Index</h2>
    <p>
      Measured distortion parameters across active signal channels.
    </p>
    <table class="data-table mt-2">
      <thead>
        <tr>
          <th>Channel</th>
          <th>Offset</th>
          <th>Noise Floor</th>
          <th>Artifact Rate</th>
          <th>Status</th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <td>RED</td>
          <td>+3px / -1px</td>
          <td>0.042</td>
          <td>12.7/sec</td>
          <td class="text-pink">CORRUPTED</td>
        </tr>
        <tr>
          <td>GREEN</td>
          <td>+0px / +2px</td>
          <td>0.018</td>
          <td>3.1/sec</td>
          <td class="text-green">NOMINAL</td>
        </tr>
        <tr>
          <td>BLUE</td>
          <td>-2px / +1px</td>
          <td>0.037</td>
          <td>9.4/sec</td>
          <td class="text-cyan">DEGRADED</td>
        </tr>
        <tr>
          <td>ALPHA</td>
          <td>+0px / +0px</td>
          <td>0.003</td>
          <td>0.2/sec</td>
          <td class="text-green">NOMINAL</td>
        </tr>
        <tr>
          <td>SYNC</td>
          <td>+7px / -4px</td>
          <td>0.089</td>
          <td>24.1/sec</td>
          <td class="text-pink">CRITICAL</td>
        </tr>
      </tbody>
    </table>
  </section>

  <!-- CONTACT -->
  <section class="section" id="contact">
    <span class="section-label">// 004 &mdash; Contact</span>
    <h2>Transmit</h2>
    <p>
      Signal endpoint: <a href="mailto:glitch@example.com">glitch@example.com</a>
      &mdash; Source: <a href="#">view repository</a>
      &mdash; License: MIT
    </p>
  </section>

  <!-- FOOTER -->
  <footer class="footer">
    <p>&copy; 2026 GL//TCH &mdash; Error is the message.</p>
    <nav>
      <a href="#">Top</a>
      <a href="#">Source</a>
      <a href="#">RSS</a>
    </nav>
  </footer>

</body>
</html>