One Support Call, Four Bugs: A Postmortem on Our AI Website Builder A WebDigitize engineer found four bugs in the AI website builder after a customer reported a collapsed hero section. The bugs spanned the editor, CSS layout system, AI onboarding pipeline, and database ORM, with one bug hidden inside the fix itself. The incident highlights the limitations of @media queries for component-level responsiveness. I discovered a page on our customer's site that, at first glance, appeared to be a CSS bug. A hero section on her site had collapsed into a vertical sliver — a fashion-photo strip about 70 pixels wide, running the full height of the page, with her headline text wrapping into a column one word deep. Below it, the same broken hero repeated itself. The service cards that should have been on the page were gone. It's the kind of screenshot that makes you assume you know the fix before you've looked at anything. A missing breakpoint, probably. Ship a CSS patch, close the ticket, move on. I was wrong about the scope in almost every direction. By the time I was done, I'd found four separate bugs, two of them in completely different parts of the stack, and one of them entirely unrelated to the customer's report — a bug in the fix itself. This is a write-up of what actually happened, in the order I found it, because the order matters: each bug looked like the whole story until the next one showed up underneath it. WebDigitize is an AI website builder for Nigerian small businesses — describe your business, get a live, editable, multi-page site in minutes, built on a drag-and-drop editor Puck https://github.com/measuredco/puck with an AI layer on top. The incident touched the editor, the CSS layout system, the AI onboarding pipeline, and — in the least expected turn — the database ORM. The customer had onboarded as a business selling physical products, added a handful of items to her catalog, and picked a general-purpose template rather than one of the commerce-flavored ones it was the best fit for how she described her business . The site generated fine. Interestingly, I launched WebDigitize the previous day, so I was checking to see if there were new onboards. I saw her website on the dashboard and decided to check out each page. That was when I discovered the issue. I followed up with a call, and she confirmed exactly what happened. She went looking for her products on the live site and couldn't find them anywhere — no shop page, no product grid, nothing. So she opened the editor on her phone and started poking at the Services page, trying to see if the products were hiding in a section she hadn't looked at. That's where the sliver came from. The page's hero component — a two-column "text on the left, full-height photo on the right" layout — had been dragged, on a touchscreen, into a three-column grid meant for service cards. A hero designed to occupy the full page width was now confined to one-third of it, and its internal CSS a 7fr / 5fr grid split rendered that third into two even-narrower slivers. The section had also been duplicated somewhere in the process, which is why I saw it twice. The obvious read: "customer made a drag-and-drop mistake on mobile, CSS broke because nobody designed for a hero being squeezed that small." Both true. Also, not remotely the full story. The hero component's CSS looked like this before I touched it: .hero-split { display: grid; grid-template-columns: minmax 0, 7fr minmax 0, 5fr ; } @media max-width: 899px { .hero-split { grid-template-columns: minmax 0, 1fr ; } } A perfectly reasonable component, built around one assumption: the only thing that would ever make this hero narrow is a narrow viewport . On a phone, stack the columns. On a desktop, split them 7:5. That assumption is true right up until someone drops the component somewhere that isn't the full page width — inside a grid column, a sidebar, anywhere the component's rendered width is decoupled from the browser's. @media queries answer "how wide is the viewport?" They cannot answer "how wide is this component, right now, wherever it's been placed ?" That second question is what a component with an internal responsive layout actually needs answered, and for a long time, CSS had no good way to ask it. The fix is a container query — CSS that responds to an element's own size rather than the viewport's: .hero-section { container-type: inline-size; } @container max-width: 899px { .hero-split { grid-template-columns: minmax 0, 1fr ; } } Same breakpoint, same fallback layout — the difference is what's being measured . Now, if this hero ever ends up somewhere narrow, for any reason, at any nesting depth, it stacks gracefully instead of dividing an already-small box into two useless columns. We didn't design this fix for "what if someone drags a hero into a grid cell" specifically — we designed it for "this component should never assume it owns the full viewport," which is the more durable version of the same idea. The next unanticipated place a hero ends up will handle itself the same way. If you maintain any component library with a component that has an internal responsive layout, this is worth auditing today: every @media -based internal layout in a component that could ever be nested is a latent version of this bug, just waiting for someone to place the component somewhere you didn't design for. The CSS fix makes the outcome of a hero-in-a-grid drop survivable. It doesn't answer the more basic question: should our drag-and-drop editor have allowed that drop in the first place? No. A full-width hero, a call-to-action banner, a page section — these are page-level compositional elements. They don't have a sensible meaning inside a three-column card grid, any more than it makes sense to put a