/* Override this file to customise the theme's CSS for your site */

/* --- Wider page, readable text column ------------------------------------
   The risotto theme caps the whole page at 64rem and centres it, which leaves
   large empty margins on wide screens. Widen the page so it fills most of the
   viewport and resizes with the window, but keep body prose at a comfortable
   reading measure. Code blocks, tables, images, and blockquotes opt back out
   so they use the extra width. Adjust the two figures below to taste. */

.page {
    max-width: min(90rem, 95vw);
}

/* Cap the reading measure of post body text (~76 monospace chars). */
.content__body > * {
    max-width: 46rem;
}

/* Let wide block elements use the full body width. */
.content__body > pre,
.content__body > .highlight,
.content__body > table,
.content__body > figure,
.content__body > blockquote,
.content__body > p:has(> img) {
    max-width: 100%;
}

/* --- Colour themes -------------------------------------------------------
   The risotto theme renders a single palette: every semantic colour in
   colours.css (--bg, --fg, --link, …) derives from a base16 ramp,
   --base00..--base0F. We redefine that ramp under selectors so the same
   markup can present four ways:

     * Auto  — follow the OS via prefers-color-scheme (no JS, no flash).
     * Light — Solarized Light, forced regardless of OS.
     * Dark  — Solarized Dark, forced regardless of OS.
     * High contrast — a WCAG-AAA pair that ALSO follows the OS light/dark.

   The early inline script in head.html sets html[data-theme] from
   localStorage before first paint; header.html drives it from a dropdown.
   "Auto" simply removes the attribute, so the media query below governs.

   Specificity note: the theme's palette link sets a bare :root (0,1,0) as the
   dark default. :root:not([data-theme]) (0,2,0) wins for OS-light auto;
   html[data-theme="…"] (0,1,1) always wins when a choice is forced. The
   high-contrast rule re-declares under a later media query so its light
   variant overrides its dark variant when the OS prefers light. */

/* Auto: follow the OS. Default (no attribute) is Solarized Dark via the
   theme's palette link; this flips it to Solarized Light when the OS asks. */
@media (prefers-color-scheme: light) {
    :root:not([data-theme]) {
        --base00: #fdf6e3;
        --base01: #eee8d5;
        --base02: #93a1a1;
        --base03: #839496;
        --base04: #657b83;
        --base05: #586e75;
        --base06: #073642;
        --base07: #002b36;
        --base08: #dc322f;
        --base09: #cb4b16;
        --base0A: #b58900;
        --base0B: #859900;
        --base0C: #2aa198;
        --base0D: #268bd2;
        --base0E: #6c71c4;
        --base0F: #d33682;
    }
}

/* Forced Solarized Light. */
html[data-theme="light"] {
    --base00: #fdf6e3;
    --base01: #eee8d5;
    --base02: #93a1a1;
    --base03: #839496;
    --base04: #657b83;
    --base05: #586e75;
    --base06: #073642;
    --base07: #002b36;
    --base08: #dc322f;
    --base09: #cb4b16;
    --base0A: #b58900;
    --base0B: #859900;
    --base0C: #2aa198;
    --base0D: #268bd2;
    --base0E: #6c71c4;
    --base0F: #d33682;
}

/* Forced Solarized Dark (e.g. user picks Dark while the OS prefers light). */
html[data-theme="dark"] {
    --base00: #002b36;
    --base01: #073642;
    --base02: #586e75;
    --base03: #657b83;
    --base04: #839496;
    --base05: #93a1a1;
    --base06: #eee8d5;
    --base07: #fdf6e3;
    --base08: #dc322f;
    --base09: #cb4b16;
    --base0A: #b58900;
    --base0B: #859900;
    --base0C: #2aa198;
    --base0D: #268bd2;
    --base0E: #6c71c4;
    --base0F: #d33682;
}

/* High contrast — dark variant (default for this mode). Solarized hues kept
   recognisable but brightened; bg/fg pushed to ~19:1. */
