The scene stops heating the MacBook

"Terribly high CPU usage, the MacBook gets really hot" - a fanless MacBook
Air on a 144Hz screen. Measured on that machine with headed engines
(process CPU plus the per-process GPU time macOS keeps): an idle Aero
library cost LibreWolf ~110% CPU and ~230ms/s of GPU, the study feed ~130%,
Chromium up to ~57% CPU and ~350ms/s of GPU, Safari ~220-250ms/s of
WindowServer GPU. Priced one by one:

- the gradient mask on .ice-floats re-rendered the animated layer offscreen
  on every frame (~75 points of Gecko CPU). The floats now rise through a
  plain rectangular band clear of the header, the bottom chrome and the
  rail, and fade in and out inside it, so the clip never cuts a visible one;
- the overlay grain forced a backdrop readback per frame for a texture that
  measured a mean <=0.11/255 difference: removed;
- the invisible blob drift made every frame a full-screen redraw: the blobs
  are painted once;
- static glass (answer tiles, feedback panel, chips, inputs, dropzones,
  lists, segmented controls, Aero hint chips) re-blurred the moving scene
  every frame: only floating glass blurs now, and Aero's baked chat chrome
  drops a live blur that never showed under the bake;
- the scene also parks while the window has no focus and under any dialog
  or sheet scrim (.scene-pause); the loading icon is a compositor-run CSS
  animation instead of a framer-motion main-thread loop.

After, focused and animating: LibreWolf library 109% -> 33% CPU, study
134% -> 34%, chat 130% -> 42%; Chromium GPU 2.5-4.4x lower with 7-22 points
less CPU; Safari's WindowServer GPU -20-26% in Aero, about half in dark.
Unfocused or under a sheet: nothing. bubbles-test sweeps every float through
41 phases against the band and pins the parking and the cost contract;
tests/heat-probe.mjs (macOS) repeats the measurement; the suites find
Playwright's Chromium on macOS.

All 15 suites pass, lint clean, the contrast scan lost a finding. Version
0.6.7, SW v89.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
pepaskopec-blip 2026-10-15 19:39:29 +02:00
commit bfc0f806b9
27 changed files with 613 additions and 249 deletions

View file

