Büro (Bürocratik) teardown

2026-10-21 · URLs read: https://www.burocratik.com/ , https://www.burocratik.com/work , https://www.burocratik.com/studios , https://www.burocratik.com/recognition (HTML, inline CSS and every JS chunk they load, each fetched once with a desktop user agent; 11 headless capture runs on fsit2) · serves inspiration rows 6, 9 and 15 of design/inspiration/INSPIRATION.md.

Checked by a verifier on 2026-10-22: corrections are made in place and listed in VERIFY.md.

1. What the owner liked

2. The stack

Layer Finding Evidence
Framework Nuxt 2, statically generated (nuxt generate), Vue 2.7.16, vue-router 3.6.5, vue-meta 2.4.0, core-js 3.38.0, webpack 4 data-n-head="ssr" on the vue-meta tags in the head (25 of the 45 head tags in the served HTML; the preload links, the title, the style block and three scripts carry none); window.__NUXT__ in /_nuxt/static/1791840994/state.js plus per-route payload.js and manifest.js; Rr.version="2.7.16", ee.version="3.6.5", version:"2.4.0" (vue-meta), version:"3.38.0" (core-js) in 34b7000.js; window.webpackJsonp runtime in 4a88b9a.js. The static folder name 1791840994 is a Unix time, 2026-10-12 21:36 UTC, the build date. The exact Nuxt 2.x release is not printed anywhere.
CMS Sanity og:image on cdn.sanity.io/images/zksivtxz/production/…; CSP frame-ancestors 'self' http://localhost:3333 burocratik.sanity.studio; a ?preview query plugin that switches on Sanity preview (in f4b42a5.js). Page images are re-hosted at build time as /_nuxt/image/<hash>.<ext>.
Hosting and CDN Vercel Response headers server: Vercel, x-vercel-cache: HIT, x-vercel-id: pdx1::…, age: 610885, last-modified: Thu, 15 Oct 2026.
Animation GSAP 3.12.2 with ScrollTrigger (and its Observer), CustomEase and MotionPathPlugin; no GSAP SplitText: text is split by the site's own SplitText Vue component; nine Material 3 easings registered as m3.* .version="3.12.2" in e6fc914.js; registerPlugin(l.CustomEase) then create("m3.emphasized", …), create("m3.standard","0.2,0,0,1") and so on (sources/page-flow.js.txt); registerPlugin(d.MotionPathPlugin) in the cursor module. GSAP is not a global: it is webpack module 0, reachable through window.webpackJsonp (this is how the slow-motion captures were made). The only modules carrying "3.12.2" are the core, ScrollTrigger with Observer, CustomEase and MotionPathPlugin; every module that names SplitText imports it as a Vue component (shots/verify/extra/meta.json).
Scroll Lenis 1.0.42 on the window, duration: 1, wheelMultiplier: 1.1, nothing else overridden window.lenisVersion="1.0.42" in e6fc914.js; scroller component options in sources/page-flow.js.txt; <html class="lenis lenis-smooth">, which becomes lenis-stopped while the menu is open (sources/capture-meta/desktop-menu-open-close.json, pageState). The menu content carries data-lenis-prevent so it scrolls natively.
Scrollbars Native and unstyled on the page; hidden only inside the menu sheet and some nested lists The only scrollbar CSS is .no-scrollbar{scrollbar-width:none} with .no-scrollbar::-webkit-scrollbar{width:0;height:0} (thumb and track transparent). Sliders draw their own 2 px track in the DOM (._slider > [data-slider-scrollbar], black thumb, cursor: grab), which is not a scrollbar style. The site measures the real scrollbar width into --sbw and lays out against --100vw: calc(100vw - var(--sbw)). The captures run Chromium with --hide-scrollbars, so no shot shows the page scrollbar.
3D and canvas three.js r171 on /work, /recognition and /studios, not on the homepage, whose hero is video const r="171" and THREE.WebGLRenderer strings in lazy chunk 89d5fef.js (594 KB); window.__THREE__ is "171" on all three pages and unset on the homepage. Each of them has a .webglContainer and loads its own web worker: Words.worker on /work, Points.worker on /recognition (a full-viewport canvas with a 2880 × 1800 backing store for 1440 × 900 CSS px at device pixel ratio 1, the dot field under "Move that mouse, shake it! Yeah!!"), Lines.worker on /studios. Home probe: 6 <video> elements, 2D canvases only (canvas.wave line dividers inside .line-divider, one 175 px canvas). Rive runtime @rive-app/canvas 2.21.6 for small animated assets that play on mouseenter; its webpack module also holds the small textured-quad WebGL program (uniform vec4 mat) of the vendor chunk.
Sound Pizzicato.js plus an $audio plugin d.Sound, d.Group, d.Effects.Reverb and friends in e6fc914.js; $audio enables on the first click, disables on window blur and comes back on the next focus, toggles with Ctrl+A (key codes 17 and 65); the photo trail plays ./audio/image-spawn.mp3.
Fonts Commercial Type's Graphik, self-hosted variable woff2/woff, upright and italic, under the family name "Commercial Gräphik Web" @font-face in the inline CSS; probe fonts: "Commercial Gräphik Web 400 normal / italic".
Analytics Umami Cloud and Google Analytics 4 <script defer src="https://cloud.umami.is/script.js" data-website-id=…>; gtag/js?id=G-52YF8HGWG2.
signature.js A console signature and nothing else: logs "Made by Büro 🤘" as styled badges (white on blue #0020f4, then on dark #242424) in Chrome and Firefox, plain "Made by Büro" elsewhere Full file (427 bytes) in sources/signature.js.txt.
Easter eggs An ASCII banner "B Ü R O … ♥ MADE BY BÜRO: BUROCRATIK.COM YEAR: 2024" as the first HTML comment; Ctrl+G toggles a 24-column grid overlay (._grid-preview); two global ::selection rules, blue #105df1 and then black, so the later one wins and selected text is white on black (computed ::selection background rgb(0, 0, 0)) HTML head; f4b42a5.js; inline CSS.
Page transitions GSAP timelines in the page component, no View Transitions Probe: viewTransitionCSS: 0 (the hasStartViewTransition: true flag is just the browser).

3. Component playbooks

3.1 The persistent bar and the sheet behind the plus

What it is in pixels (computed values, sources/capture-meta/desktop-bar-states.json, phone-bar-menu.json, desktop-menu-open-close.json):

Desktop 1440 × 900 Phone 390 × 844
Bar 575.5 × 46 px at x 432, y 823.6, so 30.4 px above the bottom edge 342.5 × 46 px, 23.75 px side gutters, 24 px above the bottom
Width rule --navbar-width-cols of a 24-column grid: 10 columns, 12 under 1290 px, 18 under 1023 px, 22 under 743 px 22 columns
Bottom offset clamp(24px, 21.621px + 0.61vw, 32px) 24 px
Skin radius 20 px; background: linear-gradient(rgba(0,0,0,.85), rgba(0,0,0,.85)), rgba(255,255,255,.4); backdrop-filter: blur(18px). It takes a tint from whatever is behind it: near black over white pages, navy over the blue hero (bar-02-pointer-on-bar.png) same
Inside padding 0 16 px, gap 14 px; glyph 24 px; 8 px gap; message in Graphik 17.6 px (clamp(16px, 15.415px + 0.15vw, 18px)), line-height 1.2, letter-spacing -0.04em, white glyph, message, plus; no chip
Chip white pill, radius 12 px, 105.3 × 28.8 px for "Homepage", sized to its label ("Work" is narrower, nl-01-before.png) not rendered ($screen.width > breakpoints.xs guard)
Plus 18 × 18 px, two 2 px white bars same
Sheet open 575.5 × 770.5 px, grows up from the bar to y 99 342.5 × 675 px, top at y 145

DOM (client-rendered, trimmed; full dump in sources/capture-meta/desktop-bar-states.json):

<nav class="_navbar no-select" data-motion-fallback>                      <!-- fixed, z 9, cursor:none, v-pointer:pointershift -->
  <div class="fixed top-0 left-0 w-full-vw h-full-vh" inert></div>        <!-- full-screen click catcher, live only while open -->
  <div class="click-catchers" aria-hidden="true"><div></div><div></div></div>
  <div class="bottom-click-catcher fixed bottom-0" aria-hidden="true"></div>
  <div class="persistent-bar">
    <div class="persistent-bar-main flex justify-space-between align-center w-full h-full">
      <div class="bot-container m-c w-full"><div class="_bot">
        <div class="icon relative flex m-c">
          <span data-name="burocratik" class="_icon active m-t"><svg …/></span>
          <span data-name="burocratik" aria-hidden="true" class="_icon aux m-t"><svg …/></span>
        </div>
        <div class="p-small whitespace-nowrap flex-grow-1"><div class="msg relative w-full m-c">
          <div class="active"><span class="m-t">We </span><span class="m-t">are </span><span class="m-t">Büro </span>… 10 slots</div>
          <div class="aux" aria-hidden="true"><span class="m-t">We </span>… 10 slots</div>
        </div></div>
      </div></div>
      <div class="active-page"><div class="_root-page-name p-small relative m-c -e0">
        <div class="background absolute inset-0 m-t"></div>
        <div class="label relative inline-block m-c whitespace-nowrap"><span class="m-t">Homepage</span>
          <span class="aux absolute left-0 top-0 m-t" aria-hidden="true" inert>Homepage</span></div>
      </div></div>
    </div>
    <button aria-label="Open/close menu" class="open-close-button">
      <div data-open="false" data-theme="light" class="_open-close-icon"></div>
      <span>Open/close menu</span>                                        <!-- invisible hit area the size of the whole bar -->
    </button>
  </div>
  <div class="menu" inert>
    <div class="navbar-background blurred-background"></div>
    <div class="menu-content-container"><div class="menu-content no-scrollbar" data-lenis-prevent>
      <div class="menu-header">glyph, "We are Büro" tagline, Let's talk pill</div>
      <ul class="menu-pages p-large"> rows: thumbnail + label, children (Branding, Naming, Book) </ul>
      <ul class="menu-socials p-tiny"> LinkedIn, Instagram, Facebook, Büro on X </ul>
    </div></div>
  </div>
</nav>

The .m-c / .m-t pair is the site-wide mask: .m-c{overflow:hidden; margin-bottom:-.16em; padding-bottom:.08em} around .m-t{display:inline-block; will-change:transform}. Every rolling text on the site is a .m-t moved by yPercent inside a .m-c.

How the message "rolls": it is a message stack, not a loop. The duplicated .active / .aux spans are two layers of the same ten word slots. The bar's line is the top of a stack kept by a $bot store (sources/bar-bot-message.js.txt):

The plus and the click area. The button's <span> is an invisible box calc(navbar-width + 16px) wide and the 18 px button's height plus 32 px (591.5 × 50 px at 1440), offset right -24 px and top -16 px, so it overhangs the 46 px bar by 8 px a side and 2 px top and bottom, and the bar's overflow: hidden clips it to the bar: the whole bar is the button. Hovering anywhere on it swaps the line to "Open menu" and shows the tilting-hand cursor; clicking anywhere opens the sheet. There is no proximity or "awake" state and the bar never shrinks on scroll (bar-04-scrolled.png). Open, the icon rotates 90° (0.35 s cubic-bezier(.645,.045,.355,1) after 0.05 s) while one bar slides out by its own width and fades to 0.5 (0.25 s), leaving a minus at the bottom right of the sheet (menu-01-open.png).

The chip shows the root page: Homepage, Studios, Recognition, Work (evals chip-studios, chip-recognition). It holds its label twice (.label .m-t and .aux) so it can roll like the message. After the sheet closes, its white background slides back in from the right (xPercent 101 → 0, 1 s expo.out) and the label rises (yPercent 101 → 0, 0.55 s power3.out, 0.225 s later).

Opening the sheet (GSAP timeline, sources/bar-menu-motion.js.txt; frames in menu-open-slowmo-sheet.png, captured at 4 % speed):

t (s) What moves Duration and ease
0 message and chip fade out 0.1 s
0 .navbar-background height 46 px → 100 % of the sheet, the dark blurred skin growing upwards out of the bar 0.65 s m3.emphasized (M0,0 C0.05,0 0.133,0.06 0.167,0.4 C0.208,0.82 0.25,1 1,1)
0 .menu-content yPercent → 0; opacity → 1 0.65 s m3.emphasized; opacity 0.23 s power3.in after 0.03 s
0.05 the page recedes: --blr-p 0 → 1 drives scale(1 - --blr-s · p) and opacity: 1 - .333p on .page-content, with --blr-s = 2 × margin / width (0.0245 at 1440 px, so the page scales to 0.9755), black bars and 20 px rounded top corners growing in at the page's edges (the black is the ._page background and its blur mask; body stays transparent); the page becomes inert, Lenis stops, Escape is pushed on a key stack 0.6 s m3.standard (0.2, 0, 0, 1)
0.1 horizontal dividers draw from the left, vertical dividers from the top 2 s expo.out, stagger 0.1 s; vertical ones 0.4 s later
0.3 page labels rise row by row 0.6 s power3.out, stagger 0.05 s
0.3 links become clickable

Note that the "blur" behind the sheet is the sheet's own backdrop-filter; the page itself is not blurred, it shrinks by one grid margin and dims to two thirds (menu-02-hover-work.png shows the black frame and rounded corners).

Closing (Escape, the minus, or a click outside): skin height back to 46 px (0.52 s power3.inOut), content yPercent → 100 (0.49 s power3.inOut) and opacity → 0 (0.3 s), page recede reversed (0.52 s power3.inOut); at 0.3 s the message and chip come back with their enter tweens (menu-close-realtime-sheet.png frame 00 shows the skin mid-collapse; menu-close-run2-sheet.png ends on "Open menu" because the pointer still rests on the bar).

Inside the sheet: hovering a page row widens its thumbnail from about 87 to 100 px at 1440 px (clamps of 77 to 90 and 90 to 102 px; 0.3 s cubic-bezier(.2,0,0,1)), nudges the label 8 px right (0.2 s cubic-bezier(.77,0,.175,1)) and slides a white left-to-right gradient at 2.5 % opacity across the row (menu-02-hover-work.png). Child links (Branding, Naming, Book) sit in a grid whose hovered column grows to 1 + n/7 fr while its label fades to 0.66 (menu-03-hover-child-branding.png). The current page is dimmed (filter: brightness(.5)) and not clickable. Social links nudge 0.5em on hover (0.175 s).

Load: the greeting becomes the bar. On a fresh load a black loader says "Hello", rolls it out, then "We are Büro" with the glyph (icons cycle every 260 ms while assets load). When the page is ready, the loader timeline (sources/page-flow.js.txt):

  1. Lifts the whole bar up to the greeting's height (navbar y = -(bar message y - greeting y)), so the bar's message slot sits on the greeting line.
  2. Slides the greeting sideways onto the bar's message slot (expo.inOut, about 0.7 s).
  3. Drops the black curtain away (y: 101%, 0.95 s expo.inOut, from 0.15 s).
  4. Glides bar and greeting down together to the bottom edge (both 0.65 s expo.out, from 0.55 s).

The bar's "We are Büro" is the greeting handed down. This is the owner's "start in the center, then move to the bottom", already built. The frames show the greeting before and the docked bar after (intro-home-slowmo-sheet.png, intro-recognition-realtime-sheet.png); the glide itself is read from source.

The bar becomes the video player. Pressing Play on a hero video morphs the bar into the player's control bar: the skin scales to the controls' width (0.363 s power4.inOut), the persistent bar fades, play, label, progress and timestamp roll in with the same enter tweens as the message (source only, sources/bar-menu-motion.js.txt neighbour code in f4b42a5.js; not captured).

Phone. Same skin, 46 px tall, full width minus 23.75 px gutters, 24 px above the bottom; no chip; no hover messages and no custom cursor ($screen.touch guards); the sheet's header drops the tagline under 743 px (phone-02-menu-open.png). A long intersection message is not truncated and runs under the plus (phone-bar-rest-vs-long-message.png).

Accessibility and reduced motion. aria-label="Open/close menu"; the closed sheet is inert; the .aux copies are aria-hidden; Escape closes. The message line is not a live region, so screen readers never hear the bar talk. There is no prefers-reduced-motion rule anywhere in the CSS or JS. :focus{outline:0} removes focus rings site-wide. Before JavaScript mounts, data-motion-fallback lets CSS show or hide the sheet by [inert] without animation.

Rebuild for ETS27 (library-agnostic): 1. One fixed element: skin layer (absolute, radius 20, dark at 85 % over backdrop-filter: blur(18px)), a row with mark, message slot, chip, plus. Size it from the layout grid, not a fixed pixel width. 2. A message store with say({icon, text}) → undo: a stack where the top wins. Wire it to hover (pointer devices only), to an IntersectionObserver band just above the bar, to visibilitychange or window blur, and to the end of the page. This is item 14's "the bar speaks for the canvas", already working at Büro. 3. Roll text with two stacked layers of word spans inside an overflow:hidden mask; animate translateY per word with a small stagger (old up and out in 0.3 s, new up and in over 0.6 s). GSAP, Motion (motion.dev) animate with stagger, or the Web Animations API all do it; SplitType or GSAP SplitText can make the spans. 4. The sheet is the same skin growing in height from the bar (animate height or, cheaper, clip-path: inset() or scaleY with counter-scaled content), content sliding up 100 % → 0, labels rising with a stagger, dividers drawing with scaleX from the left. Use the Material 3 emphasized curve for the grow. 5. Recede the stage instead of blurring it: scale by twice the margin over the width, opacity 0.67, rounded corners, inert, scrolling stopped. 6. For the ask field: keep the plus and the field as separate hit areas. Büro's whole-bar button would swallow clicks meant for an input. 7. Add what Büro lacks: aria-live="polite" on the message slot (throttled), visible focus, and a reduced-motion path that swaps text without movement.

Gotchas. The backdrop-filter over playing video is expensive: in our headless capture a frame took about 0.5 to 0.7 s (median) with the sheet closed and 1.8 to 4.2 s with it open. The whole-bar hit area (see 6). Message length on phones. Hover-only messages mean touch users only ever see section and footer messages.

3.2 The newsletter in two sentences

What it is in pixels (sources/capture-meta/desktop-newsletter.json, phone-newsletter.json):

DOM after typing (sources/capture-meta/desktop-newsletter.json, formAfter, with the data-hidden="true" flags that the button and the consent carry before typing put back in):

<form class="_newsletter">
  <div class="submit-container relative">
    <p class="p-small">Psst Psst. Wanna get Spammm?</p>
    <div class="input-container">                                   <!-- flex row, gap = grid gap; column under 1023 px -->
      <fieldset name="email" class="_newsletter-email-field">
        <input type="email" autocomplete="email" class="p-small" placeholder="Give me your e-mail.">
      </fieldset>
      <button data-hitarea class="_newsletter-button relative p-small" data-hidden="true">  <!-- attribute removed once typed -->
        <span class="_underline"><div data-underline-line class="motion"></div><div data-underline-line class="-clone m-t"></div>
          <div data-underline-slot><span>Send</span></div></span>
      </button>
    </div>
    <fieldset name="privacy-check" class="_form-checkbox-field newsletter" data-hidden="true">  <!-- absolute, bottom -35px -->
      <label><input type="checkbox" class="hide-input"><div class="tick"></div>
        <div class="p-tiny"><p>By submitting, you agree to our <a href="/privacy-policy">Privacy Policy</a>.</p></div></label>
    </fieldset>
  </div>
</form>

Behaviour (nl-states-crops.png, then nl-01, nl-02, nl-03):

Accessibility. No <label> and no aria-label; the placeholder is the only name and disappears on typing. There is no focus style, because :focus{outline:0} is global. Only the consent checkbox has a :focus-visible ring (3 px at 30 % black).

Rebuild for ETS27: plain HTML, almost no JS.

<form class="nl"><p>Line one, in ink.</p>
  <input type="email" name="email" autocomplete="email" placeholder="Line two, the grey one." aria-label="Email address" required>
  <button>Send</button><label class="consent"><input type="checkbox" required> … privacy policy</label></form>
.nl p, .nl input { font: inherit; letter-spacing: inherit; color: inherit; }
.nl input { border: 0; padding: 0; background: transparent; outline: 0; width: 100%; caret-color: currentColor; }
.nl input::placeholder { color: currentColor; opacity: .5; }
.nl input:placeholder-shown ~ button, .nl input:placeholder-shown ~ .consent { opacity: 0; pointer-events: none; }
.nl input:focus-visible { text-decoration: underline 1px; text-underline-offset: .2em; } /* the focus cue Büro lacks */

The :placeholder-shown sibling rule does Büro's show-on-type with zero JS. Post to Zpryme's list (Büro's stub posts nothing), write the two lines in the mind's voice, and with the marker look (item 8) let the caret appear in the grey line.

Gotchas. Keep line 2 one line long at every width (Büro's is 220 px, so a long address scrolls inside it). Keep the reveal from shifting layout: Büro positions the consent absolutely at -35 px. Autofill paints a background: set input:-webkit-autofill { -webkit-box-shadow: 0 0 0 1000px var(--paper) inset; }.

3.3 The custom cursor

What it is. One div._pointer (sources/pointer-cursor.js.txt, DOM in sources/capture-meta/desktop-bar-states.json, pointerDom):

Mechanism (all from source, states confirmed by the evals cursor-over-hero: eyes, cursor-over-bar: pointershift, cursor-over-card: pointershift, cursor-off-card: none):

Where it shows. The ranking cards are on the homepage, not on /studios or /recognition: four 78 × 116.5 px image links, 10 px apart, in ._manifesto .accolades under "Our Accolades" (cursor-01-hand-over-card.png). They and the bar use the tilting hand. Award names on /recognition (._award), event buttons and some footer links use the plain hand; the hero video uses the eyes (bar-01-rest-eyes-over-hero.png, menu-04-closed.png); sliders use grab. The probe counts 437 elements with cursor: none on the homepage and no url() cursors: it is all DOM, no CSS cursor images. Crops of the three looks: cursor-hand-eyes-pressed-crops.png.

Phone. Never shown (media query and $screen.touch guards).

Accessibility and reduced motion. Decorative and pointer-only; keyboard users are unaffected. No reduced-motion handling for the tilt or the blinking.

Rebuild for ETS27: 1. Draw the states in the site's hand (marker), each as an inline SVG inside one fixed, pointer-events:none element, with the hot spot planned in the drawing. 2. Mark targets with data-cursor="hand", data-cursor="eyes" and so on, and set cursor:none on exactly those selectors. Delegate pointerover / pointerout from the document to keep a stack. 3. Move the element per frame with translate3d from the last pointermove, and react through small transforms (tilt from velocity, pupils, blink). 4. Gate everything on (hover:hover) and (pointer:fine) and prefers-reduced-motion.

GSAP quickTo or Motion's animate handle the tilt and settle. Plain CSS handles state switching ([data-cursor=hand] > .hand { scale: 1 }).

Gotchas. cursor:none and the drawn cursor must cover exactly the same elements, or the visitor gets two cursors or none. Native controls (selects, iframes, text fields) keep the system cursor. Screenshots and tests only show the drawn cursor after a real mouse move. The tilt reads well because it is small: at most 20° around X and Y and 25° in the plane.

4. Flow and transitions

How the captures were made: real-time bursts under fsit2's software renderer ran at 0.1 to 4.2 s per frame (medians 0.3 to 2.7 s per run), so most animations finished between two frames (menu-open-realtime-sheet.png is all end states). For the slow-motion runs, the steps file asked webpack's module registry for GSAP and set gsap.globalTimeline.timeScale() to 0.04, 0.06 or 0.1. Frame times in those runs are stretched by 1 / timeScale. CSS transitions (the plus icon) and timers (the loader's icon cycle) are not slowed.

Flow What moves, in order Duration Contact sheet
Load black loader: "Hello" rolls in and out; glyph and "We are Büro" roll in; icons cycle while assets load; the bar is lifted to the greeting's height and the greeting slides onto its message slot; the curtain drops; bar and greeting glide down to the bottom together; on inner pages the content fades and rises into place; headings reveal word by word in masks greeting 0.6 s in, 0.4 s out; slide about 0.7 s expo.inOut; curtain 0.95 s expo.inOut; glide 0.65 s expo.out; page 1.2 s expo.out intro-home-slowmo-sheet.png (10 % speed, ends before the curtain), intro-recognition-realtime-sheet.png
Bar message swap icon down and out, words up and out, new icon from above, new words from below 0.3 s out, 0.5 to 0.6 s in, 0.2 to 0.23 s overlap bar-bot-roll-slowmo-sheet.png, bar-bot-roll-slowmo-strip.png (4 % speed)
Menu open message and chip fade; skin grows from the bar; content slides up; page recedes; dividers draw; labels rise row by row 0.65 s main, dividers run to about 2.5 s menu-open-slowmo-sheet.png (4 % speed), menu-open-realtime-sheet.png, phone-menu-open-realtime-sheet.png
Menu close content down and out; skin shrinks into the bar; page returns; message and chip roll back 0.52 s, message at 0.3 s menu-close-realtime-sheet.png (frame 00 mid-collapse), menu-close-run2-sheet.png
Page to page (from the menu) the sheet closes into the bar; the new page slides up from the bottom of the viewport over the old one, which stays put underneath (the body turns black and the old page is pinned with a clip-path at its scroll position); the chip rolls to the new page's name; headings reveal line by line; the bar takes the new page's first message new page y: 100vh → 0 over 0.9 s power3.inOut after 0.1 s nav-to-recognition-slowmo-sheet.png and nav-to-recognition-slowmo-frames-01-04.png (6 % speed), nav-to-studios-realtime-sheet.png
Within the page SplitText-style word masks (.w.m-c > .f.m-t) rise on headings; counters roll digit by digit (expo, stagger 0.05 s, yPercent 115); a photo trail spawns under the pointer with a sound in "18 fkn Years" (bar-04-scrolled.png); waveform lines in the manifesto; ScrollTrigger flips sticky and data-active states per element state shots

Source also defines a "fancy" leave for desktop (old page scale: 0, rotate: -20, y: +20 % over 1.25 s power3.in). Our frames show the old page unchanged while the new one covers it, so this is listed under "Not confirmed".

5. Shots

File What it shows Device
shots/bar-01-rest-eyes-over-hero.png Bar at rest ("We are Büro", Homepage chip, plus) over the hero video; eyes cursor at top right desktop
shots/bar-02-pointer-on-bar.png Pointer on the bar: hand cursor, the line already reads "Open menu" (the hand hides its last letters); navy tint over the blue hero desktop
shots/bar-03-hover-plus.png Pointer on the plus: "↑ Open menu" desktop
shots/bar-04-scrolled.png Scrolled to "18 fkn Years": the bar unchanged, photo trail, swearing-face glyph desktop
shots/bar-05-window-blur-message.png After a window blur: halo face and "Take your time" desktop
shots/bar-bot-roll-slowmo-strip.png Eight crops of the bar at 4 % speed: glyph sinking, words lifting desktop
shots/menu-01-open.png Sheet open: header, Let's talk, five page rows with thumbnails, socials, the minus (under the hand cursor); page receded with a black frame desktop
shots/menu-02-hover-work.png Hover on Work: wider thumbnail, label nudged, row sweep; hand cursor desktop
shots/menu-03-hover-child-branding.png Hover on the Branding child: its column grows, label fades desktop
shots/menu-04-closed.png After Escape: bar back at rest, eyes cursor over the hero desktop
shots/cursor-01-hand-over-card.png Tilting hand over the second ranking card; bar says "That's Bach, btw!" desktop
shots/cursor-04-pressed-on-bar.png Mouse held down on the bar: pressed hand, "Open menu" desktop
shots/cursor-hand-eyes-pressed-crops.png Crops: hand over the cards, eyes over the hero, pressed hand on the bar desktop
shots/nl-01-before.png /work footer: contacts, addresses, the two lines; bar shows the footer message and the Work chip desktop
shots/nl-02-focus.png Input focused: no visible change desktop
shots/nl-03-typed.png "hello@example.com" typed: Send and the consent line visible desktop
shots/nl-states-crops.png The three newsletter states cropped and stacked desktop
shots/nl-send-hover-strip.png Ten frames hovering Send: the underline replay is not visible desktop
shots/phone-01-bar-rest.png Phone bar at rest: glyph, message, plus, no chip; Play button on the hero phone
shots/phone-02-menu-open.png Phone sheet open, receded page behind phone
shots/phone-03-menu-closed.png Phone, sheet closed again phone
shots/phone-04-scrolled.png Phone scrolled: "A glimpse of our latest work, fresh and minty" running under the plus phone
shots/phone-bar-rest-vs-long-message.png Crops of the phone bar: rest and the long message phone
shots/phone-nl-01-before.png Phone footer with the two lines phone
shots/phone-nl-02-typed.png Phone after typing: Send under the address, consent below phone
shots/menu-open-slowmo-sheet.png 14 frames of the sheet opening at 4 % speed desktop
shots/menu-open-realtime-sheet.png 14 real-time frames, all already open (render too slow) over the hero reel desktop
shots/menu-close-realtime-sheet.png 12 real-time frames; frame 00 catches the skin collapsing desktop
shots/menu-close-run2-sheet.png 14 frames of a second close (normal speed, the slow-down did not re-apply); ends on "Open menu" desktop
shots/bar-bot-roll-slowmo-sheet.png 8 frames of the message swap at 4 % speed desktop
shots/intro-home-slowmo-sheet.png 16 frames of the homepage loader at 10 % speed: "Hello", then "We are Büro" desktop
shots/intro-recognition-realtime-sheet.png 16 real-time frames of loading /recognition: greeting, then the page with its heading revealing and the bar message desktop
shots/nav-to-recognition-slowmo-sheet.png 16 frames, home to /recognition from the menu, at 6 % speed desktop
shots/nav-to-recognition-slowmo-frames-01-04.png Frames 1 to 4 of that run at half size: the new page sliding up over the old one, chip changing desktop
shots/nav-to-studios-realtime-sheet.png 16 real-time frames, home to /studios; frame 00 mid-slide desktop
shots/phone-menu-open-realtime-sheet.png 10 real-time phone frames of the open sheet phone
shots/bursts/<burst>/*.jpg Every burst frame at 720 px wide (phone at 390 px), for flipping through both

6. Sources

7. Not confirmed


Verification

Büro (Bürocratik) teardown: verification

2026-10-22 (UTC; the evening of 2026-10-21 local) · verifier pass over README.md and component.json in this folder · aim: refute the claims, not restate them.

Result. 117 claims checked: 81 held, 22 were wrong or imprecise and are corrected in place, and 14 stay unconfirmed. The three playbooks stand: the bar is a message stack with a sheet that grows out of it, the newsletter is a paragraph plus an email input dressed as text, and the cursor is one DOM element holding a stack of drawn states. The errors were in the details around them: GSAP SplitText (not on the site), where three.js runs (/studios too), the selection colour, the recede variable, the click area's height, the signs of the cursor tilt and of the pupils, the blink timing and the capture frame rates.

How it was checked

What held

Stack (23). 1. Nuxt 2 full static: window.__NUXT__, per-route state.js and payload.js and a manifest.js under /_nuxt/static/1791840994/ on all four pages; every data-n-head value in the served HTML is "ssr". 2. The build id 1791840994 is 2026-10-12 21:36:34 UTC. 3. Vue 2.7.16 at runtime. 4. vue-router 3.6.5 at runtime. 5. core-js 3.38.0 at runtime (__core-js_shared__.versions, mode global). 6. webpack 4 JSONP runtime: window.webpackJsonp takes a pushed chunk and runs it with __webpack_require__. 7. The twelve shared chunks named in section 6 are exactly the homepage's preloaded and body scripts, besides state.js, payload.js, manifest.js and /signature.js; /work loads 89089df, /recognition a8e64f2 and 6af09bb. 8. Sanity: og:image on cdn.sanity.io/images/zksivtxz/production/…, CSP frame-ancestors 'self' http://localhost:3333 burocratik.sanity.studio, the ?preview plugin in the quoted source (its token already redacted), 35 /_nuxt/image/ paths in the homepage HTML. 9. Vercel: server: Vercel, x-vercel-cache: HIT, x-vercel-id: pdx1::…, age: 613648 (about 46 minutes after the agent's 610885), last-modified: Thu, 15 Oct 2026 01:18:06 GMT. 10. GSAP 3.12.2 at runtime from webpack module 0, not a global; ScrollTrigger and MotionPathPlugin registered (gsap.core.globals()), CustomEase in module 134. 11. The m3.* eases are created with the quoted curves; the m3.emphasized path in the README matches the source to three decimals. 12. Lenis 1.0.42 (window.lenisVersion); the scroller's defaults object is empty (var O={}), so duration: 1 and wheelMultiplier: 1.1 are the only options; lenis lenis-smooth on html, lenis-stopped with the sheet open. 13. The page scrollbar is native; --sbw is measured in source; the only scrollbar CSS is the .no-scrollbar set. 14. three.js r171 on /work and /recognition (window.__THREE__ "171", 89d5fef.js loaded), Words.worker and .webglContainer on /work, the /recognition canvas at 2880 × 1800; none on the homepage (__THREE__ unset, no WebGLRenderer in its 724 modules), 6 videos and 2D canvases only. 15. Rive @rive-app/canvas 2.21.6: its package.json is inlined in module 175. 16. The small textured-quad WebGL program (uniform vec4 mat; uniform vec2 translate) is in that same module 175, so it belongs to the Rive runtime. This was in "Not confirmed" and is now moved into the stack table. 17. Pizzicato in module 113 (UMD export Pizzicato and Pz, AudioContext); $audio enables on the first click and toggles on key codes 17 and 65 (Ctrl+A); ./audio/image-spawn.mp3 loops while the pointer moves, desktop only. 18. Fonts: "Commercial Gräphik Web" upright and italic variable files (…-VF_wght-Web…woff2), the only faces in the probe. 19. Umami (cloud.umami.is/script.js with a data-website-id) and GA4 G-52YF8HGWG2. 20. signature.js: 427 bytes, badges white on #0020f4 then on #242424, plain text outside Chrome and Firefox. 21. The ASCII banner is the first node of the HTML and carries "♥ MADE BY BÜRO: BUROCRATIK.COM" and "YEAR: 2024"; Ctrl+G (key codes 17 and 71) toggles ._grid-preview, built from new Array(24) columns. 22. No View Transitions: 0 view-transition rules, 0 modules with startViewTransition. 23. No reduced-motion handling and no live region: 0 prefers-reduced-motion rules among 1,339, none in the HTML, 0 modules containing reduced-motion or aria-live; :focus { outline: 0px; } is a global rule.

Bar and sheet (25). 1. Desktop geometry: 575.47 × 46 at x 432.25, y 823.61, bottom: 30.405px. 2. Phone geometry: 342.5 × 46 at x 23.75, bottom: 24px. 3. The width rule (10, 12, 18 and 22 of 24 columns) and the bottom clamp are in the quoted CSS; at 1440 px the clamp gives 21.621 + 8.784 = 30.405 px, exactly the computed bottom. 4. Skin: radius 20 px, the 85 % black gradient over 40 % white, backdrop-filter: blur(18px) (computed); the probe finds one backdrop-filter element. 5. Inside: padding 16 and gap 14 (CSS); ._bot starts at x 448.25, the 24 px glyph at 450.25 (2 px padding), the message at 482.25 (8 px gap); 17.575 px, line-height 1.2, -0.04em. 6. Chip: 105.25 × 28.78, white, radius 12; 111.45 px for Recognition and 77.30 px for Studios; 0 × 0 on the phone. 7. Plus: 18 × 18, computed transform 0.35s cubic-bezier(0.645, 0.045, 0.355, 1) 0.05s, the :before bar sliding out at 0.5 opacity; the minus is visible in menu-02-hover-work.png. 8. Sheet: 575.47 × 770.5 from y 99.1; phone 342.5 × 675.19 from y 144.8. 9. DOM: matches the template in sources/bar-menu-motion.js.txt and the persistentBarDom dump (ten word slots per layer, the label twice in the chip). 10. Message stack: the base {icon: "burocratik", message: "We are Büro"}, set pushes and returns a remover, and the base cannot be removed. 11. Event types: hover returns early on touch screens, intersection defaults to rootMargin "-70% 0% -25% 0%", custom, and the footer preset; v-bot:event is used 8 times in the homepage's modules. 12. Messages: "We are Büro", "Open menu", "That’s Bach, btw!", "Take your time" and "Don't stop now! Click for more!" read by evals; "A glimpse of our latest work, fresh and minty" on the phone; "Not quite my tempo", "Oh yes, Büro does branding too" (an intersection message) and "Yes, '99 is right" (a hover message with the exploding-head icon) are in the modules; the window-blur set and the 10 s and 2 s welcome-back are in source. 13. Roll timings: the quoted leave and enter configs, plus delay:.2 on the incoming icon and delay:.23 on the incoming words in the Bot module, so the 930 ms total holds. 14. Icons: the list has 45 entries including none, so 44 named icons. 15. Click area width and offsets: calc(navbar-width + 16px) = 591.47 px, right -24 px, top -16 px (computed); any click on the bar opens the sheet. 16. No awake state and no shrink on scroll (bar-04-scrolled.png). 17. Chip return after closing: background xPercent 101 → 0 over 1 s expo.out, label yPercent 101 → 0 over 0.55 s power3 after 0.225 s. 18. Open timeline: every row of the table against the quoted source. 19. Recede: computed matrix(0.9755, …) and opacity 0.667 on .page-content, data-blurred, inert, lenis-stopped, Escape on the key stack. 20. Close timeline (0.52 s skin, 0.49 s content, 0.3 s opacity, recede back over 0.52 s, message and chip at 0.3 s); frame 00 of menu-close-realtime-sheet.png shows the skin mid-collapse. 21. Inside the sheet: thumbnail 87.4 → 99.7 px at 1440 from the clamps over 0.3 s, label 8 px over 0.2 s, row gradient at 0.025 opacity, child label at 0.66, the current page at brightness(0.5) (probe) and not clickable, socials 0.5em over 0.175 s. 22. Load handoff: the four steps and timings in source, icons cycling every 260 ms; the frames show the greeting and then the docked bar on /recognition. 23. Video-control morph: a navbar-morph label with 0.363 s power4.inOut in source. 24. Phone: tagline hidden under 743 px (CSS and phone-02-menu-open.png), no chip, the long message running under the plus (phone-bar-rest-vs-long-message.png). 25. Accessibility: aria-label, the inert sheet, aria-hidden copies, Escape, no live region, the data-motion-fallback rules.

Newsletter (13). 1. Geometry: form at x 965.3; line 1 414.6 × 21.09; input 220.1 × 21.09. 2. Type: 17.575 px, line-height 21.09 px, letter-spacing -0.703 px, Commercial Gräphik Web 400 (computed). 3. Placeholder black at opacity 0.5 (computed). 4. Input: no border, padding 0, outline none, white background, black caret, autocomplete="email", no label and no aria-label. 5. Phone: a 252 px column at x 86.75, Send under the address (y 668.5 against 645.3). 6. The DOM block matches formAfter apart from the data-hidden flags (see correction 19). 7. Focus changes nothing: nl-01-before.png and nl-02-focus.png are byte-identical, and the focused input reads outline-style: none. 8. Typing: Send goes from opacity 0 to 1 with no transition, the consent line fades over 0.2 s cubic-bezier(0.215, 0.61, 0.355, 1), sits at bottom: -35px in 13 px text; the underline is 1.156 px at 17.575 px, so 0.066em. 9. Send hover underline timings (source). 10. Error colour #dc3429 with the placeholder at opacity 1 (CSS). 11. Submit stub: preventDefault, two console.log calls, 2 s, then "I already have you mail" / "Gotchaaa" for 4 s, no request, action never called, strings hard-coded. 12. Not in the sheet: the navbar template has no form; bar-stage-drawers.md (line 8) and components-to-copy.md do place it there, so the README's correction of them stands. 13. The consent checkbox's :focus-visible ring, 3 px at 30 % black (CSS).

Cursor (12). 1. Box: 48 × 48, fixed, top and left -24 px, pointer-events: none, z-index: 9999 (computed), shown only under (hover: hover) and (pointer: fine). 2. Six states as inline SVGs switched by data-cursor with scale(0) and opacity: 0. 3. The hand: white fill, a black 2.5 px stroke and the same stroke at stroke-opacity="0.2" (DOM); the SVG sits at 9.59 and 4.80 px, so 20 % and 10 % (computed). 4. Pressed: body:active swaps to the -active drawing with no transition; the crop of cursor-04-pressed-on-bar.png shows the bent finger next to the straight one of cursor-01. 5. Position: a passive mousemove coalesced to one call per frame by module 35's h (cancelAnimationFrame, then requestAnimationFrame), written straight into translate3d; the computed transform equals the mouse position (560, 846). 6. Stack: v-pointer pushes on mouseenter, pops on mouseleave, forwards clicks, and is skipped on touch screens. 7. cursor: none on 435 to 437 homepage elements across three probes; no url() cursor rule. 8. Tilt magnitudes and timing: factors 4, 4 and 5, clamp ±5 px, 0.25 s power2, settle over 0.5 s power4 after 100 ms (signs corrected below). 9. Eyes: ranges ±2 px and -12 to 3 px, quickTo 0.25 s, recentre after 100 ms, blink scaleY .1 for 0.1 s each way and on click. 10. Tornado (motion path, 0.4 s power2.out) and viewcase (label 0.2 s, inner 0.15 s later) in source. 11. Cards: four links of 77.97 × 116.47 at x 965, 1053, 1141 and 1229 (10 px apart) in ._manifesto .accolades on the homepage, under "Our Accolades". 12. States read by evals: eyes over the hero, pointershift over the bar and the card, none off the card; cursor-01-hand-over-card.png shows the hand on the second card with "That’s Bach, btw!" on the bar.

Flow, shots and references (8). 1. Slow motion: the evals return "gsap 3.12.2 timeScale 0.1", "0.04" and "0.06"; the second slow-down of the menu run returned "no-require", so menu-close-run2 did run at normal speed. 2. intro-home-slowmo-sheet.png shows "Hello", then the glyph and "We are Büro", and ends before the curtain; intro-recognition-realtime-sheet.png shows the greeting, then the page with its heading revealing and the bar. 3. menu-open-slowmo-sheet.png shows the skin growing, the content arriving and the labels rising row by row; menu-open-realtime-sheet.png is 14 fully open frames over the reel. 4. Page to page: the 6 % frames show the new page sliding up over an unchanged old page, the chip going blank and then "Recognition", the heading revealing line by line and "Move that mouse…" reaching the bar in the last frames; the quoted source gives y from the viewport height to 0 over 0.9 s power3.inOut after 0.1 s, the black body and the clip-path pin. 5. Counters: v-motion with yPercent: 115, expo, stagger 0.05 s, duration 0.9 + 0.05 i. 6. The photo trail with its sound is desktop only; bar-04-scrolled.png shows the trail at "18 fkn Years". 7. Captions that match their pictures: bar-01, bar-04, bar-05, menu-02, cursor-01, cursor-04, cursor-hand-eyes-pressed-crops, nl-01, nl-02, nl-states-crops, bar-bot-roll-slowmo-strip (glyph sinking, words lifting), phone-02-menu-open, phone-bar-rest-vs-long-message, the five contact sheets listed above. 8. The owner's quotes in section 1 match rows 6, 9 and 15 of INSPIRATION.md word for word.

Corrections, verifier, 2026-10-22

Each is corrected in place in README.md and, where the statement also appeared there, in component.json.

  1. GSAP SplitText. Said: GSAP 3.12.2 "with ScrollTrigger, CustomEase, SplitText and MotionPathPlugin" (component.json listed "SplitText"). The only modules carrying "3.12.2" are the GSAP core (module 3), ScrollTrigger with Observer (46), CustomEase (134) and MotionPathPlugin (397); none has SplitText's charsClass or linesClass, and all six modules that name SplitText import it as a Vue component from module 41. Now: no GSAP SplitText; the splitting is the site's own SplitText component.
  2. Number of Material 3 eases. Said "ten". There are nine create("m3…") calls in the loaded modules and in the quoted source (emphasized, standard and legacy, each plain, accelerate and decelerate).
  3. Where three.js runs. Said "on /work and /recognition only". /studios also loads 89d5fef.js, sets window.__THREE__ to "171", loads a Lines.worker web worker and has a 1440 × 946 canvas in a .webglContainer. /recognition loads a Points.worker for its dot field (on /work and /recognition the canvas gives the probe no context, and transferControlToOffscreen is among the modules on all three pages, so the drawing is most likely done offscreen in the worker), and its 2880 × 1800 canvas is a backing store at twice the 1440 × 900 CSS size on a display of device pixel ratio 1 (the site doubles it; the capture did not). component.json three_d updated.
  4. "Audio waveforms". Said the homepage's canvas.wave elements are audio waveforms. They sit inside .line-divider elements (on /studios too) and nothing read ties them to audio. Now: wave line dividers.
  5. data-n-head on every head tag. 25 of the 45 head tags in the served HTML carry data-n-head="ssr"; the 15 preload links, the title, the style block and three scripts carry none.
  6. Scrollbar rules. The README quoted the WebKit rule as a bare ::-webkit-scrollbar{width:0;height:0}, which would hide every scrollbar in Chrome and Safari. It is .no-scrollbar::-webkit-scrollbar{width:0;height:0}, with a transparent thumb and track. The conclusion (native page scrollbar) held. Added: sliders draw a 2 px DOM track (._slider > [data-slider-scrollbar], black thumb, cursor: grab), which is not a scrollbar style.
  7. Selection colour. Said "::selection is blue #105df1". There are two global ::selection rules, blue #105df1 and then black; the later one wins, and the computed ::selection background of a paragraph is rgb(0, 0, 0). Selected text is white on black.
  8. $audio on blur. Said it "disables on window blur". It also comes back on the next focus (addEventListener("focus", enable, {once: true})) if it was on.
  9. --blr-s. Said "--blr-s = 2 × margin / width (0.9755 at 1440 px)". --blr-s is 0.0245 at 1440 px (the agent's own pageState eval: blrS: "0.0245"); 0.9755 is the resulting scale.
  10. The black around the receded page. Said "a black body and 20 px rounded corners". body stays transparent while the sheet is open (bodyBg: rgba(0, 0, 0, 0)); the black is the ._page background and its blur-mask bars, and the 20 px rounded corners are the top two (border-top-left-radius, border-top-right-radius).
  11. The click area's height. Said "the bar's height plus 32 px". The span's height: calc(100% + 32px) is relative to the 18 px button, so 50 px; the span measures 591.47 × 50 at x 424.25, y 821.61, overhanging the 46 px bar by 8 px a side and about 2 px top and bottom, and the bar's overflow: hidden clips it. "The whole bar is the button" holds.
  12. A quoted message. The /recognition message is "Move that mouse, shake it! Yeah!!" (two exclamation marks, read from the bar on /recognition), not "Yeah!".
  13. Tilt signs. Said rotateX = -4·dy, rotateY = -4·dx, rotateZ = -5·dx. The $mouse watcher passes (current, previous) and the handler clamps previous minus current, so with dx and dy the movement since the previous frame the formulas are rotateX = 4·dy, rotateY = 4·dx, rotateZ = 5·dx. Measured at 0.2 speed: moving right gave rotate(10.737deg) rotateY(8.5895deg), moving down rotateX(6.0289deg); verify-02-hand-moving-right.png shows the hand leaning clockwise. component.json updated.
  14. Tilt maximum. Said "about 20° at most". The clamp allows 20° around X and Y and 25° in the plane.
  15. Pupils. Said "the pupils follow the motion". They shift against it, like inertia: x = -dx/2 clamped to ±2 px, y = -dy clamped to -12 to 3 px. Measured: moving right gave x -1.129, moving down y -5.452. component.json updated.
  16. Blinking. Said "at random every 1 to 4 s, sometimes sooner". The blink timer restarts on every mouse move, so the eyes blink 1 to 4 s after the pointer stops and then keep that rhythm; one wait in ten is instead 250 × Math.random() × 50 ms, anything from 0 to 12.5 s. component.json timings updated.
  17. Capture frame rates. Said real-time bursts "ran at 0.6 to 5 s per frame" and, in the bar's gotchas, "0.6 s with the bar closed and 2 to 5 s with the sheet open". Recomputed from the burst timestamps: 0.12 to 4.24 s per frame across the real-time bursts (medians 0.29 to 2.67 s per run); about 0.5 to 0.7 s median with the sheet closed and 1.8 to 4.2 s with it open.
  18. bar-02-pointer-on-bar.png caption. Said the message is "mid-roll to 'Open menu'". The 3x crop shows the up arrow and "Open me" at rest on the baseline, with the hand covering "nu": the roll had finished.
  19. menu-01-open.png caption. Lists the minus, which sits under the hand cursor in that frame; the caption now says so.
  20. Newsletter DOM heading. The block is headed "DOM after typing" but shows data-hidden="true" on the button and the consent fieldset, flags that exist only before typing (formAfter has neither). The heading now says the flags were put back in.
  21. Newsletter loading state. Said "the form goes inert at 0.3 opacity". The form goes inert and disabled; its fieldsets drop to 0.3 opacity and the Send button, through data-loading, to 0.4 while its underline loops. component.json state updated.
  22. Time before the load handoff (component.json, load transition). Said "about 1.8 s before the handoff". The greeting timeline is 1.8 s including its 0.2 s delay, then a 0.3 s setTimeout, then the handoff timeline's own 0.2 s delay: about 2.3 s before the handoff moves, longer while assets load.

Also changed: the "small WebGL program in the vendor chunk" item left "Not confirmed" in both files and is now a fact in the stack table (held item 16). A line under the README's title points here.

Not confirmed

  1. Nuxt release. No Nuxt version string in the HTML or the modules; Vue 2.7.16 suggests Nuxt 2.17.
  2. vue-meta 2.4.0. One homepage module carries "2.4.0"; it was not tied to vue-meta here.
  3. Size of 89d5fef.js (594 KB): not re-measured.
  4. Old page during a page change (the desktop "fancy" leave): unchanged from the README.
  5. Send underline hover replay: unchanged; note that the pointer state over Send is none.
  6. Newsletter submit: never submitted, as the rules require.
  7. The bar as video controls beyond the 0.363 s power4.inOut morph found in source.
  8. Reduced motion under emulation. The absence is now confirmed in the CSS, the HTML and all 724 homepage modules; behaviour under emulated prefers-reduced-motion: reduce was not run.
  9. The page scrollbar in a real browser: all captures run with --hide-scrollbars.
  10. Mid-roll requests queue and only the latest is kept: the transition.request code was not read.
  11. Child links growing to 1 + n/7 fr: not in the quoted CSS; set by script that was not read.
  12. The .m-c and .m-t mask values (margin-bottom: -.16em, padding-bottom: .08em, will-change: transform): not re-checked.
  13. Plain hand on ._award, event buttons and footer links, and grab on sliders: not re-checked.
  14. Rive assets playing on mouseenter: not checked.

Seen in passing, not added to the playbook: Ctrl+Shift+D toggles a window.debug console log; on /work the bar says "WebGL, baby! No flying magic carpets here."

Tidiness