Resilience
Most portfolios assume a clean Chrome window on a fast laptop. This one was tested against the messier reality: real Windows, macOS, Android, and iOS devices across Chrome, Firefox, Safari, Edge, Brave, and Opera, with ad-blockers, password managers, Dark Reader, screen translation, and reduced-motion settings running. This page is the log: the devices it ran on, the defensive patterns it ships, the approaches that failed, and the cross-browser lessons that generalize. Every claim here traces to a commit.
Coverage
Support comes in three tiers. The first is a promise, the second a soft landing, the third an honest line in the sand.
Must work, and gets tested. Current Chrome, Firefox, Safari, and Edge plus their last two major versions, on Windows 10 and 11, macOS 12 and up, current Linux, iOS and iPadOS 16 and up, and Android 12 and up. Desktops, laptops, modern phones (iPhone 8 and up), modern tablets (iPad 6th gen and up). Screens from 360px to 3840px wide, across 16:9, 16:10, 21:9 ultrawide, 9:16 to 9:21 portrait, and 4:3 to 3:4 tablet ratios. Common extensions: uBlock Origin, AdBlock Plus, AdGuard, Dark Reader, 1Password, LastPass, Bitwarden, Google Translate, Grammarly. System settings: reduced-motion, high-contrast, prefers-reduced-data, forced-colors. If you are reading this, you are almost certainly in this tier.
Browsers three to five major versions behind current, older phones (Android 8 to 11, iOS 13 to 15), less common browsers (Brave, Vivaldi, Opera, Samsung Internet, Yandex) riding Chromium compatibility, 32:9 super-ultrawide, and slow connections. Layout and content hold; some of the polish softens.
Internet Explorer, KaiOS, UC Browser, anything more than five majors behind current, text-mode browsers, and screens narrower than 320px. Not tested, not guaranteed. Drawing the line is what keeps the first two tiers honest.
Hardware
Local Playwright is necessary, not sufficient. The load-bearing checks run on real hardware, because a Linux headless browser masks Windows extension behavior, real mobile GPUs, and Safari's rendering (DEC-088).
Five physical devices: a high-end Windows desktop, a flagship Android, two iPhones (one current, one the A12 low-spec floor), and an Apple-silicon Mac. The iPhone XR (A12, 3 GB) is the canonical low-spec target: if a change holds there, it holds across the modern fleet.
| Device | Silicon | OS | Browsers exercised |
|---|---|---|---|
| Windows desktop | Core i7-14700K, RTX 4060 Ti | Windows 11 25H2 | Chrome 149, Edge 149, Firefox 152, Brave 1.91, Opera 148 |
| Pixel 8 Pro | Tensor G3 | Android 17 | Chrome 149, Edge 149, Brave 1.91, Firefox 151, Opera 99 |
| iPhone 14 Plus | Apple A15 | iOS 26.5 | Safari 26.5 |
| iPhone XR | Apple A12, 3 GB | iOS 18.7 | Safari 18.7 |
| MacBook Pro 14 | Apple M1 Pro | macOS Tahoe 26.5 | Safari 26.5 |
Chrome, Edge, Firefox, Brave, and Opera on Windows and Android; Safari on three engines (iOS 18, iOS 26, and macOS Tahoe). The two Safari engines matter because Linux Playwright WebKitGTK does not reproduce their GPU tiling or compositing (DEC-088, DEC-094). The Windows Edge pass ran with Dark Reader and uBlock Origin active, which is how the ad-blocker and dark-theme defenses get exercised against real filter lists rather than a synthetic stand-in.
Real viewport widths run from 828px (iPhone XR) to 3024px (MacBook), with 1920px desktop and 1344px Pixel in between; automated regression runs pin 393px and 1512px. The support target spans 360px to 3840px. Network conditions covered: Slow 4G throttling (Lighthouse), a 150ms-RTT and 1.6 Mbps profile (the inlineCss delivery check), offline via navigator.onLine detection, and Save-Data or low device memory, which trips lite mode.
None of these reproduced in local headless Chromium. Each was found on a device and fixed.
overflow-x: clip guard (Phase 25.7.b).pointer: coarse (WCAG 2.5.5, Phase 25.7.e).clip-path: inset(0 round ...) (Phase 25.10.d, verified on macOS Safari).Hardening
The site is built to coexist with the way people actually browse, not a clean-room ideal. Each pattern below defends against a specific real-world condition, and each lives in the codebase.
@layer base rule collapses animation duration to near zero, and staggered animations are defined only under prefers-reduced-motion: no-preference, so they do not exist when motion is off. The showreel reads matchMedia and pauses instead of autoplaying (Phase 25.7.a, DEC-023).@media (forced-colors: active) pill buttons keep an explicit ButtonText border and their focus rings, so no control disappears when the OS strips backgrounds (Phase 25.6.b).aria-current on the active nav item, and a skip-pulse gated on :focus-visible so it fires for keyboard users but never on a mouse click into the page (DEC-096).@media (pointer: coarse) (WCAG 2.5.5), which fixed footer mistaps found on the Pixel and iPhone XR (Phase 25.7.e).<noscript> block hides the interactive contact form and shows a direct email link, so a scripts-blocked visitor gets a working path instead of a dead form (Phase 25.6.a).<video> renders with no src; a mount effect attaches the tier. No-JS and reduced-motion visitors get the poster image and zero video bytes (DEC-094).msarib- prefix (130 of them) after a generic .back-to-top was hidden by a uBlock Origin cosmetic filter for Windows users, with no console error to explain it (DEC-088).data-msarib-lite on <html> before first paint when Save-Data is on or deviceMemory is 2 or less; CSS then drops the decorative atmosphere and glows, and the showreel serves poster-only (DEC-094).backdrop-filter radii are capped under pointer: coarse (50 to 24px, 20 to 12px), so old mobile GPUs stop paying full area-times-radius per frame (Phase 28).transform only, which stays on the GPU compositor with no per-frame repaint (DEC-028); the glow canvas throttles to about 10fps because an 80px blur hides the difference (DEC-022); requestAnimationFrame loops pause on hidden tabs (Phase 27.1).navigator.onLine catches offline submits, and a Turnstile error or timeout surfaces the email path so a blocked challenge never dead-ends the form (DEC-062, Phase 25.5.b).llms.txt, feed.xml, and the other content files are force-static so they never try to read the filesystem at request time on serverless (DEC-082).main { overflow-x: clip } is one choke point bounding every decorative bleed, after a recurring Safari bug where a bleed pushed the nav off-screen and forced a zoom-out. A body-level clip did not hold because Safari's visual viewport ignores it (DEC-096).filter: blur() and seams it into rectangular blocks (DEC-094, DEC-097).clip-path: inset(0 round ...) holds the radius through the transform (Phase 25.10.d).color-mix() (Chrome 111, Safari 16.4, Firefox 113); a @supports not (color-mix ...) block gives the one dependent gradient an rgba fallback on older engines.darkreader-lockmeta opts it out of Dark Reader's recoloring, preserving the intended gradients while native contrast still meets WCAG (Phase 25.3).translate="no", and the layout absorbs longer languages like German without overflow (Phase 25.4).data-1p-ignore, data-lpignore, data-bwignore, and data-form-type="other", so password managers (1Password, LastPass, Bitwarden) autofill name and email without prompting on the message body (Phase 25.5.a).Proof
A green test run is only worth what it actually proves. These are the checks the site runs, and what each exists to catch that the naive alternative misses.
color-mix(in srgb, C N%, transparent) is byte-identical to the old rgba), and pixel-diffing on this WSL2 setup is noisy. Used across the Phase 29.3 to 29.5 token migrations, color through typography through spatial (DEC-083, Phase 29.3-T1).msarib.dev, not localhost (DEC-092).Dead ends
The honest part. Each of these was tried, shipped or prototyped, and did not work. What replaced it, and the lesson, matter more than the miss.
The atmospheric wash and the media glows showed blocky, tiled edges on real macOS and iOS Safari, never on Chrome and never in Linux Playwright. The working theory was the obvious one: the blur radius was simply too large for WebKit. Phase 27.2 dropped it from 100px to 60px, then 27.2.1 to 40px, which is the empirically clean floor on iOS.
Real macOS Safari still seamed at 40px. The artifact shrank with the radius but never resolved, and Playwright's WebKitGTK rendered every value cleanly, so it could not gate the fix. Both changes were reverted (cb3accb) and the question moved from "what radius" to "what mechanism" (DEC-091). The lesson: when an artifact scales with a variable but never disappears as you tune it, the variable is a symptom, not the cause. The real cause was WebKit's tile rasterization, covered in Durable insights below.
Once tiling was the suspect, the first fix laid each glow out at 30% size, blurred it 19px, and scaled it up 4.2 times, so the blurred layer would fit inside a single GPU tile. On paper the footprint and the softness matched the old 80px blur exactly, and it passed every headless check. On real macOS Safari the glows seamed again.
WebKit rasterizes a composited layer at its on-screen size, so blur(19px) under scale(4.2) runs an effective 160px kernel on a roughly 2000px raster and recreates the exact seams the trick was meant to dodge. The static feature and portrait glows moved to a Cloudinary-baked blur (e_blur server-side, zero runtime filter), pixel-calibrated to within about 1.7 of 255 against the reference (021d19f, DEC-097). The lesson: a transform does not change the pixels WebKit actually rasterizes. On-screen scale is what counts.
The showreel glow is a live video, so it cannot use a static baked asset. The candidate computed a pixel-exact box Gaussian on the canvas each frame, and automated pixel-diff scored it at about 1.9 of 255 against the reference, the best of any option. On Sarib's real hardware it rendered as a sharp, flickering copy.
The cause was Chromium's documented heuristic that switches a canvas backend from GPU to CPU after repeated unhinted getImageData, plus per-frame readback stalls on the displayed canvas. Headless software rasterization never exercises that heuristic, which is why it measured clean. It was reverted to the reference CSS blur; the surviving candidate does its pixel work on a never-displayed offscreen canvas created with willReadFrequently: true, so the shown canvas stays GPU-backed (DEC-097). The lesson: headless verification cannot certify live-canvas pixel work, and real-hardware iteration is mandatory.
Field attribution named the showreel poster as the mobile LCP, so the plan added a responsive poster so phones would pull a smaller derivative. The premise was that a w_1280 poster is oversized on a 390px phone. Playwright iPhone 13 emulation showed the browser fetching w_1280 regardless.
A srcset candidate is chosen by device pixels, which is CSS pixels times the device pixel ratio. A 390px slot at DPR 3 needs 1170 device pixels, so a 720w candidate is too small and the browser upgrades to 1280w; only DPR 1.84 or lower would have picked the smaller tier. The responsive-poster layer was reverted, since a single large tier is correct for a hero-scale image on modern mobile (Phase 27.5.3). The lesson: "oversized" is a device-pixel claim. Compute width times DPR before optimizing.
One glow approach set ctx.filter = 'blur(...)' and drew the source through it. It rendered a raw, unblurred stretch on Safari. CanvasRenderingContext2D.filter is absent from every shipped Safari through 18.5 (WebKit bug 198416); it landed only in a Technology Preview. Headless Chromium and WebKitGTK both implement it, so it passed locally. It was replaced with a multi-pass drawImage resampling that uses no canvas filter at all (DEC-097). The lesson: a canvas 2D feature can work in every engine you can automate and still be missing from shipped Safari. Detect, do not assume.
The atmospheric gradient started as a sibling element with backdrop-filter, meant to blur the SVG circles behind it. It only ever blurred the flat parent-section background, never the circles. backdrop-filtersamples the backdrop within the element's own stacking context, and the sibling boundary put the circles outside it. It was replaced with an output filter: blur on the SVG itself (DEC-077), then replaced again by radial gradients once tiling was understood. The lesson: backdrop-filter is bounded by stacking context and cannot reach across a sibling boundary.
The original design carried a footer toggle between PP Right Grotesk and PP Neue Montreal, with the choice persisted in localStorage. The alternate font files were never added, so the toggle switched between one real font and a missing one. It cost a client island, a localStorage dependency, an SSR-hydration correction, and a second full type scale, all for a feature with no second font behind it. The toggle and its island were removed for one honest type system (DEC-100). The lesson: do not ship the switch before the thing it switches to.
Lessons
Browser and device facts that generalize past this site. Each one cost a real investigation and is cited to where it was pinned down.
WebKit rasterizes filter: blur() in GPU tiles of roughly 512px and clamps the Gaussian kernel at each tile edge, so any radius past the tile margin makes adjacent tiles disagree and seam into rectangles. The effect scales with radius, layer size, and device pixel ratio, so a Retina display doubles the effective radius. Linux WebKitGTK uses a different tiling path and never reproduces it, which is why it took real macOS Safari to find. This is the root cause behind the blur-radius chase above (DEC-094).
A blurred layer under a transform is rasterized at its final on-screen size, so blur(19px) at scale(4.2) runs an effective 160px kernel. Laying a layer out small and scaling it up does not shrink the kernel WebKit computes, so it cannot be used to dodge the tiling above (DEC-097).
Firefox clamps blur() radius to 100px regardless of the declared value (Bugzilla 1530810). A larger decorative blur reads differently there and does so silently, because the property still parses and resolves (DEC-097).
After repeated getImageData without willReadFrequently, Chromium switches the canvas backend from GPU to CPU, and per-frame readback of a displayed canvas stalls. Pixel work belongs on a never-displayed offscreen canvas created with willReadFrequently: true, leaving the shown canvas GPU-backed. Headless software rasterization never exercises the heuristic, so this only shows up on real hardware (DEC-097).
On a cold cache, Safari can hand a video's decode surface to a canvas and leave the video element's own layer black until a repaint (WebKit 153588 and 237424). The modern fix path is requestVideoFrameCallback, driving the canvas only after the video has painted. This one is still open on this site (see In flight) (DEC-097).
A browser picks a srcset candidate by device pixels, which is CSS pixels times the device pixel ratio. A near-100vw image in a 390px slot at DPR 3 needs 1170 device pixels, so any candidate under 1170wis skipped. Responsive tiers below the slot's device-pixel width add complexity for no fetch reduction; they pay off only for images whose CSS width already sits well below the thresholds (Phase 27.5.3).
Stacking effects in a single component, for example e_blur:2000,e_saturation:35, silently drops all but one. They have to be chained as separate components, e_blur:X/e_saturation:Y. A glow shipped completely unblurred before this was understood (DEC-097).
A body-level overflow-x: clippropagates to the viewport, which Safari's visual viewport ignores, so a decorative bleed still widens the zoomable canvas; a real box clip on main constrains it (DEC-096). Separately, overflow-x: hidden coerces overflow-y to auto and creates a finger-pannable nested scroll container on touch, which clip does not (DEC-084).
CSS weights 600 and 700 with no matching cut in the font family are synthesized by the browser as faux-bold rather than failing outright. The type system tokenizes them at that exact render, so the synthetic weight is visible and decidable instead of hidden (DEC-100).
Open
Not everything is closed. These are the open items, with what each one needs to resolve.
drawImage(video) compositing race; the fix path is requestVideoFrameCallback. It does not reproduce in Playwright, so it needs a real-device iteration session.drawImage lerp cascade and a pixel-exact offscreen Gaussian. Windows Chrome and the iPhone XR pass both; the MacBook verdict decides which is promoted to default, after which the flag and the losing path are deleted.p=quarantine, upgraded from p=none. It moves to p=reject once the aggregate reports confirm only legitimate senders, a manual Cloudflare DNS edit.