# Responsive

Shared viewport thresholds for layouts that depend on the screen width.

## Responsive breakpoints

Two viewport thresholds are build-time custom media definitions from breakpoints.css. Each excludes its boundary and applies to every narrower viewport, so a narrow viewport matches both. Use `not` for the range above a threshold.

| Token      | Role                                                                     |
| ---------- | ------------------------------------------------------------------------ |
| `--narrow` | Phone-sized layouts: page margins, stacked shells and menus.             |
| `--medium` | Tablets and narrow desktops: collapsed navigation and editorial columns. |

```css
@media (--narrow) {
  .collection {
    --layout-gap-inline: var(--space-4);
  }
}

@media not (--medium) {
  .article {
    grid-template-columns: minmax(0, 2fr) minmax(0, 1fr);
  }
}
```

Thresholds are in rem, so they follow the browser's text size: enlarged text reaches the narrower layouts sooner. A rem in a media query refers to the browser's initial font size, not to the root element's.

Use these aliases in the owning component's styles. The package's [Vite factory](../getting-started/new-app.md#package-and-configuration) supplies and expands them through PostCSS; other consumers must configure `@csstools/postcss-global-data` and `postcss-custom-media` with `@dg/ui/breakpoints.css`.

Custom media are not runtime CSS variables: `var()` cannot provide a media-query threshold. Keep breakpoints out of runtime foundation imports. Preference queries and input capabilities remain native conditions.

## Viewport or container

Page structure follows the viewport: margins, header, footer, navigation and editorial columns. A reusable block that can sit in a full page, a sidebar or a panel follows its own width instead.

| Component                          | Condition                                                                                                     |
| ---------------------------------- | ------------------------------------------------------------------------------------------------------------- |
| `Page`, `Header`, `Footer`, `Tabs` | `--narrow`: smaller margins and gaps; header and footer wrap or stack.                                        |
| `ChatWindow`                       | `--narrow`: the launcher moves closer to the corner and hides its badge; the floating dialog fits the screen. |
| `Header` navigation                | `--medium`: links move into the menu.                                                                         |
| `Page` with an `aside`             | `--medium`: the aside stacks between the header and the content.                                              |
| Text fields, `ChatComposer`        | `(pointer: coarse)`: at least 1rem, so touch browsers do not zoom on focus.                                   |
| `Grid`                             | Container query: one column at 40rem of its own width or less.                                                |
| `Cards`                            | Measured track width: as many whole cards as `minWidth` allows.                                               |

Align app layouts with these conditions when they must change together, such as an editorial column that collapses with the header navigation at `--medium`.

## Units

Size layout in `rem`, so it follows the reader's text size together with the breakpoints: page, panel and column widths, heights, maximum widths, flex bases and type sizes. Spacing already does, through the `--space-*` scale. Set letter spacing in `em`, relative to the text it tracks.

Keep `px` for geometry that must not grow with text: strokes such as `--border-width`, the focus stroke and offsets, drawings and icons, optical adjustments and control targets such as `--control-min-size`. Browser zoom still enlarges them; only the text-size preference leaves them unchanged.
