Override on :root, not a wrapper. Modals, dropdowns, and tooltips render in a portal at the end of the page, so a selector scoped to a wrapper around the editor will not reach them.
Load your stylesheet after Updog’s. Both sit at :root, so they share specificity and source order decides the winner.
Inspect to find the token. Open devtools on the element you want to change, read the var(--updog-*) in its rule, and override that token. The names map to what you see: surface is background, content is text, border is lines.
Updog ships no dark theme. Build one by re-declaring variables under your own dark selector. The canvas grid repaints automatically when the theme changes.
Work with the ramps rather than the semantic tokens:
Point --updog-ramp-light at your dark base.surface-layer0 and every low shade you do not tune lean toward it, so nothing strays light. Leave --updog-ramp-dark black.
Set the gray ramp. Surfaces, borders, content, disabled, and the neutral tag all derive from gray shades, so tuning the ramp flips them together. The high grays carry text and must be light; the low grays are tuned for surface depth, since a linear mix lacks separation in the dark band.
Invert the colored ramps. Point each 50 and 100 shade at its dark counterpart (--updog-brand-50: var(--updog-brand-950)), which flips button hovers, tag and tooltip backgrounds, selection, edited and invalid cells, matches, and skeletons.
Keep the row status bars saturated so the strip stays visible.
.dark {
/* Dark base: surface-layer0 and every untuned low shade lean toward this, so
nothing strays light. Leave ramp-dark black so the -950 shades the colored
ramps invert toward stay dark. */
--updog-ramp-light: #0f1115;
/* Gray ramp. Surfaces, borders, content, disabled, and the neutral tag all
derive from these. The high grays carry text, so they must be light; the
low grays are tuned for surface depth. */
--updog-gray-50: #161a20;
--updog-gray-100: #1e232b;
--updog-gray-200: #262c36;
--updog-gray-300: #2f3641;
--updog-gray-400: #5c6370;
--updog-gray-450: #5c6370;
--updog-gray-500: #6b7280;
--updog-gray-600: #a8aeb8;
--updog-gray-950: #e6e8eb;
/* Colored ramps invert: subtle fills go dark, accents and text stay bright */
--updog-brand-25: var(--updog-brand-950);
--updog-brand-50: var(--updog-brand-950);
--updog-brand-100: var(--updog-brand-900);
--updog-red-50: var(--updog-red-950);
--updog-red-100: var(--updog-red-900);
--updog-yellow-50: var(--updog-yellow-950);
--updog-yellow-100: var(--updog-yellow-900);
--updog-green-50: var(--updog-green-950);
--updog-green-100: var(--updog-green-900);
--updog-blue-50: var(--updog-blue-950);
--updog-blue-100: var(--updog-blue-900);
/* Keep the row status bars saturated so the strip stays visible */
Changing a base color such as --updog-brand does not produce dark mode. The generated shades always run light to dark in the same direction, so a base swap only tints. Inverting the light shades is what turns the polarity around.
A few more things:
Apply your dark selector high in the page, above the editor and the portal root, not on a wrapper around the editor, so it reaches the portaled modals and dropdowns. The canvas grid repaints on the change.
Keep --updog-content-inverse light. It is the text on brand-colored buttons, so it should stay light in dark mode.