Engineering Journal
Ginexys
Ginexys

Modal Renders Unstyled in a Tool That Does Not Load Portfolio.css

2026-06-03

TLDR

When embedding our shared modal stylesheet (ginexys-modals.css) into a standalone build of the PDF Processor tool, modals rendered as completely unstyled HTML forms. The modal stylesheet referenced 20 CSS custom properties defined in portfolio.css. Because PDF Processor used its own isolated design tokens, the modal variables evaluated to empty strings. We resolved the issue by extracting the 20 required variables into a lightweight, collision-free ginexys-modals-tokens.css (2KB) file.
ApproachFile size and overheadsCSS collision riskModal rendering status
Import portfolio.css48KB full stylesheetHIGH (Overrides global root, body, flex layouts)Correct
Extract tokens (ginexys-modals-tokens.css)2KB isolated contractZERO (Only defines surface-raised, etc.)Correct

Missing CSS custom properties fail silently in production environments

When a user opened /tools/pdf-processor/ as a standalone app and clicked a modal trigger, the modal rendered as plain, unstyled text inputs stacked on a white background:

Inspect element in DevTools showed:
background: ; border-radius: ; color: ;

Because CSS custom properties that fail to resolve evaluate silently to empty strings without throwing console warnings or syntax errors, the component failed silently in production.


Design token discrepancies trigger broken component styling

ginexys-modals.css relies on 20 shared design tokens:

.gx-modal {
  background: var(--surface-raised);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-lg);
  color: var(--text-primary);
  font-family: var(--font-body);
}

These variables were originally declared inside portfolio.css. However, PDF Processor maintains its own internal layout system (src/styles.css) using different variable names.

+-------------------------------------------------------------+
Token Resolution Contract
ginexys-modals.css
v
Token Provider Present?
/ \
Without portfolio.css With modals-tokens.css
/ \
v v
Variables resolve to Variables resolve to
empty strings scoped hex values
v v
Unstyled HTML Correct Rendering
+-------------------------------------------------------------+

Loading portfolio.css directly into PDF Processor was impossible. portfolio.css includes global selectors that completely ruined PDF Processor flexbox column layout.


Dedicated design token contracts decouple shared component styles

We extracted the 20 variables expected by ginexys-modals.css into a standalone, scoped tokens file:

/ assets/css/ginexys-modals-tokens.css /
:root {
  --surface-raised:        #1b2835;
  --surface-overlay:       #192230;
  --border-default:        #1e3348;
  --text-primary:          #d8eaf8;
  --gold-base:             #00b4d8;
  --radius-lg:             10px;
  --font-body:             "DM Mono", monospace;
  / 20 explicit modal variables /
}

[data-theme="light"] { --surface-raised: #f2f8ff; --border-default: #42586c; / Light theme overrides / }

PDF Processor now includes the lightweight token contract before the modal stylesheet:

<link rel="stylesheet" href="src/styles.css">
<link rel="stylesheet" href="/assets/css/ginexys-modals-tokens.css">
<link rel="stylesheet" href="/assets/css/ginexys-modals.css">

To ensure no new modal changes introduce un-tokenized variables, we run a pre-commit check:

# Extract all CSS custom property references from modal stylesheet
grep -oE "var\(--[a-z0-9-]+" assets/css/ginexys-modals.css | sort -u
Rule of thumb: CSS custom properties fail silently. When publishing shared CSS UI components across standalone apps, always extract the required :root design tokens into a standalone, side-effect-free token contract file.
Read this post in the full Engineering Journal →