/* Okabe-Ito, because a site about colorblind-safe figures that themed itself
   on an arbitrary hue would be making the argument badly.

   The two link colors are different on purpose, and the numbers are the
   reason. Measured with this project's own `contrast()` against the surface
   each one is actually drawn on. There are three surfaces, not two: Zensical
   ships two theme variants and their dark backgrounds differ, `modern` at
   hsl(225, 15%, 5%) and `classic` — the Material for MkDocs look — at
   hsl(225, 15%, 14%). Neither is neutral; both are blue-tinted.

                        on white   slate classic   slate modern
                                      #1e2129        #0b0c0f
     #0072B2 (blue)       5.19:1       3.10:1          3.77:1
     #56B4E9 (sky)        2.31:1       6.98:1          8.48:1

   Body-text links need 4.5:1 (WCAG AA), not the 3:1 floor a figure's series
   colors are held to — a link is text being read, not a mark being told apart
   from its neighbour. Blue clears 4.5 on white and misses it on both dark
   backgrounds, so dark mode takes sky instead. Using one hue for both would
   have shipped a site about colorblind-safe figures whose own dark-mode links
   miss the floor the project exists to enforce.

   `zensical.toml` selects the variant, so the choice is one line away from
   changing. Quoting the variant actually in use and no other would make this
   comment true until someone flipped that line and false silently afterwards,
   which is the failure mode the whole project is about. Both columns are
   recomputed by `tests/test_docs_site.py`, and the floor is asserted against
   the worse of the two.

   All of that is arithmetic about two hex values, and it stays true whether or
   not either one reaches the screen — which is a thing that has happened here.
   `tests/test_docs_render.py` renders the site and measures what is painted. */

:root {
  --fg-blue: #0072b2;
  --fg-sky: #56b4e9;
}

/* Bare attribute selectors. The `:root` that looks like it belongs in front of
   them is a bug, and it shipped.

   Zensical sets `data-md-color-scheme` on `<body>`. `:root` is `<html>`, so
   `:root[data-md-color-scheme="slate"]` matches zero elements and takes this
   whole file off the page with it.

   It was added to win a specificity fight that does not exist. With
   `primary`/`accent` set to "custom" no theme `[data-md-color-primary=...]`
   rule matches at all, and the theme's `:root` block loses to a declaration on
   `<body>` by inheritance, not by specificity — there is no contest to lose.
   Both upstreams document `:root > *` for this, which selects the body.

   `tests/test_docs_render.py` asserts these rules reach the page. */

[data-md-color-scheme="default"] {
  --md-primary-fg-color: var(--fg-blue);
  --md-primary-fg-color--light: var(--fg-sky);
  --md-primary-fg-color--dark: #005b8f;
  --md-accent-fg-color: var(--fg-blue);
  --md-accent-fg-color--transparent: #0072b21a;
  --md-typeset-a-color: var(--fg-blue);
}

/* Dark: sky, at 6.98:1 on classic and 8.48:1 on modern. Blue would be 3.10
   and 3.77, under the floor on both. */
[data-md-color-scheme="slate"] {
  --md-primary-fg-color: var(--fg-blue);
  --md-primary-fg-color--light: var(--fg-sky);
  --md-primary-fg-color--dark: #005b8f;
  --md-accent-fg-color: var(--fg-sky);
  --md-accent-fg-color--transparent: #56b4e91a;
  --md-typeset-a-color: var(--fg-sky);
}

/* The header deliberately sets no color here.

   A `.md-header { color: #ffffff }` used to, carried over from the Material
   look where the header is a solid bar filled with the primary color. `modern`
   does not fill it — the header is translucent over the page, white at 0.7
   alpha in light mode — so that rule composited to white on white, 1.00:1, and
   the site's own name was invisible.

   The theme's own header foreground is right for both variants: 16.07:1 light,
   19.56:1 dark. Anything put back here has to be measured against the
   composited surface, not against `--md-primary-fg-color`. */

