Motion
Icons move only to communicate state. The vocabulary is deliberately small: 200–300ms, positional, and every transition is killed under prefers-reduced-motion.
- Menu → XThe header menu button morphs while the drawer is open. The drawer slides under the header (z-index below it, top padding clearing it) so the X stays visible and tappable — morphing to an X you can’t see or tap is meaningless. The SVG is inlined in
chrome.js— paths inside a<use>shadow tree can’t be targeted by CSS, so this is the one sanctioned exception to the sprite. - Tab fillThe active tab swaps its outline icon for the filled Tabler partner (
icon-home-fill,icon-document-fill,icon-book-fill), iOS-style..icon-filloverrides the stroke look of.ui-iconbecause filled glyphs are solid shapes. - Highlight slideTapping a tab swaps the page without a document navigation —
site.jsintercepts same-origin tab links, fetches the page, and swaps<main>in place while the tab bar stays mounted as the same element. The highlight pill glides the instant--active-indexmoves (.28s live::beforetransition); the URL updates viahistory.pushStateand the back button works viapopstate. Neither the animation nor the load waits for the other — both start on tap. Feedback starts onpointerdownand navigation commits onclick. Full interaction contract on the dock page. - Copy → checkThe copy button morphs on success —
site.jstoggles.copiedand flips the label to “Copied” for 1.8 seconds. The icons scale and rotate (pivoting ontransform-box: fill-box) so the morph reads as a morph, not a straight swap. No separate toast: the button is the feedback, and Android already shows its own native confirmation — a second toast just overlaps it. - Drawer staggerDrawer links slide in with a 40ms stagger, wrapped in
prefers-reduced-motion: no-preference. - Dock position
bottom: calc(10px + env(safe-area-inset-bottom, 0px)), withviewport-fit=coverenabled on Android bychrome.jsbefore first paint. The inset is evaluated against the live viewport, so the dock tracks Chrome's retracting toolbar with pure CSS. Full saga — dead ends included — on the dock page.