/* theme.css — dark mode overrides for calvinhamilton.co
 * Every rule is scoped under html.ch-dark so light mode (no class) is
 * byte-for-byte unchanged. Dark mode is a whole-page colour inversion,
 * which stays pixel-exact on a strictly two-colour (#000/#fff) page and
 * inverts canvases, dither patterns, and bitmap icons for free. */

/* The inversion itself, plus a background of #fff on the same rule.
 * That #fff RENDERS as black because the inversion is applied to it,
 * guaranteeing a black page during the brief window before the site's
 * own stylesheet has loaded, regardless of the browser's own default
 * background. */
html.ch-dark {
  filter: invert(1);
  background: #fff;
}

/* The boot screen is already black paper with white text in light mode.
 * A page-wide inversion would turn it white, producing a full-screen
 * white flash on every dark-mode load. Counter-inverting it here is
 * deliberate, not a bug: two inversions cancel, so the boot screen stays
 * black-on-white text in both modes. */
html.ch-dark [data-screen-label="Boot"] {
  filter: invert(1);
}

/* The site's single accent colour (#0000FF) is used only on outbound
 * mailto/"Visit" links, set inline so !important is required to beat
 * them. Because the whole page is inverted, the value declared here is
 * the PRE-inversion colour: #7F7F00 is turned by the inversion into
 * #8080FF (blue mixed halfway to white), which is legible on black where
 * pure #0000FF would not be. The selector matches links whose inline style actually contains the
 * accent colour, which is precisely the mailto link and the outbound
 * "Visit" buttons. It deliberately does NOT match `a[target="_blank"]`,
 * because the five menu-bar social links are also target="_blank" but
 * are styled plain black and must stay that way. Internal links styled
 * black inline are excluded for the same reason. Never use a bare `a`.
 * Both a hex-substring selector AND an rgb()-substring selector are
 * required: the runtime sets this colour through the CSSOM, and the
 * CSSOM always serializes colours in rgb() form, so the live inline
 * style attribute reads `color: rgb(0, 0, 255)` and never contains the
 * literal text "#0000FF" at all. Without the rgb() selector, the outbound
 * "Visit" links (which have no mailto href to fall back on) are missed
 * entirely and render pure #0000FF, which the page inversion turns
 * illegible yellow. The hex selector is kept too, belt and braces, in
 * case a style is ever set as a literal HTML attribute instead of
 * through the CSSOM. Do not simplify this down to one selector. */
html.ch-dark a[style*="#0000FF" i],
html.ch-dark a[style*="rgb(0, 0, 255)" i],
html.ch-dark a[href^="mailto:"] {
  color: #7F7F00 !important; /* declared #7F7F00; the page inversion renders it as #8080FF */
}

html.ch-dark a[style*="#0000FF" i]:hover,
html.ch-dark a[style*="rgb(0, 0, 255)" i]:hover,
html.ch-dark a[href^="mailto:"]:hover {
  color: #7F7F00 !important; /* declared #7F7F00; the page inversion renders it as #8080FF */
}

/* CSS filters do not affect cursor images, so the page-wide invert(1)
 * leaves the site's bitmap cursors light-mode-coloured even in dark
 * mode. index.html supplies pre-inverted cursor data URIs in the
 * --cur-dark / --cur-text-dark custom properties; swap them in here.
 * The fallbacks (default/text) cover the moment before those properties
 * are set. */
html.ch-dark {
  cursor: var(--cur-dark, default);
}

html.ch-dark p,
html.ch-dark li {
  cursor: var(--cur-text-dark, text);
}

/* The 20 About-window brand tiles are <li role="button">, not prose, and index.html's own
 * stylesheet already gives them the pointer cursor via `li[role="button"]{cursor:var(--cur,default)}`
 * (moved out of an inline style so this rule could ever win — inline styles beat any external
 * stylesheet selector regardless of specificity, the same trap the accent links and photo
 * borders hit). This rule's specificity (0,0,2,2: two type selectors, one class, one attribute)
 * beats the html.ch-dark li rule just above (0,0,1,2), so in dark mode a tile gets the dark
 * ARROW, not the dark I-beam. Verified in a browser. */
html.ch-dark li[role="button"] {
  cursor: var(--cur-dark, default);
}

/* Photographs keep their original tones in dark mode. The root inversion would
   render them as negatives; a second invert(1) here is exact on pure 1-bit
   content (0 and 255 simply swap back, no grey introduced), so the image shows
   as authored. Because double inversion is identity, the frame must be declared
   #fff to APPEAR white against dark mode's black paper -- a #000 frame would be
   invisible there. border-color needs !important because each photo carries an
   inline `border:1px solid #000`, and inline style specificity otherwise beats
   any external stylesheet selector regardless of how specific it is (same
   reason the accent-colour rule above needs !important on inline-styled links).
   Calvin's call, 2026-09-09, reversing the earlier decision to let the photos
   invert with the page. */
html.ch-dark img[data-photo]{filter:invert(1);border-color:#fff !important}
