Lab
Every uniform, every token, the hinge spring, and how it was made.
Playground
Tokens
--void#020204Hero and footer, the dark stage--ink#000000Text, borders, icon fills--carbon#636363Secondary text--slate#888888Tertiary text, inactive--silver#c6c6c6Dividers, placeholders--graphite#575757Dark secondary buttons on light--paper#ffffffCards, button surfaces--bone#f8f8f8Page canvas, nav--linen#efefefButton fills, pills--lime#f2fcb3Accent wash band--saffron#ffdc5cWarm highlight--spectrum6 stopsOnce per page. The divider under the hero.Shut
Follows the hinge, not a timer. 54, Clamp 300
Eight ways to shut. 48, Inter Tight 650
Heading small, 24
Subheading, 22.
Body at 18, line height 1.5. Short flat sentences. No exclamation marks. One joke per screen.
Body small at 16 with a 2.19 line height for long copy. It breathes.
Eyebrow · JetBrains Mono 13 · 0.1em
--ease-lidcubic-bezier(.45, 0, .85, .55)--ease-2cubic-bezier(.4, 0, .2, 1)--easeease · 0.2s, color onlySpring editor
The hinge on this page. SwiftUI's vocabulary on the left, the physical one on the right. They are the same spring.
- mass
- 1
- stiffness
- —
- damping
- —
How it reads the lid
Most Apple silicon MacBooks, every M2 and later and most M1s, have a hinge angle sensor. It shows up as a HID device on IOKit: vendor 0x05AC, product 0x8104, usage page 0x20, usage 0x8A. Feature report 1 carries the angle in bytes 1 and 2, little-endian, in degrees. That is the whole interface. No private framework, no entitlement.
The raw readings are noisy and jump by a degree or two, so the app runs them through three stages. A short least-squares line fit smooths and gives velocity. A One Euro filter keeps latency low when the lid moves fast and steadies it when it moves slowly. A calibration learns the shut floor and the open reference for this particular machine, so nobody types their angles in. The result is a HingeState: angle, velocity, direction, and progress from 0 (open) to 1 (shut).
Idle stays idle. The sensor is polled once a second at rest, and only a real movement of two degrees or more wakes it. Nothing draws unless progress changed. Macs that only report open or closed play the style on a short timeline instead, about half a second to a second and a half depending on Speed, and after sleep the reopening is a spring from black because the lid finished moving while the screen was off.
Progress passes through a curve, cubic-bezier(.45, 0, .85, .55), published on this site as --ease-lid. The effect begins in earnest a set number of degrees above shut. The app calls that Speed. On this page it is the Speed slider, and it starts at 45°.
Porting the shaders to WebGL
The app renders with Metal: one fragment shader for Sinkhole, one for Frost, and a 48×48 mesh with a vertex stage for the five panel styles. The site runs the same code as GLSL ES 3.0, uniform for uniform. Three things needed care.
- The Metal pipeline is linear light, so its constants assume sRGB decoding. The GLSL ports decode on sample and encode on output, and the tuned numbers read the same.
- Frost and the panel blurs read a mip chain instead of a Gaussian kernel, so the per-frame cost does not depend on the radius. WebGL 2 builds the chain with one call and samples it with
textureLod. - The panel styles are premultiplied and composited over black, or over the live desktop for the mask styles. The same blend mode does both.
There is one WebGL context on the page. Every live surface is a plain canvas that receives a copy of the shared frame, so the nav can blur over it and no browser runs out of contexts. A surface only draws when its job changes, so a page at rest costs nothing.
Explorations
- A video hero. Rejected. A recording cannot follow a slider, and the site is supposed to behave like the app.
- A lid you drag with the mouse. Tried. It fought the scroll. The slider says Open → Shut, like the app, and scroll does the rest.
- Reading the real lid angle from the browser. There is no web API for it. The app is the way.
- Color. Almost none. Black on bone, two washes, one spectrum line under the hero. The effects carry the color.
- Explaining the name. No.
Source for the app and this site: notthamer/shut.