/* static/css/tokens.css — the design-token foundation layer.
 *
 * FIRST of the seven stylesheets split out of the former single
 * ``gallae.css`` (tasks/FILE_SPLIT_TASKS.md Phase 1). It holds the
 * element reset, the self-hosted ``@font-face`` declarations, and the
 * ``:root`` color-token palettes (light + both dark variants). Nearly
 * every rule in the later files reads a ``var(--…)`` token or assumes the
 * reset defined here, so this file MUST load first — the ``<link>`` order
 * in ``templates/base.html`` is the authoritative cascade order
 * (tokens → base → … → reading-tools); never load a later file ahead of it.
 *
 * Conventions that hold across all seven files:
 *
 * - Mobile-first. Base rules target a ~380px viewport; wider layouts are
 *   opt-in via ``min-width`` media queries. "No horizontal scroll at any
 *   width" is a hard rule (the original Task 5.2 acceptance criterion).
 * - Theming is token-driven: light colors live in ``:root`` and the dark
 *   palettes override them; the ``@media (prefers-color-scheme: dark)`` copy
 *   MUST stay after the light ``:root`` (equal specificity, later-wins —
 *   documented at that block).
 * - Sizes use ``rem`` so the reader's browser zoom works as expected.
 * - No CSS framework, hand-written throughout.
 */

/* ---------------------------------------------------------------------
 * Resets and root
 * ------------------------------------------------------------------ */

*,
*::before,
*::after {
    box-sizing: border-box;
}

html {
    /* 16px base × 1.0 == 1rem == 16px. Browser zoom adjusts this. */
    font-size: 100%;
    line-height: 1.5;
    /* ``text-size-adjust`` keeps iOS Safari from inflating body text
     * after a rotation; we want the CSS sizes to be authoritative. */
    -webkit-text-size-adjust: 100%;
    text-size-adjust: 100%;
}

/* ---------------------------------------------------------------------
 * Webfonts (self-hosted)
 * ------------------------------------------------------------------ */

/* The redesign's three typefaces, vendored under ``static/fonts/`` as
 * woff2 and served same-origin so the Content-Security-Policy needs no
 * font-src exception (Google Fonts CDN would be blocked). ``swap`` keeps
 * text visible while the file loads. Newsreader + JetBrains Mono are
 * variable fonts — one file each covers the whole weight range (Newsreader
 * ships a separate italic file). Only the Latin subset is vendored; the
 * Korean ``(갈래)`` in the wordmark falls back to a system serif stack
 * (``--font-korean``). The ``../fonts/`` paths are relative to this file
 * (``static/css/``). */
@font-face {
    font-family: "Aboreto";
    font-style: normal;
    font-weight: 400;
    font-display: swap;
    src: url("../fonts/aboreto-latin-400-normal.958b4cfc9272.woff2") format("woff2");
}
@font-face {
    font-family: "Newsreader";
    font-style: normal;
    font-weight: 200 800;
    font-display: swap;
    src: url("../fonts/newsreader-latin-wght-normal.175a37868200.woff2") format("woff2");
}
@font-face {
    font-family: "Newsreader";
    font-style: italic;
    font-weight: 200 800;
    font-display: swap;
    src: url("../fonts/newsreader-latin-wght-italic.94402255a099.woff2") format("woff2");
}
@font-face {
    font-family: "JetBrains Mono";
    font-style: normal;
    font-weight: 100 800;
    font-display: swap;
    src: url("../fonts/jetbrains-mono-latin-wght-normal.b058178d7f30.woff2") format("woff2");
}
/* Open Sans (variable) — the sans-serif reading face. Currently used on the
 * account-preferences pages; will become a user-selectable body font. */
@font-face {
    font-family: "Open Sans";
    font-style: normal;
    font-weight: 300 800;
    font-display: swap;
    src: url("../fonts/open-sans-latin-wght-normal.dcf31ebe1074.woff2") format("woff2");
}

/* ---------------------------------------------------------------------
 * Color tokens (theming)
 * ------------------------------------------------------------------ */

