← Back to Blog Engineering

Light-Mode Lockdown: Why proofco.ai Will Never Go Dark

There is a particular shade of slate — #0f172a if you want the receipt — that quietly took over the marketing web in 2023. It is the default hero band of every developer-tools landing page, every AI startup splash, every “we ship velocity” pitch. It is also the wrong color for our customers.

This week we locked the entire Proof AI marketing site to light mode. Not as a preference. As a contract.

The audit

The trigger was a customer call. A general manager running a sixteen-truck restoration shop in Tulsa opened our pricing page on his iPad in the bed of a pickup, in direct Oklahoma sun, mid-morning. He could read nothing. Our dark hero was a black mirror reflecting his own face back at him.

That afternoon we ran the audit. The numbers were worse than we expected: twenty-plus pages with hardcoded dark backgrounds — #0f172a, #020617, #1e293b, a couple of bg-proof-black strays, a Discord-flavored #18191c lurking inside our chat widget. The blog post layout had a prose-invert band. The vertical landing pages — every one of the city/state SEO pages, hundreds of routes — inherited a dark enterprise-footer band from a single shared stylesheet.

A restoration company is a daylight business. Crews open our site on a phone, in a truck, on a roof, in a flooded basement with a single trouble light. The site has to read in sunlight, and it has to signal “operations console” not “video game.” Dark UI is for IDEs and Discord. Bright, calm, high-contrast surfaces are for the people who actually have to use the thing while wearing nitrile gloves.

The fix is not “swap colors”

The first instinct is to find-and-replace the hex codes. We tried it; we got halfway through and regressed twice. The real problem was deeper: every dark surface had been hardcoded inline, page by page, by a different contributor on a different week, with no shared vocabulary for what the surface meant.

So we built one. The design-token contract lives in apps/website/public/theme.css, in :root, and it names every surface the marketing site is allowed to use:

--bg:              #f8f9fc;       /* page background */
--bg-soft:         #f1f5f9;       /* secondary band */
--bg-card:         rgba(255,255,255,0.7);
--bg-card-solid:   #ffffff;

--surface-hero:        linear-gradient(180deg, #ffffff 0%, #f1f5f9 100%);
--surface-cta:         linear-gradient(135deg, #eef2ff 0%, #ede9fe 50%, #fef3c7 100%);
--surface-enterprise:  linear-gradient(135deg, #f8fafc 0%, #eef2ff 100%);

--text:        #0f172a;
--text-muted:  #334155;
--border:      rgba(15, 23, 42, 0.08);

--code-bg:     #0f172a;   /* ONE legitimate dark surface */
--code-fg:     #e2e8f0;

Three rules govern these tokens:

  1. No page may declare a background hex code. It uses a token or it does not ship.
  2. The only legitimate dark surface is <pre> inside help documentation — code fences need contrast, and a code block isn’t a hero band.
  3. The tokens are the only API. A component that needs a hero gradient asks for --surface-hero; it does not invent its own.

The forbidden hex list

We made the contract enforceable by writing it down as a denylist. These are the hex codes and Tailwind classes that the marketing site will not accept as backgrounds outside the <pre> allowlist:

  • #0f172a, #1e293b, #020617 (slate-900/800/950)
  • #18191c, #2b2d31 (Discord dark / less-dark)
  • bg-slate-9*, bg-zinc-9*, bg-neutral-9*, bg-black, bg-black/*
  • bg-white/[0.0*] (low-opacity white-on-dark — implies a dark parent)
  • prose-invert, text-neutral-300/400/500 on a light layout
  • bg-proof-black, bg-proof-deep

A CI grep guard now fails any PR that introduces one of those tokens as a background. The check is intentionally dumb — a single rg invocation, no AST parsing, no allowlist negotiations beyond doc-prose pre. Dumb checks are the only checks that survive contact with a five-person team shipping daily.

The seo.css move

The technical leverage on this cleanup came from one file. Every vertical landing page — restoration, roofing, plumbing, and the hundred-plus city/state combinations underneath them — inherits a shared stylesheet: seo.css. That file owned .seo-hero and .enterprise-footer, two classes responsible for the dark band at the top of every SEO page and the dark band at the bottom of every SEO page. Two selectors, hundreds of routes.

We rewrote those two selectors to consume --surface-hero and --surface-enterprise. One file, twenty-plus pages corrected, zero per-page edits. This is the design-token payoff: a contract at the root of the tree is leverage on every leaf.

The lesson is older than CSS. Centralize the surface, not the page. If the same visual concept appears on more than three routes, it belongs in a token, not a component, and definitely not inline. Every minute spent naming a surface saves an hour spent grepping for its hex code six months later.

What “lockdown” actually means

This is the part that matters more than the colors. We have shipped design refreshes before. They drift. The new buttons stay shiny for a quarter, and then someone adds a page in a hurry, copies an old component, hardcodes a hex, and the rot starts again. By the time it shows up in a customer call from Tulsa, it has already metastasized.

Lockdown means three things:

  • The tokens are versioned in theme.css and reviewed like an API.
  • The denylist runs in CI on every PR; a forbidden hex fails the build.
  • New surfaces must be proposed as tokens before they appear in components.

The design system is the contract, not the suggestion. If a designer wants a new surface, it becomes a token first. If an engineer wants to ship without one, the build catches it. If the founder wants to break the rule, the rule changes in theme.css and propagates everywhere at once — including the SEO pages, including the city pages, including the help docs.

What’s next

Light-mode lockdown is the floor, not the ceiling. The same token discipline now extends to typography (one Inter stack, one mono fallback), radius (--radius: 16px, --radius-sm: 10px), and brand color glows. We’re working through the application shell next, where dark patterns are louder still — the dispatcher view, the field worker mobile flow, the after-hours nightshift dashboard for water-mitigation crews.

The principle that carries forward is the one we should have written down years ago: the customer’s environment is the design constraint, not the team’s aesthetic. Our customers work in attics at three in the afternoon with the sun coming through a torn-out roof. Our UI has to be readable there. Everything else is preference.

If your site has a hex code in it, you do not have a design system. You have inertia. Name the surface. Enforce it. Then go build the next thing.

Ready to see AI in action?

Proof AI handles dispatch, documentation, vision, and operations — so you can focus on the work.

Get Started →

Proof AI Assistant

Online
Hi! I'm Proof AI. How can I help you today?