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.
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 Width is the voice.
wght 800–900 · wdth 92–125 · headlines animate wdth 78→108 on entrance
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.
Everything that moves
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.
Headline word-rise
Per-word rise + variable-width expansion (wdth 78→108), 90ms stagger, blade easing cubic-bezier(.16,1,.3,1). Runs once.
Docket marquee
Practice areas + venue on a 30s linear loop, duplicated track, pause on hover, static under reduced-motion.
Magnetic CTA
Primary buttons ease toward the cursor within ~90px (max 6px), spring back on leave. Pointer-fine devices only.
Docket line
2px bone progress hairline across the top of the viewport, scaleX by scroll fraction, rAF-throttled.
Reveals
20px rise + fade, 480ms, 60ms stagger within groups; hairlines draw scaleX. IntersectionObserver, once.
Exhibit tabs
Wax-red tabs on case-file cards slide 4px on hover; docket numbers ignite wax on row hover; buttons invert in 120ms.
Grain + ghost numerals
SVG-noise film grain at 5.5% over everything; chapter numerals set outline-only at up to 15rem behind sections.
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.
- 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.
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.