html[data-theme="contrast"] {
    --base00: #000000;
    --base01: #121212;
    --base02: #1e1e1e;
    --base03: #b8b8b8;
    --base04: #e6e6e6;
    --base05: #ffffff;
    --base06: #ffffff;
    --base07: #ffffff;
    --base08: #ff6b66;
    --base09: #ffae57;
    --base0A: #ffd700;
    --base0B: #5cff8f;
    --base0C: #5fe3ff;
    --base0D: #6cb6ff;
    --base0E: #d3a0ff;
    --base0F: #ff7ac6;
}

/* High contrast — light variant, used when the mode is on AND the OS prefers
   light. Black-on-white with darkened accents; bg/fg ~21:1. */
@media (prefers-color-scheme: light) {
    html[data-theme="contrast"] {
        --base00: #ffffff;
        --base01: #f0f0f0;
        --base02: #e4e4e4;
        --base03: #595959;
        --base04: #1f1f1f;
        --base05: #000000;
        --base06: #000000;
        --base07: #000000;
        --base08: #c00000;
        --base09: #9c4500;
        --base0A: #7a6000;
        --base0B: #1f7a1f;
        --base0C: #006e8a;
        --base0D: #0044cc;
        --base0E: #6a2cc4;
        --base0F: #b02080;
    }
}

/* --- Theme switcher control ---------------------------------------------- */
.theme-switch {
    margin-left: auto;
    display: flex;
    align-items: center;
    gap: 0.4rem;
}

.theme-switch::marker {
    content: "";
}

.theme-switch__label {
    color: var(--muted);
    font-size: 0.85rem;
    text-transform: lowercase;
}

.theme-switch__select {
    font-family: inherit;
    font-size: 0.85rem;
    color: var(--fg);
    background: var(--off-bg);
    border: 1px solid var(--muted);
    border-radius: 4px;
    padding: 0.15rem 0.4rem;
    cursor: pointer;
}

.theme-switch__select:hover {
    border-color: var(--link);
}

/* --- Theme-aware figure (theme-figure shortcode) ------------------------- */
/* Swap a figure's image with the palette: the "light" photo under light/contrast
   palettes, the "dark" photo under the dark palette. These mirror the exact same
   selectors as the base16 ramp above, so the image always matches the active
   theme. The bare default (no media query, no attribute) is the dark palette. */
.theme-figure img { max-width: 100%; height: auto; }
.theme-img-light { display: none; }
.theme-img-dark { display: block; }

/* Auto — OS prefers light */
@media (prefers-color-scheme: light) {
    :root:not([data-theme]) .theme-img-light { display: block; }
    :root:not([data-theme]) .theme-img-dark { display: none; }
}

/* Forced light */
html[data-theme="light"] .theme-img-light { display: block; }
html[data-theme="light"] .theme-img-dark { display: none; }

/* Forced dark (explicit, e.g. OS light but dark chosen) */
html[data-theme="dark"] .theme-img-light { display: none; }
html[data-theme="dark"] .theme-img-dark { display: block; }

/* High contrast follows the OS like Auto: dark by default (rule above),
   light photo only when the OS also prefers light. */
@media (prefers-color-scheme: light) {
    html[data-theme="contrast"] .theme-img-light { display: block; }
    html[data-theme="contrast"] .theme-img-dark { display: none; }
}

/* --- Code blocks & inline code ------------------------------------------
   The risotto theme paints pre/code with --inner-bg (base02) on --off-fg
   (base04) — two adjacent steps on the base16 ramp, ~1.7:1 contrast in every
   palette, effectively illegible. Repoint to --off-bg (base01) on --fg
   (base05), ~5:1, matching body prose. The theme sets its background with
   !important, so we must too; custom.css loads after risotto.css, so equal-
   specificity rules win on source order. */
pre,
code,
kbd,
samp {
    /* First declaration is the fallback for browsers without color-mix(); the
       second wins where supported. */
    background: var(--off-bg) !important;
    background: var(--code-bg) !important;
    color: var(--fg);
}

/* Code background (--code-bg): dark themes get a "well" a shade darker than
   the page for depth (the editor look), which also lifts text contrast to
   ~6:1. Light themes can't follow — a near-white page darkened toward a slate
   body text drops below the WCAG 4.5 floor — so they revert to the lighter
   Solarized cream inset (--off-bg/base01). Default below is the dark well;
   the light contexts override it, mirroring the palette selectors above. */