@ -217,16 +217,18 @@ the saved notes) with the matching words highlighted green, and the feed chrome'
their own bottom action bar instead of the tab bar, and the in-page segmented switch moves between
the deck and homework wizards.
- **Frosted ice glass, both themes**: light page `#eef5fd` (pale ice) with white glass panels;
dark page `#0a1120` with `rgba(255,255,255,.06)` glass. Every large surface shares one recipe —
translucent tint, 24px `backdrop-blur` (16px on phones), a bright 1px rim, an inner top highlight
and a blue-tinted shadow — over a fixed ice scene (navy/pale base, drifting glacier blobs, glossy
ice orbs and a whisper of grain).
dark page `#0a1120` with `rgba(255,255,255,.06)` glass. Every surface shares one recipe —
translucent tint, a bright 1px rim, an inner top highlight and a blue-tinted shadow, plus a real
16px `backdrop-blur` (12px on phones) only on floating glass that content scrolls under — over a
fixed ice scene (navy/pale base, soft glacier blobs and glossy ice orbs rising through the open
band between the chrome).
Text tiers are documented AA ratios (see below), and the cards fill the row with
`repeat(auto-fill, minmax(280px, 1fr))` — no stranded cards, no dead space
- Deck cards: title → muted metadata → neutral tags (difficulty carries the only colour:
green/amber/red) → summary → a single **Study** button, with everything else in the `⋯` menu
- **Frosted UI**: the sticky header, tab bar, sheets and panels use real `backdrop-filter` blur over
the fixed ice scene (drifting glacier blobs, glossy orbs, a whisper of grain) — depth without noise
- **Frosted UI**: the sticky header, tab bar, study chrome and sheets use real `backdrop-filter`
blur over the fixed ice scene — depth without noise. Glass that sits still never blurs, and the
scene parks whenever nobody is watching it (hidden tab, unfocused window, an open dialog)
- **Pill language**: primary CTAs are near-black in light mode and white in dark mode; secondaries
are outlined or ghost. Colour is reserved for meaning — activity tints (sky/lilac/mint/peach/rose),
correct/wrong feedback, key status
@ -1434,6 +1436,53 @@ Things I chose while building, with the reasoning:
(measured: 268..1280 at a 1280 window) — a flat pane floating 40px inside the scene read as
"cut off next to the sidebar".
98. **The MacBook ran hot on the scene, so the scene's per-frame bill came down.** "It has
terribly high CPU usage and the MacBook gets really hot when I'm on it" — a fanless MacBook Air
driving a 144Hz display. Measured on that machine with real headed engines (process CPU plus
the per-process GPU time macOS keeps — `tests/heat-probe.mjs`), not frame times in a throttled
software renderer: an idle Aero library cost LibreWolf (Gecko) ~110% CPU and ~230 ms of GPU
per second, the study feed ~130% / ~320 ms, Chromium ~57% CPU and up to ~350 ms/s of GPU, and
Safari ~220-250 ms/s of WindowServer GPU above the desktop. Each suspect was switched off on its
own to price it:
- **The gradient mask on `.ice-floats`** (from 91) re-rendered the whole animated layer
offscreen on every frame — ~75 points of Gecko CPU by itself. The floats now rise through a
plain rectangular band (68px below the top, 151px above the bottom — 172px on phones — and
right of the 268px rail strip on desktop), and every orb and bubble starts at the band's
bottom and ends at its top at zero opacity: the fades live in the keyframes (in by 18%, out
from 90%; `--ice-rise` is the band height minus the float's own) and the 1.06 end scale is
taken back by a 3% nudge, so no visible float ever touches the clip. The bubbles suite sweeps
every float through 41 phases at 1280 and 390 and fails on any visible frame outside the band.
- **The overlay grain** (`mix-blend-mode` over the animated layer) forced a backdrop readback
per frame for a texture that measured a max 2-6/255 and mean ≤0.11/255 difference —
invisible. Gone.
- **The blob drift**: four viewport-sized layers moving a few vw over 44-60s at 0.045-0.1
opacity turned every frame into a full-screen redraw (Chromium GPU 128 → 80 ms/s with them
still). They are painted once now.
- **Backdrop blurs on glass that sits still**: answer tiles, the feedback panel, chips, inputs,
dropzones, grouped lists, segmented controls and Aero's hint chips re-blurred the moving
scene every frame (the study feed's tiles alone: ~20% Chromium CPU, ~270 ms/s of GPU). Only
floating glass that content scrolls under blurs now; the hint chips use the shared bake, and
the baked Aero chat header/composer drop a live blur that never showed under the opaque bake
(touch has no bake there and keeps it). Their bake is the glass on desktop, so 97's flat
nested tiles still sit on the right backdrop.
- **Nobody watching**: besides the hidden tab, the scene now parks while the window has no
focus (another app in front, the browser on the other screen) and while any dialog or sheet
is open — its scrim carries `.scene-pause`, so the blurred scrim and sheet render once.
- The loading screen's rocking icon was a framer-motion loop writing the transform from the
main thread every frame for the whole generation; it is a compositor-run CSS animation on
`rotate`/`scale` now.
Same machine, focused and animating (before → after): LibreWolf library Aero 109% → 33% CPU
(GPU 227 → 101 ms/s), study 134% → 34% (316 → 141), chat 130% → 42%, dark/light library ~94% →
24-26%; Chromium's GPU time 2.5-4.4× lower (study Aero 354 → 80 ms/s) with 7-22 points less CPU;
Safari's WindowServer GPU above the desktop −20-26% in Aero and about half in dark. Unfocused,
or with a sheet open, the scene costs nothing. What remains is the price of the ambient motion
itself — the orbs (23 floats in Aero) composited at the display's refresh rate, on the
compositor only (Chromium's main thread: ~9ms busy per 4s); Settings → Reduce motion parks it
entirely. The visuals are unchanged apart from where a bubble happens to be at a given moment,
and the pixel-contrast scan lost a finding (the Aero study chip, 4.49:1). The suites also find
Playwright's Chromium on macOS now (`~/Library/Caches/ms-playwright`).
97. **Nested tiles inside the real-blur chrome drop the baked backdrop.** "Frutiger aero theme —
the attachment button looks completely different to the other ones." The composer band, the
chat header and the study pager keep a real `backdrop-filter` (they float over scrolling