Skip to main content
Copy for LLM

Theme: Retro Terminal

Phosphor-monitor aesthetic — maximum commitment. Requires config/wirekit.php → 'sans' => 'vt323':

/* WireKit Theme: Retro Terminal — Phosphor-monitor aesthetic.
   Fully self-contained color palette — inherits nothing from Default.
   No .dark override block — this theme is a dark theme.

   If your app uses class="dark" for dark-mode toggling, wrap the entire
   block in a plain `.dark { ... }`, not in `@layer theme`: a layered block
   loses to WireKit's unlayered defaults whatever its specificity, so a
   layered wrap would switch the preset off. Drop the trailing color-scheme
   rule as well; the class covers it.

   Prerequisite: config/wirekit.php → 'sans' => 'vt323'
   All colors WCAG AA/AAA verified on #0d0d0d (inline ratios). */
/* `:root` and `.dark`, NOT `@theme` / `@layer theme`, and the difference decides whether
   this block does anything at all.

   WireKit's own defaults sit inside `:where(:root)` — specificity 0 — precisely so a plain
   `:root` override wins whichever stylesheet the browser reads last. `@theme` compiles into
   `@layer theme`, and UNLAYERED CSS beats LAYERED CSS whatever the specificity: the defaults
   are unlayered, so a preset in `@theme` loses to them and silently does nothing except for
   the handful of tokens WireKit never declares.

   Nothing reports that. The CSS is valid, the custom properties resolve, and the page renders
   in the default theme while the developer reads their own preset in their own stylesheet. */
