Design guide · Candidate B of III

“Monument”

Type as architecture; the docket as design language. The gravity of the courtroom rendered as a very large, very calm building at night.

This page ships with the candidate on purpose — the process is part of the product.

I — Concept

Force, held in reserve.

For the business owner in a serious dispute, the right feeling is not friendliness — it is calm, enormous capability.

Monument borrows two visual grammars and fuses them: the modernist monument (near-black space, monumental variable-width type, structural hairlines) and the federal court filing (IBM Plex Mono docket labels, case-file cards, exhibit stamps, one drop of sealing-wax red). Motion is surgical: 100ms color inversions, blade-curve reveals, a marquee that never hurries.

The hero runs a hand-rolled WebGL shader — ink drifting in warm charcoal with an ember undertow — because the firm's story is pressure applied slowly and deliberately. No three.js, no libraries: one fragment shader, ~5 KB, DPR-capped, paused off-screen, replaced by a static gradient under reduced-motion or when WebGL is unavailable.

II — Tokens

Palette & type

--void #0F0D0B page ground — warm near-black, never pure #000
--void-2 #171310 elevated bands
--bone #F1ECE0 display text · ~15:1
--bone-60 #A79F8F secondary text · ~6:1
--wax #C2361F sealing-wax red — graphic accents only
--wax-bright #E8593F red text on dark · ~5:1, used sparingly
--line rgba(bone, 0.16) hairlines, structural grid
Display — Archivo Variable

Width is the voice.

wght 800–900 · wdth 92–125 · headlines animate wdth 78→108 on entrance

Docket — IBM Plex Mono

NO. 01 — CIVIL LITIGATION
FILED: FRANKLIN, TENN.
EXHIBIT A — AVVO REVIEW

Every label on the site is a docket entry. The metaphor is load-bearing: this is a firm that files things.

III — Motion inventory

Everything that moves

SHDR

Ink-well hero

Hand-written WebGL fragment shader: 4-octave domain-warped fbm, ember undertow breathing at 0.11Hz, film grain. DPR cap 1.5 (1.2 mobile), low-power context, IntersectionObserver + visibilitychange gating. Static frame under reduced-motion; CSS gradient when WebGL is unavailable.

TYPE

Headline word-rise

Per-word rise + variable-width expansion (wdth 78→108), 90ms stagger, blade easing cubic-bezier(.16,1,.3,1). Runs once.

MARQ

Docket marquee

Practice areas + venue on a 30s linear loop, duplicated track, pause on hover, static under reduced-motion.

MAGN

Magnetic CTA

Primary buttons ease toward the cursor within ~90px (max 6px), spring back on leave. Pointer-fine devices only.

PROG

Docket line

2px bone progress hairline across the top of the viewport, scaleX by scroll fraction, rAF-throttled.

RVLS

Reveals

20px rise + fade, 480ms, 60ms stagger within groups; hairlines draw scaleX. IntersectionObserver, once.

TABS

Exhibit tabs

Wax-red tabs on case-file cards slide 4px on hover; docket numbers ignite wax on row hover; buttons invert in 120ms.

GRPH

Grain + ghost numerals

SVG-noise film grain at 5.5% over everything; chapter numerals set outline-only at up to 15rem behind sections.

IV — Build & iteration

Stack, steps, passes

Stack. Astro 5, static output. Self-hosted variable fonts via Fontsource (Archivo Variable, IBM Plex Mono) — zero external requests. Hand-written CSS system, no framework. Vanilla TypeScript for reveals, nav, marquee, magnetic buttons, progress, and the shader. The shader is the only WebGL on the site and the whole JS payload stays in the tens of kilobytes.

Process. Design exploration ran first (ui-ux-pro-max catalog: kinetic-brutalism and exaggerated-minimalism mechanics, dark-mode contrast rules), then the system was locked in design.md before any page was written. Copy was drafted against the shared facts file with attorney-advertising rails: no outcome claims, no "expert/specialist," placeholders bracketed [LEEN: …] until real content exists.

Reproduce. npm install && npm run dev in b-monument/. Deploy: npm run build → wrangler pages deploy dist --project-name lmh-monument. Noindexed via meta robots + _headers X-Robots-Tag until promoted.

Iteration log — three passes in the rendered browser
  • Pass 1 — desktop: all six routes walked in the rendered browser. Caught & fixed a font-package path that broke the dev build (Archivo variable ships wdth.css, not full.css). Verified: shader mounts with WebGL + gradient fallback, marquee loop, exhibit tabs, ghost numerals, docket hovers, form validation and demo-submit state.
  • Pass 2 — mobile (375px): verified in a true 375px viewport — no horizontal overflow (371px content width measured), headline clamps correctly, CTAs go full-width, docket rows collapse to single column, hero keeps its presence at phone scale.
  • Pass 3 — polish: programmatic WCAG audit of every rendered text node: zero failures. Banned-phrase grep clean. Added the width-axis hover on case-file titles (wdth 108→118) — the "width is the voice" micro-move. Production build: six pages, ~680 KB total including fonts and the portrait.
V — Before launch

Replace list

Every [LEEN: …] chip is a deliberate placeholder — Avvo excerpts and initials, the Avvo profile link, education years, memberships, fee language. Nothing is fabricated. The contact form is demo-mode and must be wired to the firm's endpoint. Final attorney-advertising review belongs to the attorney.