Open Nyquest on a phone last week and you would have seen a lovely welcome screen, four suggested prompts — and no way to type. The chat composer, the single most important control in a chat app, rendered 82 pixels below the bottom of the screen. You could scroll down to find it, if you thought to. Most people, reasonably, thought the app was broken. Most people were right.
This post is the postmortem and the fix: one layout mistake that broke all eleven of our visual chassis at once, plus three more bugs underneath it that turned out to be the same CSS rule wearing different costumes, plus a hamburger menu that had been silently deleted by a stylesheet loading order. Everything below was measured on the live app before and after.
Every Nyquest chassis — the visual themes you can switch between — builds its shell the same way: a grid pinned to height: 100vh. Header on top, chat below, composer docked at the bottom. On its own, that works.
Then anonymous visitors got a free-mode banner, mounted above the shell, in normal document flow. Desktop users saw a slim strip and never noticed the whole app quietly sliding down by its height. On a 375px-wide phone, that banner wrapped its copy and two buttons into a block 261 pixels tall — a third of the viewport — and the shell, still stubbornly 100vh, carried the composer straight off the bottom of the screen. On every theme. For every anonymous visitor. Which on a phone is essentially everyone we would like to impress.
The fix is the boring, correct one: the banner and the shell now share a single viewport-height flex column, and the shell takes whatever is left instead of insisting on all of it. We also moved from 100vh to 100dvh where supported, so the layout tracks the space that is actually visible when mobile browsers collapse their URL bars, instead of the space that would exist in a perfect world.
With the composer back on screen, the sweep got interesting. Three seemingly unrelated bugs fell out of testing, and they were all one CSS behavior: a grid track politely refuses to be smaller than its most stubborn child. Grid and flex tracks floor at their content's minimum size unless you explicitly tell them not to.
Costume one: on phones, several chassis topbars measured 415 to 489 pixels wide in a 375-pixel viewport. The brand mark, the buttons, and the pills added up to more than the screen, and instead of squeezing, the topbar widened the shell's grid column and dragged the whole app past the right edge.
Costume two: the icon rail down the left side holds twelve navigation buttons — about 556 pixels of them. On a short screen the same rule played out vertically: the rail's height blew out the body row, and the composer slid behind an inner scroll. Same rule, rotated ninety degrees.
Costume three is my favorite, because it was caused by an accessibility fix. iOS Safari auto-zooms the page when you focus any input smaller than 16px, so we floored the composer font at 16px on phones. Fonts change a textarea's intrinsic width — which propagated up through the form, into the grid column, and pushed the layout 59 pixels past the viewport. The fix for phones broke phones.
All three died the same way: minmax(0, 1fr) on the tracks and min-width: 0 down the composer's chain, which tells the layout that the viewport, not the content, is in charge. The topbar brand now truncates instead of shoving, the rail scrolls itself when it runs out of room, and the textarea keeps its 16px without redesigning the building around it.
The honest section. Our mobile drawer — the panel with your conversation list — had a hamburger button, styling, slide-in animation, backdrop, escape-key handling. All of it shipped. None of it was reachable, because a later-loading stylesheet contained one line, display: none, that was supposed to hide the button on desktop and instead hid it everywhere. CSS gives the last loaded rule the win, the mobile rule loaded first, and the entire drawer feature spent months as decoration. On a phone there was simply no way to reach your past conversations.
No exotic bug, no deep lesson — except this one: a feature is not shipped when the code merges. It is shipped when someone watches it work on the device it was built for. We had built it and never stood where a phone user stands.
| Measurement (375×812 phone) | Before | Now |
|---|---|---|
| Free-mode banner height | 261px | 42px |
| Page height vs. screen | 1,027px — composer off-screen | 812px — exactly the screen |
| Widest chassis topbar | 489px | 375px |
| Conversation drawer | unreachable | opens |
| Composer font on focus (iOS) | 14px — page zooms | 16px — no zoom |
Being precise about the claim: this is a repair, not a redesign. There is no separate mobile app, no reduced feature set, no “lite” anything — every chassis, the model picker, the Splicer, and anonymous free chat work on a phone the same way they do on a desktop, on the same page. Desktop layouts are untouched. And phones did not become our primary design target overnight; they became a place where the app works, which is a lower bar we are no longer tripping over.
Nobody funds a wallet, brings a key, or compares models through an app whose send button they cannot see. Phones are where a first impression of Nyquest is most likely to happen and where it was, until this week, at its worst. The gap between “works on my machine” and “works in your hand” was three CSS rules and a stylesheet ordering — small fixes, found the only way they ever are: by standing where the user stands and measuring what they actually see.