:root {
    /* Radius — null. */
    --radius-wk: 0px;

    /* Shadows — phosphor glow, not box-shadow. */
    --shadow-wk-sm: 0 0 0 0 transparent;
    --shadow-wk-md: 0 0 8px rgba(0, 255, 65, 0.15);
    --shadow-wk-lg: 0 0 16px rgba(0, 255, 65, 0.2);

    /* Font — VT323: pixel font inspired by DEC VT320 terminal.
       Only Regular (400) available — heading-weight and body-weight
       both 400. 0.06em tracking for pixel-font breathing room. */
    --font-wk-sans:           'VT323', 'Courier New', monospace;
    --font-wk-mono:           'VT323', 'Courier New', monospace;
    --font-wk-heading-weight: 400;
    --font-wk-body-weight:    400;
    --font-wk-letter-spacing: 0.06em;
    --font-wk-line-height:    1.5;

    /* Text sizes — slightly larger for VT323 legibility. */
    --text-wk-sm: 0.9375rem;
    --text-wk-md: 1rem;
    --text-wk-lg: 1.125rem;

    /* Motion — none. Instant, like a real terminal. */
    --transition-wk-duration: 0ms;

    /* Border — 1px terminal-style lines. */
    --border-wk-width: 1px;

    /* Focus ring — 2px is WCAG 2.4.11's minimum focus area, so the terminal's
       1px border width is deliberately NOT reused here. 0px offset puts the ring
       directly on the element edge (terminal-authentic, overrides the 2px gap). */
    --ring-wk-width:  2px;
    --ring-wk-offset: 0px;

    /* Disabled opacity — lower than Default (0.5) for the dark canvas. */
    --opacity-wk-disabled: 0.35;

    /* Accent & Ring — #00ff41 on #0d0d0d: ~14.3:1 AAA ✓ */
    --color-wk-accent:         #00ff41;
    --color-wk-accent-hover:   #33ff66;
    --color-wk-accent-content: #00ff41;
    --color-wk-accent-fg:      #0d0d0d;
    --color-wk-ring:           #00ff41;
    --color-wk-ring-offset:    #0d0d0d;

    /* Backgrounds — near-black canvas with subtle elevation steps. */
    --color-wk-bg:          #0d0d0d;
    --color-wk-bg-elevated: #1a1a1a;
    --color-wk-bg-subtle:   #1a1a1a;
    --color-wk-bg-muted:    #1f1f1f;
    --color-wk-bg-input:    #0d0d0d;
    /* The loading placeholder, and it has to be here rather than inherited.
       This preset re-tones `:root` to a dark surface — it is a dark theme that does not use
       the `.dark` class — so it inherits WireKit's LIGHT skeleton, `oklch(93% 0 0)`. That is
       a near-white block, and every loading placeholder on the page was one, flashing bright
       against the terminal before the content arrived. The presets that go dark under `.dark`
       are unaffected: they pick up the default's own dark value. */
    --color-wk-bg-skeleton: #2a2a2a;

    /* Text — 4 green tiers, all WCAG verified on #0d0d0d. */
    --color-wk-text:             #00ff41;  /* ~14.3:1 AAA */
    --color-wk-text-muted:       #00dd38;  /* ~10.9:1 AAA */
    --color-wk-text-subtle:      #00bb30;  /*  ~7.8:1 AAA */
    --color-wk-text-placeholder: #009926;  /*  ~5.4:1 AA  */

    /* Borders — all ≥ 3:1 on #0d0d0d.
       #00bb30: ~7.8:1 ✓  #008022: ~4.0:1 ✓ */
    --color-wk-border:        #00bb30;
    --color-wk-border-subtle: #008022;
    --color-wk-border-hover:  #00ff41;
    /* Form controls read --color-wk-border-strong, not --color-wk-border.
       Without these the inputs render with the stock neutral gray edge — on a
       phosphor-green terminal, the one element that must not look borrowed. */
    --color-wk-border-strong:       #00bb30;  /* 7.5:1 on #0d0d0d ✓ */
    --color-wk-border-strong-hover: #00ff41;  /* 14.2:1 — brightens away from the fill ✓ */
    /* A state border tracks its own helper TEXT, never the state SURFACE:
       border-error = danger-text, border-success = success-text. Re-tint one
       without the other and a field draws its edge in one red while the message
       underneath prints in a lighter one — it reads as a rendering fault, not a
       palette. Both clear the 3:1 non-text minimum on #0d0d0d. */
    --color-wk-border-error:   #ff6666;  /*  6.8:1 ✓ — matches --color-wk-danger-text  */
    --color-wk-border-success: #00ff41;  /* 14.2:1 ✓ — matches --color-wk-success-text */

    /* Danger — fix: danger-fg was inherited as white from Default.
       white on #ff4444 = 3.41:1 — WCAG 1.4.3 FAIL!
       #0d0d0d on #ff4444 = ~5.70:1 AA ✓
       #0d0d0d on #ff6666 (hover) = ~6.80:1 AAA ✓ */
    --color-wk-danger:       #ff4444;
    --color-wk-danger-hover: #ff6666;
    --color-wk-danger-fg:    #0d0d0d;
    --color-wk-danger-text:  #ff6666;

    /* Success — explicitly set for palette consistency.
       #0d0d0d on #00ff41 = ~14.3:1 AAA ✓ */
    --color-wk-success:       #00ff41;
    --color-wk-success-hover: #33ff66;
    --color-wk-success-fg:    #0d0d0d;
    --color-wk-success-text:  #00ff41;

    /* Warning — amber terminal glow.
       #0d0d0d on #ffaa00 = ~10.18:1 AAA ✓
       The -text and -bg pair below is what the other three intents get from
       their own declarations, and warning was the one left to inherit. This
       block applies as `@theme`, so an undeclared token resolves against the
       LIGHT baseline — amber-800 text (2.8:1 here) and a near-white highlight
       surface (1.2:1 under the phosphor body text). Both are real surfaces:
       -text draws warning body copy, the badge and usage-meter labels, and the
       optimistic-rollback outline; -bg is the fill behind <x-wirekit::mark> and
       <x-wirekit::highlight>. */
    --color-wk-warning:       #ffaa00;
    --color-wk-warning-hover: #ffcc33;
    --color-wk-warning-fg:    #0d0d0d;
    --color-wk-warning-text:  #ffcc33;  /* 12.9:1 on #0d0d0d, 11.6:1 on #1a1a1a AAA ✓ */
    /* Highlight fill. Same value the dark baseline uses for this token, so the
       amber wash keeps the step it was tuned for — 1.6:1 against the page and
       1.4:1 against an elevated panel — with #00ff41 body text at 9.1:1 AAA ✓ */
    --color-wk-warning-bg:    #432f07;

    /* Info — cyan accent. #00ddff on #0d0d0d: ~11.83:1 AAA ✓ */
    --color-wk-info: #00ddff;

    /* Overlay & Scrollbar — green-tinted scrollbar. */
    --color-wk-overlay:               rgba(0, 0, 0, 0.8);
    --color-wk-scrollbar-thumb:       #008022;
    --color-wk-scrollbar-thumb-hover: #00bb30;
    --color-wk-scrollbar-track:       transparent;
}

