|
| 1 | +# Handoff: the mobile overhaul |
| 2 | + |
| 3 | +Written 2 October 2026, at the end of the session that built the Research |
| 4 | +vasculature, the For fun section and the Connect tracts. **The desktop site is |
| 5 | +approved and live. The phone experience is not, and needs a proper redesign, |
| 6 | +not more patching.** Read `SPEC.md` first; it holds the content rules, the |
| 7 | +science and the design language, and none of that changes for mobile. |
| 8 | + |
| 9 | +## What Evyatar said about mobile |
| 10 | + |
| 11 | +On his iPhone, after this round: |
| 12 | + |
| 13 | +1. The animations do not run well. They feel awkward. |
| 14 | +2. They are too dense. |
| 15 | +3. **The red light does not work.** (Holding the 620 nm control does nothing on |
| 16 | + the phone. In desktop WebKit with an emulated iPhone the hold works, so this |
| 17 | + is something a real touch screen does differently: start here.) |
| 18 | +4. The model always hides behind the text, so it cannot really be seen. |
| 19 | +5. Hover does not exist on a phone, so the For fun section does not work. |
| 20 | + |
| 21 | +His words: "we need to think of a serious overhaul to the mobile page. The |
| 22 | +desktop one is fine though." Treat the desktop as a reference to keep, not |
| 23 | +something to change while fixing mobile. Every mobile change should be scoped |
| 24 | +to the phone breakpoint, and the desktop must look identical afterwards. |
| 25 | + |
| 26 | +## How mobile works today (what to replace) |
| 27 | + |
| 28 | +Everything below is in `src/main.js`, `src/styles/layout.css` and |
| 29 | +`src/styles/components.css`, behind `@media (max-width: 1080px)` (and, for the |
| 30 | +band, `and (orientation: portrait)`). |
| 31 | + |
| 32 | +- **One fixed canvas behind the text.** Portrait phones get a band from just |
| 33 | + under the lede to the bottom of the screen (`--band-top`, `--band-h`, |
| 34 | + measured by `placeBand()` in main.js). Its opacity is `--gl-presence`: 1 at the |
| 35 | + top of the page, falling to **0.2 after a third of a screen of scrolling** |
| 36 | + (`updatePresence()`), 0.85 while the light is held, 0.55 while recovering. |
| 37 | + That 0.2 is why every section's view is nearly invisible on a phone: the |
| 38 | + rule was written when the site had one brain, before Research, For fun and |
| 39 | + Connect had views of their own. |
| 40 | +- **Section views.** Each one reuses the desktop camera framing from |
| 41 | + `src/scene/frames.js`, which was composed for a canvas on the right half of |
| 42 | + a wide screen. Nothing is reframed for a phone. |
| 43 | +- **For fun.** No hover, so `main.js` cycles rest, Lotto and football every |
| 44 | + 8 s while the section is active. The caption (`#fun-caption`) is hidden |
| 45 | + below 1081 px and the descriptions stay in the list. The views are fitted to |
| 46 | + a fixed band (`measureFun()` passes `{ top: 0.55, bottom: -0.35 }` below |
| 47 | + 1081 px) rather than to the layout. |
| 48 | +- **Connect.** Drag-to-turn ignores touch on purpose (a finger must still |
| 49 | + scroll). `#contact`'s full-height rule is desktop only. |
| 50 | +- **The light control.** `src/signal/stim.js`: pointerdown on `#stim` (and on |
| 51 | + the canvas) begins, lostpointercapture/pointerup ends; a long press must not |
| 52 | + open a menu (`contextmenu` is prevented). Look at what iOS Safari does with a |
| 53 | + long touch on a button: callouts, text selection, `touch-action`, and |
| 54 | + whether pointer capture is lost early. |
| 55 | + |
| 56 | +## Load on a phone |
| 57 | + |
| 58 | +All of it is lazy: each section's data is fetched once the reader is close, |
| 59 | +and only the visible section's layer is drawn (`group.visible` follows its |
| 60 | +presence). Pixel ratio is capped at 2. |
| 61 | + |
| 62 | +| Layer | File (gzip) | Drawn | |
| 63 | +| --- | --- | --- | |
| 64 | +| Shell and trigeminal highlights | `public/data/*.bin` (~170 KB) | 30k points | |
| 65 | +| Research vessels | `vessels.bin` (1.08 MB) | 265k line and point vertices, 7k neurons, leak halos | |
| 66 | +| For fun | `fun.json` (17 KB) | 24k landscape points; walks 145k line vertices; seasons 34 ridges | |
| 67 | +| Connect tracts | `tracts.bin` (152 KB) | 75k line vertices | |
| 68 | + |
| 69 | +The vessels and the walks are the heavy ones. "Too dense" and "does not run |
| 70 | +well" probably both point there: a phone could take a third of the vertices, |
| 71 | +fewer and larger dots, and thinner fields of lines. The data-prep pipelines in |
| 72 | +`tools/data-prep/` take the counts as parameters (see `vessels/prep.py`'s |
| 73 | +arguments), so a lighter mobile file is a re-run, not a rewrite. |
| 74 | + |
| 75 | +## Directions worth weighing (none decided) |
| 76 | + |
| 77 | +Bring options to Evyatar as mockups before building, the way every round in |
| 78 | +this project has gone. He decides from seeing them, not from descriptions. |
| 79 | + |
| 80 | +- **Give the model its own space on a phone.** For example a figure block in |
| 81 | + each section that has a view (Research, For fun, Connect), with the canvas at |
| 82 | + full strength while that block is on screen and reframed to fill it. That is |
| 83 | + the lesson he already gave once (memory: never hide the model behind the text |
| 84 | + to protect legibility; give it its own space). |
| 85 | +- **Reframe for portrait.** New camera frames per section for a tall, narrow |
| 86 | + canvas instead of the desktop ones. |
| 87 | +- **For fun by tap.** A tap on a project row could show its view, with an |
| 88 | + explicit link affordance to visit the project, instead of an automatic cycle. |
| 89 | +- **A lighter mobile data set,** as above, and possibly a reduced-motion or |
| 90 | + low-power fallback. |
| 91 | +- **Fix the light first.** It is the site's central interaction and it is |
| 92 | + broken on the device that matters most. |
| 93 | + |
| 94 | +## Verifying |
| 95 | + |
| 96 | +- `tools/verify/mobile.mjs`: the iPhone 14 Pro profile in Playwright's WebKit, |
| 97 | + through every section; frame timing, overflow, presence, errors, the For fun |
| 98 | + cycle, a light hold, a tap on Connect. Desktop GPU, so frame rates there say |
| 99 | + nothing about the phone. Usage is in the file's header. |
| 100 | +- **iOS Simulator**: needs full Xcode. Evyatar is installing it, then running |
| 101 | + `sudo xcode-select -s /Applications/Xcode.app/Contents/Developer`. |
| 102 | +- **His phone**: `npm run dev -- --host`, then `http://<the Mac's IP>:5173` on |
| 103 | + the iPhone over the same Wi-Fi. This is the only real test of speed and touch. |
| 104 | + |
| 105 | +## Also open |
| 106 | + |
| 107 | +- **Footer.** Evyatar has a new idea for it (not yet described). Its line |
| 108 | + border was removed in anticipation. At 1440 px on desktop the footer's last |
| 109 | + credit runs under the light control in the corner; the redesign should fix |
| 110 | + that too. |
| 111 | +- **Credits that must stay visible:** Allen Mouse Brain Atlas (CCF v3 and the |
| 112 | + Connectivity Atlas), and VesSAP / VesselGraph under CC BY-NC 4.0, which |
| 113 | + requires attribution on the page. |
| 114 | + |
| 115 | +## Map of this round's code |
| 116 | + |
| 117 | +- `src/scene/index.js`: the shell, frames, and the hand-offs between views |
| 118 | + (`vesselMix`, `funMix`, `tractsMix`), the light's focus, the fiber's fade, |
| 119 | + drag-to-turn (`turn`), and `fitFun()` for the For fun layout. |
| 120 | +- `src/scene/vessels.js`: Research. Barrel-cortex activity, the leak, the |
| 121 | + dilation wake, the beam onto the cortical surface. |
| 122 | +- `src/scene/fun/`: `landscape.js` (rest), `walks.js` (sikui), `seasons.js` |
| 123 | + (NextPredictor), `index.js` (switching and the shared fit), `common.js`. |
| 124 | +- `src/scene/tracts.js`: Connect. |
| 125 | +- `src/main.js`: section tracking, the For fun hover/caption/cycle, the fit |
| 126 | + measurement, drag-to-turn, the footer height for `#contact`. |
0 commit comments