{% raw %}
# Responsiveness
The interface works from a 320px phone to a wide desktop without a separate mobile site. The same HTML reflows; only the CSS changes per breakpoint.
## The goal
- **One readable column on small screens.** Multi-column layouts collapse to a single fluid column; secondary rails are dropped, not squeezed.
- **No accidental horizontal scroll.** Long content (code, URLs, tables) is contained, never pushing the page wider than the viewport.
- **Comfortable touch targets.** On touch devices every interactive element is at least `44 x 44px`.
- **No iOS zoom-on-focus.** Form controls are at least `16px` on touch devices so Safari does not zoom when they are focused.
- **Respect device safe areas.** Floating controls keep clear of notches and home indicators with `env(safe-area-inset-*)`.
The viewport is declared once in `base.html` and must not be changed:
```html
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">
```
## The standard breakpoint ladder
Use these four breakpoints. They are `max-width` (desktop-first refinements) and the ones the shared shell already targets, so a page that uses them stays in step with the nav, breadcrumb, and footer.
| Breakpoint | What changes |
|-----------|--------------|
| `1024px` | Multi-column layouts collapse to one column; the right rail is hidden; the top nav links collapse into the hamburger menu; the page padding tightens. |
| `768px` | Horizontal tab strips (feed tabs, project tabs) switch to a single scrolling row; labels shrink. |
| `480px` | Compact paddings; secondary actions hidden; post/detail typography steps down; `grid-2col` becomes one column; floating buttons honour safe-area insets. |
| `360px` | Headers allowed to wrap; timestamps drop to their own line; the comment avatar is hidden so the input keeps room. |
> The ladder is exact and enforced: every stylesheet uses only `1024 / 768 / 480 / 360` (plus the capability queries below). The one-off breakpoints that used to exist (900, 720, 640, 600, 560, 520) were consolidated by snapping each up to the next canonical stop. **Do not add new ad-hoc breakpoints**; if a component genuinely breaks between two stops, raise it in `static/css/CLAUDE.md` first.
## How it is achieved
**Collapse a grid to one column.** The whole mobile story for a multi-column page:
```css
@media (max-width: 1024px) {
.feed-layout { grid-template-columns: 1fr; }
.feed-right { display: none; }
}
```
**Keep the fluid column from overflowing.** A grid/flex child does not shrink below its content unless told to. Every fluid main column sets:
```css
.feed-main, .leaderboard-main { min-width: 0; }
```
**Let tab strips scroll instead of wrapping or overflowing:**
```css
@media (max-width: 768px) {
.feed-nav { overflow-x: auto; flex-wrap: nowrap; -webkit-overflow-scrolling: touch; }
.feed-nav-btn { flex-shrink: 0; }
}
```
**Guarantee touch targets and prevent zoom.** One shared rule in `base.css` covers every page, so pages do not repeat it:
```css
@media (hover: none) and (pointer: coarse) {
.btn, .topnav-link, .sidebar-link, .post-action-btn, .profile-tab { min-height: 44px; }
.topnav-icon, .emoji-toggle-btn { min-width: 44px; min-height: 44px; }
.modal-card input, .modal-card textarea, .modal-card select { font-size: 16px; }
}
```
**Keep floating controls off the notch / home bar:**
```css
@media (max-width: 480px) {
.feed-fab {
bottom: calc(1rem + env(safe-area-inset-bottom));
right: calc(1rem + env(safe-area-inset-right));
}
}
```
**Respect reduced motion, globally.** One rule at the end of `base.css` collapses every animation and transition to a near-zero duration under `prefers-reduced-motion: reduce` (near-zero rather than `none`, so JavaScript `transitionend`/`animationend` handlers still fire). Pages never need their own reduced-motion query; a page-level one is only for content that must *also* change visually (for example stopping an indeterminate progress bar).
## Rules
1. **Use the four standard breakpoints** (`1024 / 768 / 480 / 360`); do not invent new ones without a written reason.
2. **Every fluid grid/flex column sets `min-width: 0`.** This single line prevents almost all horizontal-overflow issues.
3. **Collapse, do not cram.** Below `1024px` a page is one fluid column; drop side rails with `display: none` rather than shrinking them to slivers.
4. **Never override the viewport meta or the shared touch-target rule.** They are global; rely on them.
5. **Test the small end.** The hard cases are `360px` (wrapping) and long unbroken strings inside a card.
{% endraw %}
Live reflow (three columns to two to one as the viewport narrows)
Item one
Item two
Item three
Item four
Item five
Item six
This grid uses the standard 768px and 480px breakpoints. Narrow the browser to watch it step from three columns to two to one.