Why this page exists
FiveM’s embedded browser is Chromium 103. Your development browser is several years newer. That gap is expensive because the failures are silent and one-sided:bun run start looks perfect, you ship, and the UI is broken in-game. Every item below was paid for once already. The kit carries the fixes so you do not pay again.
oklch() is not parsed
The 9AM tokens are authored in OKLCH. Chromium 103 cannot read them, so every token resolves to nothing and the interface renders completely unstyled in-game.postcss.config.js converts them at build time:
bun src/scripts/9am-ui.mjs doctor runs this check for you, including scanning your built CSS.
Tailwind v4 separately emits a hex fallback before each color-mix() behind an @supports guard, which is why color-mix is safe to use.
Wheel scroll does nothing on clipped containers
CEF’s compositor will not scroll aclip-path’d container with the mouse wheel. The event reaches the page; the scroll never happens. Since Viewport uses clip-path, that means nothing scrolls.
installSmoothScroll() catches the wheel event and drives the scroll from JavaScript. Call it once in main.tsx.
mask does not apply to backdrop-filter output
A gradient mask over abackdrop-filter is ignored (crbug.com/41465359, fixed in later Chrome).
Viewport fakes the gradient by stacking bands of fixed blur with progressively shorter spans. The blur values are chosen so the combined result increases linearly toward the edge — each step lands under half a pixel, so the eye cannot pick out the bands.
No :has(), no @container
Both need Chromium 105+. Where the kit needs them it computes the result in JavaScript instead.ViewportHeader detects a ViewportAction child at the React level and applies its grid columns directly, rather than using :has().
If you find yourself reaching for either, restructure the component or resolve it in JS.
overflow + border-radius does not clip composited layers
Rounded corners withoverflow: hidden do not clip composited layers — scrolled content and backdrop-filter output escape the radius.
Use clip-path instead, which the compositor applies to every layer:
Viewport uses clip-path, which is in turn why the wheel-scroll fix is required. The two are linked.
Tailwind v4: @theme inline emits no custom properties
Not a CEF issue, but it bites in the same way — silently, and only in some contexts. Variables declared in@theme inline are inlined into the generated utilities. They do not exist as CSS custom properties at runtime:
`bg-primary-${n}` generates no CSS — spell out each class you intend to use.
Checklist before shipping a NUI
1
Confirm the CSS is CEF-safe
2
Confirm smooth scroll is installed
installSmoothScroll() runs in main.tsx.3
Test in-game, not just in the browser
Scrolling, blurred edges, and anything using a modern selector need a real CEF check.
ensure <resource> and look at it.4
Run doctor