/* Palette swatches.

   The style guide states hues as hex. Every number beside them is recomputable
   — a contrast ratio goes back through `contrast()` — and the hue is not, which
   left the Hue column answering it with the word "vermillion". So the site
   paints the square.

   It is `::before` on the code span holding the hex, not a sibling element.
   The first version was a sibling, and a swatch can be separated from its hex
   by a line break: the diverging poles wrapped, leaving a red square at the end
   of one line and `#b1182b` at the start of the next. Generated content cannot
   be orphaned from the element that generates it, and `nowrap` closes the one
   break opportunity left, inside the code element itself.

   The hex travels in `--c` rather than in a class per hue. A class per hue
   would put a third copy of the palette in this file, an editing distance away
   from the two that already have to agree; `--c` keeps the copy on the element
   whose text it is a claim about, which is also what lets the tests read the
   pair as one thing.

   `content-box`, and the dark-mode mat below is drawn as `box-shadow` rather
   than as a thicker border. One point, twice: either alternative takes its
   4px out of the color area instead of out of the margin, which at this type
   size is a third of the hue. The first draft used border, and slot 1 read as
   an outline with something dark inside rather than as black.

   The border is not decoration. `#ffffff` is the surface row of the ink table
   and is the page it is drawn on; `#F0E442` is slot 5, at 1.32:1, which at
   11px is not reliably distinguishable from it. Without a frame both read as a
   failed image rather than as the hue they assert. `tests/test_docs_render.py`
   measures that the frame has width, for the same reason it measures the
   fill. */
.md-typeset code.sw {
  white-space: nowrap;
}

.md-typeset code.sw::before {
  content: "";
  display: inline-block;
  box-sizing: content-box;
  width: 0.85em;
  height: 0.85em;
  vertical-align: -0.1em;
  margin-right: 0.4em;
  background: var(--c);
  border: 1px solid rgba(0, 0, 0, 0.35);
  border-radius: 2px;
}

/* Dark mode puts the swatch on a white mat, the same answer the gallery
   figures got below and for a stronger reason: the column beside it is headed
   "Contrast #ffffff". Orange at 2.25:1 on white looks emphatic against a
   near-black page, and a reader taking the square at face value reads the
   table's central number backwards. The mat is the surface the number is
   about. It is drawn outside the border rather than in place of it, so the
   hairline still separates a pale hue from the mat and the mat still separates
   the hue from the page. The mat needs no edge of its own: it is white on a
   near-black page. */
[data-md-color-scheme="slate"] .md-typeset code.sw::before {
  box-shadow: 0 0 0 2px #ffffff;
}

/* Gallery figures are wide and detailed; let them use the full column and
   carry their caption as visible text rather than only as alt. */
.md-typeset figure img {
  max-width: 100%;
  border: 1px solid var(--md-default-fg-color--lightest);
}

/* The figures are opaque white because they are drawn for paper, which on the
   dark page is seven bright slabs at 19.56:1.

   Inverting them is not available: a filter moves every Okabe-Ito hue off the
   palette the gates enforce, and the gallery would stop showing what the
   checker passed. So the white is framed rather than fought — a mat in the same
   white, so each figure ends in a margin instead of a torn edge.
   `--md-default-fg-color--lightest` is a light-on-dark tint and vanishes on
   that mat, which is why the border here names its own color. */
[data-md-color-scheme="slate"] .md-typeset figure img {
  background: #ffffff;
  padding: 0.6rem;
  border-color: rgba(0, 0, 0, 0.24);
  border-radius: 2px;
}

/* The home page's cards carry raw inline `<svg>` icons, copied from Lucide with
   a `viewBox` and no width or height. SVG's own default for both is 100%, so an
   unsized icon takes the full card width and the card's height with it: the
   rocket on the tutorial card measured 480px square. Nothing in the theme sizes
   a bare `<svg>`, because Material's icon shortcodes emit a `.twemoji` wrapper
   these hand-written icons do not have. 1.5rem is the theme's own `.lg` icon
   size, which is what a card icon is set in. */
.md-typeset .grid.cards svg {
  width: 1.5rem;
  height: 1.5rem;
  vertical-align: -0.35rem;
}

.md-typeset figure figcaption {
  max-width: 42rem;
  margin: 0.4rem auto 0;
  font-size: 0.75rem;
  line-height: 1.5;
  color: var(--md-default-fg-color--light);
}
