How the Atlas was made

A standalone concept for LMH Law, PLLC — art-directed like a diplomatic passport: an engraved dot-globe of real coastlines, guilloché seals generated from spirograph math, foil-stamped typography, and every word of copy carried verbatim from the firm's live site.

01 · The premise

Immigration is the practice of crossings, and the passport is its most beautiful printed object: navy leather, gold foil, engraved security patterns, stamps. The whole site is staged as that document — a dark cover, ivory interior pages, circular seals, typewritten docket labels, and one drop of stamp-red. Nothing on the page invents a legal claim; every sentence is the firm's own approved copy, and every link lands on the real site (lmhlawpllc.com). The page ships noindex so a concept can never compete with the practice it celebrates.

02 · The engraved globe

The centerpiece is a 10,872-point globe of real Natural Earth coastlines — no texture, no model. A one-time build script rasterizes the land polygons into an even spherical grid:

// build-land.mjs — runs once, ships as a 96 KB JSON
for lat in −58…84 step 1°:
  lonStep = 1° / max(0.22, cos(lat))   // even density on the sphere
  if geoContains(naturalEarthLand, [lon, lat]) → keep [lon·10, lat·10]

In the shader, far-hemisphere dots fade (smoothstep on the view dot product) so the sphere reads as an engraving, not an x-ray. A 20° graticule, a fresnel gold rim, and five great-circle arcs complete it — each arc slerps from a world city to a U.S. port of entry, draws itself in via setDrawRange, lands with a ring pulse, fades, and respawns somewhere new. Every arc is a client's crossing.

03 · One scroll, five acts

The canvas is fixed and z-stacked between the section backgrounds and the content, so one globe serves the whole document. A keyframe table — rebuilt from the real DOM offsets on every resize — drives its position, scale, opacity, and palette per scroll position:

cover     x +0.98  scale 0.94  alpha 1.00  gold on navy
pages     x  0     scale 1.60  alpha 0.07  ink watermark on ivory
we-argue  x −0.95  scale 1.35  alpha 0.35  gold, left of the text
attorney  x  0     scale 1.70  alpha 0.05  watermark again
final     x  0     scale 0.92  alpha 0.95  center seal, full return

Scroll also spins the earth (rotation.y += progress · 2.4): reading the page turns the world.

04 · Security printing, in SVG

05 · Art direction

cover navy
page ivory
foil gold
stamp red
ink

Marcellus (an inscriptional roman — Trajan-column energy at 13 KB) sets the foil headlines; Lora carries text and the italic counter-voice; Courier Prime types the docket labels. The foil itself is an animated gradient clipped to the glyphs. Texture: SVG grain at 6%, hairlines at 14% — the leather, not the sticker, of luxury.

06 · Iteration log (three passes)

Pass 1 — correctness

Headless framebuffer ASCII-renders confirmed the globe's rim, continents, and framing; found the land dots under-weighted (raised size + facing floor), the sphere kissing the viewport top (camera pulled to z 3.5), and — the big one — the cover's opaque background sitting above the canvas in the stacking order. Restacked: backgrounds → globe → content.

Pass 2 — composition

Display type was sized against the viewport and clipped inside its column ("AMERICAN" lost its N) — re-clamped to the column. Globe reframed to sit fully in view, initial rotation turned so the continents face the reader, figure-caption given a shadow to sit on the engraving, final-act lead-in tightened, scroll-choreography verified numerically at all six anchors.

Pass 3 — ship-shape

375 px audit (zero overflow, nav collapses to the one CTA, oval and ledger reflow), reduced-motion path (no spin, no foil sweep, no reveals), zero-size-viewport guard verified, console clean, weights checked (~96 KB land + ~230 KB fonts + 7 KB CSS/JS gz), deployed and re-verified live.

07 · Reproduce it

atlas/
├── index.html        # cover · transit · pages · argue · attorney · ledger · process · final
├── css/main.css      # foil, stamps, ledger, ovals, reveals
├── js/main.js        # globe + arcs + keyframes + spirograph SVG generators
├── assets/land.json  # 10,872 coastline points (Natural Earth 50m)
└── fonts/            # Marcellus · Lora · Courier Prime (self-hosted woff2)

# regenerate the coastlines:
npm i d3-geo topojson-client world-atlas@2 && node build-land.mjs