:root {
    --code-bg: color-mix(in srgb, var(--bg) 85%, #000);
}
@media (prefers-color-scheme: light) {
    :root:not([data-theme]) { --code-bg: var(--off-bg); }
    html[data-theme="contrast"] { --code-bg: var(--off-bg); }
}
html[data-theme="light"] {
    --code-bg: var(--off-bg);
}

/* Block code reads as a distinct panel, delineated by a base02 border (the
   page/code background delta alone is barely perceptible in light themes).
   Inline code is excluded, so it stays an unbordered tint. */
pre {
    border: 1px solid var(--inner-bg);
    border-radius: 4px;
}

/* --- Syntax highlighting (Chroma) ---------------------------------------
   markup.highlight.noClasses=false makes Chroma emit token classes but ships
   no stylesheet, so highlighted blocks rendered monochrome. Map every token
   to the base16 ramp (standard Solarized -> base16 hues) rather than fixed
   hex, so highlighting follows all four palettes automatically — the accent
   tokens brighten on their own under the high-contrast theme. */
.highlight .chroma {
    background: var(--off-bg) !important;
    background: var(--code-bg) !important;
    color: var(--fg);
}
.chroma code {
    background: transparent !important;
}

/* Line numbers and the highlighted-line band */
.chroma .ln,
.chroma .lnt { color: var(--muted); }
.chroma .hl { background: var(--inner-bg); }

/* Keywords */
.chroma .k,
.chroma .kn,
.chroma .kp { color: var(--base0B); }
.chroma .kd,
.chroma .kr { color: var(--base0D); }
.chroma .kc { color: var(--base09); }
.chroma .kt { color: var(--base08); }

/* Names */
.chroma .na { color: var(--fg); }
.chroma .nc,
.chroma .nd,
.chroma .nt,
.chroma .nf,
.chroma .fm,
.chroma .bp,
.chroma .nv,
.chroma .vc,
.chroma .vg,
.chroma .vi,
.chroma .vm { color: var(--base0D); }
.chroma .no,
.chroma .ni,
.chroma .ne,
.chroma .x { color: var(--base09); }
.chroma .nb { color: var(--base0A); }

/* Strings and numbers */
.chroma .s,
.chroma .sa,
.chroma .sc,
.chroma .dl,
.chroma .s2,
.chroma .si,
.chroma .sx,
.chroma .s1,
.chroma .ss,
.chroma .m,
.chroma .mb,
.chroma .mf,
.chroma .mh,
.chroma .mi,
.chroma .il,
.chroma .mo { color: var(--base0C); }
.chroma .se { color: var(--base09); }
.chroma .sr { color: var(--base08); }
.chroma .sd,
.chroma .sh { color: var(--fg); }

/* Operators */
.chroma .o,
.chroma .ow,
.chroma .or { color: var(--base0B); }

/* Comments (preproc/special keep a live hue) */
.chroma .sb,
.chroma .c,
.chroma .ch,
.chroma .cm,
.chroma .c1 { color: var(--base03); }
.chroma .cs,
.chroma .cp,
.chroma .cpf { color: var(--base0B); }

/* --- Syndication links ("Find this post on") --------------------------------
   Rendered by partials/syndication-links.html when per-platform post URLs are
   present in front-matter. Styled to sit beside the tags/series taxonomy lines
   at the bottom of a post. */

.content__syndication {
    display: flex;
    align-items: baseline;
    gap: 0.4rem;
    margin: 0;
    font-size: inherit;
    color: var(--fg);
}

.content__syndication-label {
    white-space: nowrap;
}

.content__syndication-links {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-wrap: wrap;
    gap: 0;
}

.content__syndication-links li + li::before {
    content: " · ";
    color: var(--muted);
}

/* --- Generic tokens (diffs, headings, emphasis) */
.chroma .gd { color: var(--base08); }
.chroma .gi { color: var(--base0B); }
.chroma .gh { color: var(--base09); }
.chroma .gu { color: var(--base0D); }
.chroma .gr { color: var(--base08); font-weight: bold; }
.chroma .ge { font-style: italic; }
.chroma .gs { font-weight: bold; }
