Both themes set `fontFamily: Inter`, and Inter carries no Ge'ez glyphs. So
every Amharic string in a bilingual system — 45-73 KB of locale data per app —
has been rendering in whatever font the OS happened to substitute: different on
Windows, macOS and Android, and matching neither the design nor each other.
Noto Sans Ethiopic goes directly after Inter in one stack rather than being
swapped in under `[lang='am']`. Browsers fall back per glyph, not per element,
so a single stack renders Latin in Inter and Ge'ez in Noto automatically —
including within one string. That is the case that matters here: a registry is
full of mixed-script lines like an Amharic name beside a Latin IMO number, and
a language-scoped swap renders half of those in the wrong face.
Heading line-heights go up a step at the same time. Ge'ez has taller ascenders
and deeper descenders than Latin, so headings set to Inter's natural leading
clip once Ethiopic is actually being rendered. This was deliberately held back
from the theme refactor so that change could prove it altered nothing.
The gallery gains Ge'ez headings and a mixed-script line, so the baselines
cover the case rather than only Latin.
Follow-up: both fonts still load from Google Fonts via a render-blocking CSS
@import. Self-hosting with a subset and preload links is worth doing —
government networks frequently make fonts.googleapis.com slow or unreachable,
and silent Amharic fallback is precisely the failure this commit fixes.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Tailwind was configured but had no effect. There is no postcss config anywhere
in the repo, so the three `@tailwind` directives in the backoffice stylesheet
were never expanded — they passed through verbatim into the production CSS
bundle as invalid at-rules for browsers to discard. The portal's copy could not
even do that: nothing imports `apps/portal/src/styles.css`.
The utility classes visible in the built CSS come from the vendored
@tria-plc/iamui package, which ships its own pre-compiled stylesheet and
declares only React as a peer dependency. Removing Tailwind here does not
affect it.
`tailwind-merge` goes too — no file in apps/ or libs/ imports it. postcss and
autoprefixer stay; Vite uses them independently.
Also fixes a bug this uncovered. The orphaned portal stylesheet was not dead
code — it contained scrollbar theming the portal never received, so it has been
rendering raw OS scrollbars while the backoffice got themed ones. Those rules
move to portal.css, which actually loads. Deleting the file without reading it
would have silently kept that gap.
No visual change: all 8 baselines pass unmodified.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>