/* Every color in this stylesheet is a ``var(--token)`` reference; the
 * concrete values live here so the whole palette can be swapped per
 * theme without touching any rule. The light palette below is the
 * original hand-designed v0 scheme (each value is exactly what used to
 * be inlined); the dark palette is a warm charcoal-brown counterpart
 * that echoes the warm light theme rather than a cold blue-black.
 *
 * Theme selection is driven by ``data-theme`` on <html> (rendered
 * server-side from ``UserPreferences.theme`` — see the
 * ``theme_preference`` context processor):
 *
 *   - data-theme="light"  -> always this :root (light) palette.
 *   - data-theme="dark"   -> the dark block below, always.
 *   - data-theme="system" -> light by default, but the
 *     ``prefers-color-scheme: dark`` media query at the end of this
 *     section flips it to the dark palette when the OS asks for dark.
 *
 * ``color-scheme`` is set alongside so native form controls,
 * scrollbars, and the like render in the matching light/dark style.
 *
 * NOTE: the dark values appear twice — once under
 * ``:root[data-theme="dark"]`` and once under the
 * ``prefers-color-scheme`` media query for the System default. Keep
 * the two dark blocks in sync. */
:root {
    color-scheme: light;

    /* Typography (redesign). Aboreto for the wordmark only; Newsreader is
     * the serif body/title face; JetBrains Mono carries nav, labels, and
     * metadata. ``--font-korean`` backs the wordmark's Hangul (no Latin
     * face here ships Hangul). */
    --font-display: "Aboreto", "Newsreader", Georgia, serif;
    --font-serif: "Newsreader", Georgia, "Times New Roman", serif;
    --font-mono: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    --font-sans: "Open Sans", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
    --font-korean: "Apple SD Gothic Neo", "Noto Serif KR", "Nanum Myeongjo", serif;

    /* Brand accents (redesign). ``--brand-cool`` is the cool (blue) accent —
     * the GALLAE wordmark / title plus link-hover and focus rings.
     * ``--brand-red`` is the warm (red/terracotta) accent — the resting
     * link/accent colour (eyebrow, inbox count, nav-link hover,
     * notification-title links), mirroring ``--link``. The names now track
     * hue (cool vs warm-red) consistently across light and dark.
     * ``--card-hover-bg`` is the surface a post card raises to on hover. */
    --brand-cool: #495ee4;
    --brand-red: #b3562d;
    --card-hover-bg: #fbf8f1;

    /* Shared page frame: the nav inner wrapper and the homepage container
     * both cap + centre their content at this width so the bar's links align
     * with the hero and post cards beneath. 60rem on normal desktop; mobile
     * falls below it (full-width with padding). The feed stays a single
     * column at every width — no ultra-wide two-column layer. */
    --page-max: 60rem;

    /* Approximate height of the sticky ``.site-nav`` bar. The nav is
     * content-sized (its padding + one mono line), so this is a close estimate
     * used only as a min-gap cap — e.g. keeping the mobile comments bottom
     * sheet's top edge clear of the nav. Slight over/under is harmless. */
    --nav-height: 3.25rem;

    /* Surfaces & backgrounds — warm paper. The page (``--surface``) is a
     * saturated cream; cards sit on it transparently and lift to
     * ``--card-hover-bg`` on hover. */
    --bg: #e2d6bd;
    --bg-nav: #efe7d6;
    --surface: #e8ddc6;
    /* Raised surfaces (the compose/edit "writing sheet", dropdowns, meta panels):
     * a warm cream, hand-tuned to sit a little above --surface's warm paper while
     * staying clearly lifted off it. */
    --surface-raised: #f2ebda;
    --surface-comment: #f5f7fa;
    --surface-meta: #f4f6f9;
    /* The reading-UI comment box: a warm tan a touch darker than the page so it
     * reads as its own rail panel against the cream surface. */
    --surface-comment-box: #e0d4bc;
    --surface-muted: #f5f5f5;
    --surface-code: #f0f0f0;
    --surface-pending: #f1f8f3;

    /* Text — warm near-black on the cream. */
    --text: #2a2520;
    --text-comment: #333;
    --text-muted: #5f574a;
    --text-muted-2: #6b6356;
    --text-link-muted: #777;
    --text-subtle: #888;
    --text-faint: #aaa;
    --text-faintest: #bbb;

    /* Borders — warm hairlines tuned to the cream surfaces. */
    --border: #c9bb9e;
    --border-subtle: #d4c8ae;
    --border-faint: #ddd2ba;
    --border-nav: #d2c5a9;
    --border-disabled: #e3e8ef;
    --border-tree: #cdd2d8;
    --border-card-rv: #cdd6e4;
    --border-pending: #cfe3d4;
    /* High-contrast hairline for the subscribe picker's floating menu: pure
     * black on light, pure white on dark (kept in both dark blocks below). */
    --picker-outline: #000;
    /* Resting colour of the reading rail's action icons (edit / delete /
     * subscribe / like / cowrite): a neutral so they recede until hovered.
     * Beige-tan on light, medium gray on dark (set in both dark blocks). */
    --rail-icon-color: #b19c8f;
    /* OKLCH lightness for the author-hued rail-icon tint (see .post-metacol-icon).
     * Tuned to match --rail-icon-color's perceived brightness so tinting by hue
     * doesn't change how much the icons recede. Light theme sits brighter. */
    --rail-icon-tint-l: 0.73;
    /* NOTE: the author-hued rail-icon colour is built inline at each use site
     * (.post-metacol-icon + .likers-popover), NOT via a shared :root variable.
     * A relative colour — oklch(from var(--card-author-color) …) — inside a
     * custom property is substituted on the element that DECLARES the property,
     * so a :root definition resolves against :root's (absent) --card-author-color
     * and bakes in the neutral fallback once for every card. The chroma channel
     * reads --rail-icon-chroma (see the .post-detail / .contribution rule) so the
     * gray-author exception can zero it per card. */

    /* Accent (blue) */
    --accent: #1a4f8b;
    --accent-hover: #163f6f;
    --accent-strong: #133a64;
    --accent-tint: #eef3f9;
    --accent-tint-hover: #d8e3ef;
    --on-accent: #fff;

    /* Link (blue) */
    --link: #b3562d;

    /* Success (green) */
    --success-text: #1f5e23;
    --success-border: #2e7d32;
    --success-bg: #eaf6ec;

    /* Danger / error (red) */
    --danger: #c0392b;
    --danger-strong: #b3261e;
    /* Inbox row backgrounds (per-theme; dark overrides below). Read rows are
     * NOT tinted — they fall back to the page surface (see .notification-read).
     * Unread normal is a solid warm tint a step off the page (a bit of pop);
     * super rows get a warm rose→tan gradient. */
    --notif-unread-bg: #ddcfb1;
    --notif-super-bg: linear-gradient(155deg, #e8c2b8 0%, #ddd0bb 100%);
    --error-text: #7d2823;
    --error-bg: #fdecea;
    --error-bg-hover: #fbeae9;

    /* Warning (amber) */
    --warning-text: #8a5a00;
    --warning-accent: #d9a441;
    --warning-bg: #fffbf2;
    --highlight-search: #fef3c7;

    /* Toast — a floating layer that stays dark in both themes */
    --toast-bg: #222;
    --toast-bg-success: #1f2937;
    --toast-text: #fff;

    /* Shadows */
    --shadow-sm: rgba(0, 0, 0, 0.1);
    --shadow-md: rgba(0, 0, 0, 0.12);
    --shadow-lg: rgba(0, 0, 0, 0.18);
}

/* Warm dark palette. Contrast on body / muted / link / accent text is
 * WCAG AA against the dark surfaces. */
:root[data-theme="dark"] {
    color-scheme: dark;

    /* Brand accents (redesign) — link-blue wordmark/title (``--brand-cool``),
     * terracotta accent links (``--brand-red``), dark-blue card hover (per
     * the dark mockups). */
    --brand-cool: #99a3ff;
    --brand-red: #e17a5c;
    --card-hover-bg: #1c2738;

    --bg: #141110;
    --bg-nav: #1f1b16;
    --surface: #1a1713;
    /* Raised surfaces run a deliberately COOL blue-gray in dark mode — a departure
     * from the warm-brown page/surface — so the writing sheet (compose/edit) and
     * the other raised panels read as distinctly lifted, not just a lighter brown. */
    --surface-raised: #313342;
    --surface-comment: #26282c;
    --surface-meta: #23262c;
    /* Dark-theme comment box: a warm brown lifted off the page so the rail panel
     * reads as its own surface. */
    --surface-comment-box: #2f2824;
    --surface-muted: #2f2a23;
    --surface-code: #16130f;
    --surface-pending: #1e2b20;

    --text: #ece4d8;
    --text-comment: #ded6c8;
    --text-muted: #b3a895;
    --text-muted-2: #a89d8b;
    --text-link-muted: #9d9382;
    --text-subtle: #8f8676;
    --text-faint: #756c5e;
    --text-faintest: #6e6557;

    --border: #43392e;
    --border-subtle: #3a342b;
    --border-faint: #302b23;
    --border-nav: #332e26;
    --border-disabled: #2c2a25;
    --border-tree: #46403a;
    --border-card-rv: #4a4438;
    --border-pending: #2f4031;
    --picker-outline: #fff;
    --rail-icon-color: #8a8a8a;
    --rail-icon-tint-l: 0.63;

    --accent: #7ea9e8;
    --accent-hover: #a3c2f0;
    --accent-strong: #9bb8ea;
    --accent-tint: #2c3340;
    --accent-tint-hover: #374050;
    --on-accent: #17130e;

    --link: #99a3ff;

    --success-text: #8fd49a;
    --success-border: #3f8a45;
    --success-bg: #1c2b1e;

    --danger: #e08278;
    --danger-strong: #ec8d7f;
    --notif-unread-bg: #1b212c;
    --notif-super-bg: linear-gradient(155deg, #3d1f37 0%, #191722 100%);
    --error-text: #f0a39a;
    --error-bg: #3a201d;
    --error-bg-hover: #3e221e;

    --warning-text: #e0b25a;
    --warning-accent: #c79233;
    --warning-bg: #2b2417;
    --highlight-search: #4a3f1d;

    --toast-bg: #0f0d0a;
    --toast-bg-success: #152028;
    --toast-text: #f4f0e8;

    --shadow-sm: rgba(0, 0, 0, 0.45);
    --shadow-md: rgba(0, 0, 0, 0.5);
    --shadow-lg: rgba(0, 0, 0, 0.55);
}

/* System default: follow the OS. Mirror of the dark block above —
 * keep the two in sync. */
@media (prefers-color-scheme: dark) {
    :root[data-theme="system"] {
        color-scheme: dark;

        --brand-cool: #99a3ff;
        --brand-red: #e17a5c;
        --card-hover-bg: #1c2738;

        --bg: #141110;
        --bg-nav: #1f1b16;
        --surface: #1a1713;
        /* Cool blue-gray raised surface — mirrors the :root[data-theme="dark"]
         * block above (see its note); this is the prefers-color-scheme fallback. */
        --surface-raised: #313342;
        --surface-comment: #26282c;
        --surface-meta: #23262c;
        --surface-comment-box: #2f2824;
        --surface-muted: #2f2a23;
        --surface-code: #16130f;
        --surface-pending: #1e2b20;

        --text: #ece4d8;
        --text-comment: #ded6c8;
        --text-muted: #b3a895;
        --text-muted-2: #a89d8b;
        --text-link-muted: #9d9382;
        --text-subtle: #8f8676;
        --text-faint: #756c5e;
        --text-faintest: #6e6557;

        --border: #43392e;
        --border-subtle: #3a342b;
        --border-faint: #302b23;
        --border-nav: #332e26;
        --border-disabled: #2c2a25;
        --border-tree: #46403a;
        --border-card-rv: #4a4438;
        --border-pending: #2f4031;
        --picker-outline: #fff;
        --rail-icon-color: #8a8a8a;
        --rail-icon-tint-l: 0.63;

        --accent: #7ea9e8;
        --accent-hover: #a3c2f0;
        --accent-strong: #9bb8ea;
        --accent-tint: #2c3340;
        --accent-tint-hover: #374050;
        --on-accent: #17130e;

        --link: #99a3ff;

        --success-text: #8fd49a;
        --success-border: #3f8a45;
        --success-bg: #1c2b1e;

        --danger: #e08278;
        --danger-strong: #ec8d7f;
        --notif-unread-bg: #1b212c;
        --notif-super-bg: linear-gradient(155deg, #3d1f37 0%, #191722 100%);
        --error-text: #f0a39a;
        --error-bg: #3a201d;
        --error-bg-hover: #3e221e;

        --warning-text: #e0b25a;
        --warning-accent: #c79233;
        --warning-bg: #2b2417;
        --highlight-search: #4a3f1d;

        --toast-bg: #0f0d0a;
        --toast-bg-success: #152028;
        --toast-text: #f4f0e8;

        --shadow-sm: rgba(0, 0, 0, 0.45);
        --shadow-md: rgba(0, 0, 0, 0.5);
        --shadow-lg: rgba(0, 0, 0, 0.55);
    }
}

body {
    margin: 0;
    /* Newsreader serif sets the reading tone site-wide (redesign); nav,
     * labels, and metadata opt into ``--font-mono`` locally. */
    font-family: var(--font-serif);
    color: var(--text);
    /* Match the page background to a post card's beige (``--surface``)
     * rather than the slightly darker ``--bg``, so cards and page read as
     * one continuous surface; the selected card is set apart by its
     * author-colour side border, not a background contrast. */
    background: var(--surface);
}