/* Native control chrome. The tokens above repaint everything WireKit draws,
   but not what the BROWSER draws — the native <select> popup, the document
   scrollbar, number spinners, the date and color pickers, autofill. Those
   follow `color-scheme` alone, and on a #0d0d0d canvas its light default is
   the one thing that still looks borrowed. It cannot live inside `@theme`,
   which accepts custom properties and keyframes only.

   Taking the `@layer theme { .dark { ... } }` route above instead? Then drop
   this rule: the `dark` class already selects WireKit's own
   `color-scheme: dark`, and an unconditional `:root` would darken the native
   controls in light mode too. */
:root {
    color-scheme: dark;
}

/* More contrast, on a theme whose `:root` is dark.

   `[data-contrast="more"]` pushes the muted text families toward BLACK, which is
   correct on a light page and exactly the wrong direction here: on this terminal it
   took hint text from 10.55:1 down to 2.11:1, so asking for MORE contrast made the
   theme unreadable.

   The base stylesheet's own dark override does not help — it is keyed on `.dark`, and
   this preset is a dark theme that re-tones `:root` instead. So the values are restated
   in the same shape the preset itself uses. Same trap as `--color-wk-bg-skeleton`
   above, one selector further along. */
:root[data-contrast="more"] {
    --color-wk-text-muted:       #00ff41;  /* 14.23:1 on #0d0d0d, up from 2.11:1 */
    --color-wk-text-subtle:      #00ee3c;  /* 12.30:1 */
    --color-wk-text-placeholder: #00ee3c;  /* a placeholder is text a reader must read */
    --color-wk-border:           #00bb30;  /*  7.54:1 */
    --color-wk-border-subtle:    #008022;  /*  3.80:1 */
}

Retro Terminal uses hardcoded hex values for a complete custom color scheme — it inherits nothing from Default. VT323 is bundled with WireKit (config/wirekit.php → 'sans' => 'vt323'). Every color is WCAG AA/AAA verified against the #0d0d0d canvas — do not lower any value's lightness without re-running contrast math, or contrast drops below the AA threshold. If your app toggles class="dark", wrap the block in @layer theme { .dark { ... } } so Default's dark overrides don't win the cascade, and drop the trailing :root { color-scheme: dark; } rule — the class already carries it, and left unconditional it would darken the native controls in light mode too.

Design notes

Retro Terminal commits fully to a phosphor-monitor aesthetic: green-on-near-black, the VT323 pixel font, and no compromises toward a conventional look. It is a statement theme, not a quiet default — every surface reads like a CRT console.

Best for: hacker / CTF tooling, developer products, and playful or nostalgic brands. Avoid it for long-form reading or broad general audiences, where a saturated single-hue palette tires the eye.

Accessibility

Every color is WCAG-verified against the #0d0d0d background: the primary green #00ff41 is ~14.3:1 (AAA), the muted tier ~10.9:1 (AAA), and the focus ring is 2px (fixing a sub-minimum 2.4.11 area). Note that an all-green palette can be hard for some low-vision and color-vision-deficient users — if your audience is broad, offer the default theme as a switchable alternative.

Was this page helpful?

Thank you for your feedback!

Voting requires cookies or local storage. What we store