Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/apursley2012/player-one/llms.txt

Use this file to discover all available pages before exploring further.

The CRTOverlay component reproduces the visual artifacts of a cathode-ray tube monitor using only CSS — no canvas, no WebGL. It outputs two sibling div elements that sit at the very top of the stacking order and span the full viewport. Both carry pointer-events-none so they never interfere with user interaction, and both are purely decorative, adding depth and retro atmosphere to every screen in the app.

No Props

CRTOverlay accepts no props. The effect is intentionally global and uniform — drop it in and it works.

Usage

import CRTOverlay from "./components/CRTOverlay";

// Typically placed at the root layout level so it covers every page.
export default function Layout({ children }) {
  return (
    <>
      <CRTOverlay />
      <main>{children}</main>
    </>
  );
}
The Navigation component renders its own internal CRTOverlay inside the stage-select modal. This is intentional — the effect on the modal is independent of the root-level overlay, and stacking them deepens the aesthetic when the modal is open.

The Two Layers

Layer 1 — .crt-overlay (z-index: 9999)

This is the primary effect layer. It applies three visual techniques simultaneously: Scanlines Horizontal scanlines are drawn using a repeating linear-gradient:
.crt-overlay {
  background-image: linear-gradient(
    #12101000 50%,   /* transparent for the "lit" half of each line */
    #00000040 50%    /* semi-transparent black for the "dark" half  */
  );
  background-size: 100% 4px; /* each scanline pair is 4px tall */
}
Every 4 px of vertical space is split into a transparent upper half and a dimmed lower half, creating the characteristic horizontal banding of CRT displays. Color Channel Fringing A subtle text-shadow/filter combination introduces lateral color separation (chromatic aberration) that mimics the slight misalignment of RGB phosphor groups on a real CRT. This gives text and edges a faint red/blue halo. Flicker Animation The overlay’s opacity is animated with a CSS @keyframes flicker rule:
@keyframes flicker {
  0%,  100% { opacity: 0.85; }
  50%        { opacity: 1.0;  }
}

.crt-overlay {
  animation: flicker 0.15s infinite;
}
The rapid 0.15 s cycle is below the threshold of deliberate perception but produces a faint, organic screen-shimmer that reads subconsciously as an aged CRT.

Layer 2 — .crt-vignette (z-index: 9998)

The vignette layer sits one step below the scanline overlay and darkens the edges of the viewport using a radial gradient:
.crt-vignette {
  background: radial-gradient(
    ellipse at center,
    transparent 60%,
    rgba(0, 0, 0, 0.65) 100%
  );
}
This draws the viewer’s attention toward the center of the screen — exactly as the curved glass of an old monitor would — and reinforces the sense that content is displayed on a physical cabinet screen rather than a flat digital surface.

Full CSS Reference

/* Both layers share these base properties */
.crt-overlay,
.crt-vignette {
  position: fixed;
  inset: 0;
  pointer-events: none;
}

/* Scanline + flicker layer */
.crt-overlay {
  z-index: 9999;
  background-image: linear-gradient(#12101000 50%, #00000040 50%);
  background-size: 100% 4px;
  animation: flicker 0.15s infinite;
}

@keyframes flicker {
  0%,  100% { opacity: 0.85; }
  50%        { opacity: 1.0;  }
}

/* Edge vignette layer */
.crt-vignette {
  z-index: 9998;
  background: radial-gradient(ellipse at center, transparent 60%, rgba(0,0,0,0.65) 100%);
}

Implementation Notes

export default function CRTOverlay() {
  return (
    <>
      <div className="crt-overlay fixed inset-0 pointer-events-none" />
      <div className="crt-vignette fixed inset-0 pointer-events-none" />
    </>
  );
}
If you need to temporarily disable the CRT effect (e.g., for accessibility or screenshot testing), wrapping the component in a feature flag or env check is the cleanest approach since all visual logic lives in the two CSS classes.
The flicker animation runs continuously at 0.15 s. On very low-power devices this is negligible, but if you add additional CSS animations to the same element, test for cumulative GPU paint cost.

Where It’s Used

CRTOverlay appears in two places in the app:
  1. Root layout — mounted once alongside HUD and Navigation, covering every page at all times.
  2. Navigation modal — mounted inside the full-screen stage-select overlay to give the modal its own self-contained CRT treatment.

Build docs developers (and LLMs) love