Another minimalist CSS framework, another review from me. :-)

> :root { color-scheme: dark light; }

The stylesheet is written with light values by default, and dark values in a prefers-color-scheme media query. Therefore, this should be `color-scheme: light dark` instead. As written, if no preference is expressed, your styles will be light, but UA styles will be dark.

> * { box-sizing: border-box; }

I personally am one of the rare contrarians that prefers content-box for the web (simplifying my position a lot: good responsive design bases sizes and such on content, not layout). But if you’re going to change it to border-box, you might want to consider changing it on pseudoelements (at least ::before and ::after) as well. Then again, you’re not using them. Then too, the whole box-sizing declaration seems no-op.

> * { color: var(--dark); }

That’s… um… courageous. No, I can’t leave it at that: this is a very bad idea. This will make custom styling painful, may ruin elements that have backgrounds set in the UA stylesheet (e.g. input, mark), and I detest links being the same colour as the surrounding text.

> :root { --light: …; --dark: …; }

I don’t like how these two variables are used: you’re using them as #defines (to use C preprocessor lingo) rather than what custom properties can be, and end up with significant duplication because of it. Consequently, every time you use --light or --dark, you have a counterpart the other way round in the tail @media (prefers-color-scheme: dark) block (except that input[type=submit]’s counterpart is just input; I’ll remark on that later). Here’s how you should do it:

:root {
--bg: #fff;
--fg: #404040;
}

@media (prefers-color-scheme: dark) {
:root {
--bg: #404040;
--fg: #fff;
}
}

… and then use --bg and --fg throughout, and need no more dark color scheme media query at the end. You could define two colours and have --bg and --fg use them, but because of how light works, you may not want to just swap the two colours—for example, you might want to darken both --bg and --fg in dark mode (it’s currently fairly bright for a dark mode; something like #eee on #333 would be more common).

> html { border-style: solid; border-width: 5px 0 0 0; border-color: var(--dark); }

Shorter written in the :root block before it and as `border-top: 5px solid var(--dark)`. As for what it represents, I don’t like it. It’ll tend to be an eyesore, especially on dark. If it was a colour, sure, but just --light or --dark? Nah, don’t like it.

> font-family: sans-serif;

Thank you for a sensible font-family.

> px

There’s quite a bit of not-great usage of pixels. Remember that the root em is not necessarily 16 pixels, so for correctness most px things should actually be defined font-relative. As a simple rule of thumb, take any px value, divide by 16 and change the unit to rem. (Single-pixel lines are about the only place I can think of where px is genuinely what you want, though even then it’s still not guaranteed to be a crisp single pixel, due to possible fractional scaling.)

> p { margin-bottom: 10px; }

This doesn’t do what you probably intended. Indeed, in the sample document, I think it does nothing: remember that most of your flow content elements have 1em block margin, which is (likely) greater than your 10px, and margin collapse applies.

> p { line-height: 1.4em; }

Dubious: now anything that’s not inside a <p> uses some other line-height. You probably want to specify line-height on the root element. Remember that line-height accepts a unitless value, too, to be calculated relative to each element’s font-size, whereas em fixes it. Me, I’ve actually started experimenting with this, to conveniently reduce otherwise-extravagant leading in headings:

* {
line-height: calc(1em + 0.5rem);
}

That is, 1rem (16px) body text gets line-height 1.5 (24px), 2rem (32px) heading gets line-height 1.25 (40px).

> img { width: 100%; }

This needs `height: auto`, or else <img width=… height=…> (which you should strongly prefer, to avoid layout reflow as the image loads) will get a mangled aspect ratio. Also consider using max-width instead of width.

> button, .button, input[type=submit]

I’m not fond of various of the styling here. I reckon it could do with a hover/focus-visible colour change, and no `cursor: pointer`, among other things.

> button:last-child, .button:last-child { margin-right: 0; }

This kind of thing is smelly.

> ol { column-count: 2; }

This is a phenomenally bad idea. Some opt-in class, maybe. Numbered lists in general, no.

> .row .column:not(:last-child) { margin-right: 10px; }

Better, provided you’re OK with as low as two years (to the day!) of browser support (https://caniuse.com/flexbox-gap): `.row { gap: 10px }`.

> Put in four columns and you'll get four equally sized columns.

Not true, actually; put something too big in one column and it’ll cause the other columns to shrink. That’s what you get for using flexbox! (Grid, by contrast, is… well, more size-is-defined-by-the-parent-and-the-children-are-welcome-to-lump-it.)

Really, I don’t like the columns arrangement. I much prefer to use flexbox with flex-wrap and sensibly-chosen flex-{basis/shrink/grow}, so that the content defines when things can fit beside one another or wrap. The current .row and .column arrangement is much too fiddly, specific, and weird. Also the .column class name is superfluous, should have just used `.row > *`.

> input

I said I’d address this later, but I’ve taken too long on this. Suffice it to say that there are problems with how form elements other than buttons are handled in diverse colouring situations. Either override (nigh-) everything, or nothing. Never override just one of background and foreground colour.