180DC Delft–Rotterdam›Design guide
V13 — Aperture
The headline is a window. Real photography of Rotterdam appears only inside its letterforms, and scrolling opens the aperture until the photograph takes the whole frame.
One idea, carried end to end
Every other variant in this set leans on a structural metaphor — a drawing, a manifest, a polder, a broadsheet, a ledger, a network map. Aperture is the only one whose thesis is optical: the site treats type as a lens onto real places, and treats the act of scrolling as the act of opening that lens.
That thesis had to survive one hard constraint. The branch's differentiator is that it does not invent things, so the "it plays like a video" quality could not come from a video file, a synthetic render, or an AI-generated cityscape. It comes from CSS driving one number across a real photograph.
The device, in three drivers
The entire hero choreography is expressed once, in CSS, as functions of a single custom property --ap-p (aperture progress, 0 → 1). That property is then driven three ways, and because there is only one set of visual rules the three paths cannot drift apart:
Native, no JS
A CSS scroll-driven animation (animation-timeline: scroll(root block)) interpolates --ap-p over the first 150vh. Zero JavaScript involved.
rAF fallback
Where scroll-driven animations are unsupported, ten lines of JS keep the same property up to date on scroll. Same visual, no duplicated choreography.
Nothing at all
With JS off and no native support, --ap-p keeps its initial value of 0.34 — a composed, fully legible resting state. Nothing is hidden or broken.
prefers-reduced-motion: reduce takes the same path as Driver 3: the aperture simply rests, the sticky stage collapses to static, and no animation runs anywhere on the site.
Two decisions that came out of looking at it
The headline never fades out. The first build dissolved the display type once the aperture had opened. On screen it read as a washed-out grey smear rather than a transition — and it meant animating the page's only h1 to invisibility, which is an accessibility failure as much as a design one. The type now stays: it is the window, for the whole scroll.
The frame never gets as bright as the fill. Because the letterforms are filled with the same photograph that lands behind them, there is a scroll position where the headline camouflages itself into total invisibility. The scrim over the background photograph therefore never opens past 0.62 opacity, so the type is always the brighter window. This is the one number in the file that is load-bearing for legibility.
Where the aperture recurs — and where it deliberately doesn't
The masked-type treatment appears exactly twice, both on the home page: the headline, and the "What we do" section header — which is filled with the same hero photograph, so it reads as a callback rather than an unrelated image, and costs no extra bytes because the file is already cached. Interior pages never use it, which is what keeps the aperture feeling like it belongs to the front door.
It is also not used on the mosaic callouts. Photographic fill inside small type is a contrast failure dressed up as craft, and the six service areas are the copy a paying client most needs to read.
Instead the aperture recurs as a gesture: each mosaic tile's photograph opens from a tight crop to full as it enters view, via clip-path: inset() on a view() timeline. Same idea, executed where it doesn't cost legibility.
Build sheet
| Pages | index.html, for-clients.html, for-students.html, mission.html, guide.html, one styles.css |
|---|---|
| Build | Hand-written static HTML/CSS. No framework, no build step, no dependencies at runtime. |
| Signature device | Scroll-driven masked-type aperture hero · glass panel carrying the engagement cycle · irregular photo mosaic whose tiles open from a tight crop. |
| Second register | Interior pages open full-bleed dark with one large Archivo Black headline and minimal chrome — no photographic mask, so the aperture stays unique to the home page. |
| Colour | Verified 180DC greens only, per _brand/BRAND.md: #78B038 for large/decorative use, #4A7322 for AA text on white, #3D6B1C for small text. No invented palette. |
| Type | Archivo Black (display/masked), Archivo 400/600 (body), Space Mono 400/700 (eyebrows, metadata, step numerals). Self-hosted woff2 latin subsets, ~105 KB total. |
| Motion | One thesis-native motion. All of it gated behind prefers-reduced-motion; all of it optional (the site is complete without any). |
| JavaScript | Progressive enhancement only: the --ap-p fallback driver, IntersectionObserver reveals, and the carousel's arrows and dots — which are hidden until JS is present, so no control is ever dead. |
| Imagery | Six real, credited photographs of Delft and Rotterdam. No AI imagery. No stock faces. Nobody presented as our team. See provenance below. |
| Weight | img/ totals ~502 KB across the whole variant; mosaic tiles are lazy-loaded, so a first paint carries the hero only. Under the 1 MB budget. |
Every photograph, sourced and credited
All from Pexels, compressed to WebP with sharp via tools/prep-v13.mjs. Each was opened and looked at before use, to confirm it is a real photograph of the real city rather than synthetic or AI-generated content.
| File | Subject | Photographer | Pexels ID |
|---|---|---|---|
hero-rotterdam.webp | Rotterdam, the Erasmus Bridge over the Maas | Steshka Croes | 5402027 |
tile-rotterdam-skyline.webp | Rotterdam skyline from above | Werner Hilversum | 20053087 |
tile-rotterdam-maas.webp | Rotterdam waterfront across the Maas | Fleur van Deijck | 11661493 |
tile-delft-above.webp | Delft's historic centre from above | George F | 6197871 |
tile-delft-oostpoort.webp | The Oostpoort, Delft | Igor Passchier | 19104574 |
tile-delft-canal.webp | A canal in Delft | Leslie Lankhorst | 7116030 |
tile-port.webp | Port of Rotterdam terminal | Pexels (reused from V2) | — |
Two sourcing notes worth recording. First, Pexels titles one Delft frame as the Nieuwe Kerk when the tower shown is the Oude Kerk; rather than propagate a wrong landmark name on a site whose whole pitch is accuracy, the captions name cities, not churches. Second, several otherwise excellent Port of Rotterdam frames were rejected because they are dominated by third-party corporate liveries (Maersk, COSCO, Evergreen) — V2's own critique round had already established that the photography should be brand-free, and that precedent was followed here.
What is real, and what is visibly reserved
Every factual claim on this variant is carried by the shared source of truth (content-v2v3v7.md, _brand/BRAND.md) and matches the other twelve variants: founded 2019, first multi-city branch, TU Delft × Erasmus Rotterdam, six service areas, two roles (Consultant / Team Leader), two cycles a year (Oct–Jan, Mar–Jun), recruitment in September and January/February.
Cost language is "uniquely affordable" / "low-cost" throughout — never free, pro bono, or €0 — per the client's approved terminology. Board titles are Branch President and Branch Vice-President.
Note on terminology. "Team Leader" is used for the role that leads a consulting team. This reverses the org's own Terminology Requirement document, which lists Team Leader as the disallowed term and Project Manager as the approved one. The conflict was flagged to the client, who confirmed Team Leader is what should ship; this variant follows that instruction, consistently with V2, V7, and V11.
Case studies, committee photographs, member testimonials, the event calendar, and the application portal are all visibly reserved rather than filled with something plausible. One honesty register, used consistently, and quieter than the real content.
Critique rounds
Built 2026-07-26. This variant runs the same discipline as the original ten: three independent fresh-context art-director rounds, each hunting for anything generic, any motion that doesn't earn itself, and any place real craft was substituted with a cliché.
Pre-critique — fixes from the first look at rendered output
Four bugs the first build only revealed once screenshotted at real viewport sizes: (1) the display headline overflowed the right edge at every width, because its measure was set in em against a vw font-size — now set in ch; (2) the headline dissolved to a grey smear at the end of the scroll, and animated the page's only h1 to opacity 0 — the dissolve was removed entirely; (3) the lede, absolutely positioned at the bottom of the stage, collided with the display type — it is now in normal flow beneath it, where a collision is structurally impossible; (4) the mobile header wrapped into three unusable rows — it is now a single non-wrapping strip that scrolls horizontally, with no JS drawer. Two smaller ones: the rotated photo credit was clipped and is now horizontal, and the masked type was muddy on phones because small glyphs sample only a dark patch of the frame, so mobile pulls the zoom back and lifts brightness.
Round 1
Pending — art-director round 1
Round 2
Pending — art-director round 2
Round 3
Pending — art-director round 3