> ## Documentation Index
> Fetch the complete documentation index at: https://docs.wpos.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Troubleshooting

> The field-learned gotcha library: symptom, cause, fix. Every entry cost a real debug cycle once.

Each entry below follows the same shape: what you see, why it happens, what
fixes it. The [verification gates](/ultra/verify) catch most of these
mechanically; this page is for when you are staring at the symptom.

## Layout

### The header links rail is centered instead of right-pinned

**Symptom:** in a `justify="space-between"` header, the links cluster sits
centered. Invisible at 1200, glaring at 1512 and wider.

**Cause:** a hidden-on-desktop mobile burger that hides its **button** but not
its **widget**. A bare `<html>` widget as the third child still occupies the
right flex slot even when its inner button is `display: none`, so the row
balances against a ghost. This broke 8 of 10 sites in one batch run, and it is
exactly what the `empty-flex-slot` probe in `eu-studio check` fails on.

**Fix:** wrap the burger widget in a box that hides the whole widget on
desktop:

```jsx theme={null}
<box w="hug" pad={0} display="none" mobile={{ display: 'flex' }}>
  <html raw={burgerHtml} />
</box>
```

Or use `navBar()`, which is immune by construction. The same ghost-slot logic
applies to any html widget whose only content is hidden or absolutely
positioned, sitting in a centered or space-between flex row: the slot
participates in layout even though nothing paints.

### A heading shrinks and overflows on mobile

**Symptom:** a headline inside a flex column renders at max-content width and
pushes past 390px.

**Cause:** headings in flex columns shrink to max-content unless given width.

**Fix:** `w="100%"` on headings inside columns.

### An absolute overlay renders at zero size

**Symptom:** `pos: 'absolute'` plus `raw="inset:0;"` and the overlay is
invisible.

**Cause:** in a flex parent the overlay has no width or height of its own;
inset alone does not size it.

**Fix:** give the overlay explicit `w="100%" h="100%"` and the parent
`pos: 'relative'`.

### A fixed overlay is trapped inside the nav

**Symptom:** a `position: fixed` mobile menu positions itself relative to the
header instead of the viewport.

**Cause:** `backdrop-filter` on the nav creates a containing block for fixed
descendants.

**Fix:** toggle the filter off while the overlay is open:
`.open { backdrop-filter: none }`.

### A marquee or bleed decoration widens the page

**Symptom:** `check` fails at some width with an overflow offender that is a
decorative strip or marquee.

**Cause:** the decoration legitimately extends past the section edge.

**Fix:** `raw="overflow:hidden;"` on the section that contains it.

### Text never wraps on mobile

**Symptom:** a mono or nowrap line overflows 390px.

**Cause:** `white-space: nowrap` (and mono blocks styled that way) wrap
nowhere.

**Fix:** cap the width or allow wrapping below the tablet breakpoint.

## CSS and deploy state

### The page loads but looks unstyled or broken

**Symptom:** content renders, styling is partly or fully missing.

**Cause:** one of several CSS lifecycle failures: a stylesheet that 404s (or
301-redirects to the homepage and "serves" as HTML), an unprimed atomic page,
or a stale cache.

**Fix:** run `eu-studio doctor`. It checks every stylesheet the page enqueues
(asserting content-type, not just status), names the failing ones, and heals
via cache regen plus re-prime with retries. Do not hand-grep page HTML; the
doctor is faster and it is right.

### The page renders collapsed, sections stacked at a fraction of their height

**Symptom:** a previously fine page suddenly renders compressed or z-stacked;
`check` may fail `css-coverage`, naming classes no stylesheet defines.

**Cause:** the global class store lost classes the page references. The known
trigger is an Elementor editor session writing back an incomplete store copy.
On real sites the [companion plugin](/ultra/plugin) blocks the worst case (the
mass-deletion 409) and keeps a restorable backup; on the playground the store
can still lose classes.

**Fix:** redeploy from source (`exjsx deploy`, idempotent), which rewrites the
store; or on a plugin-guarded site, `POST
/elementor-ultra/v1/design/classes/restore`. Then `eu-studio doctor` to
confirm.

### Styles keep flaking on the playground specifically

**Symptom:** doctor heals CSS, it breaks again later, repeatedly.

**Cause:** the WASM playground's css file store is the flaky part, not your
build.

**Fix:** `eu-studio carry-css --page <id>` once at the end of the build: the
page's generated CSS is baked in as an inline carrier and survives the file
store. See also the CSS harvest recipe in the eu-studio README for the
last-resort path.

## Design review catches

### Dark theme text is unreadable on some screens

**Symptom:** body copy that looked fine in the editor is muddy on a real
display.

**Cause:** low-contrast ink on near-black backgrounds; hex values lie about
perceived contrast.

**Fix:** keep body text at roughly `#b0b8c0` or lighter on near-black, and
judge contrast in screenshots (`eu-studio measure shots`), not by hex.

### Fonts measure wrong everywhere

**Symptom:** every geometry measurement is slightly off; line wraps differ from
the design.

**Cause:** a family referenced only inside raw html widgets or `raw=` CSS is
invisible to Elementor's font enqueue and silently falls back.

**Fix:** name the family in a style prop somewhere, or add
`fontLoader('Family', [400, 700])` first in the tree. Confirm with
`eu-studio measure fonts`, which reports which families actually painted.
`exjsx lint` warns about this (`font-not-loaded`).

## When a deploy is refused

* **A 422 naming an envelope:** the server-side validator is authoritative; fix
  the named envelope. The compiler's build-time gates catch almost all of these
  first.
* **`skipped-drifted` pages:** someone hand-edited the page in Elementor.
  Reconcile or consciously `--force`; see [Deploy](/ultra/deploy).
* **A class-store refusal telling you another project lives here:** you are
  deploying a side bundle to an occupied site; the merge guard is protecting
  the resident project. See [Deploy](/ultra/deploy).

<Tip>
  Most of this page is encoded in the gates: `exjsx lint` catches the authoring
  mistakes at build time, `eu-studio check` catches the layout failures in one
  call, and `doctor` diagnoses the CSS lifecycle. Run the gates first; read
  this page when a symptom survives them.
</Tip>
