
/* Pine Web Monitor — Bloom design system (Hallmark studied-DNA: Hyperlane).
   Production adaptation: default = LIGHT (:root); dark via [data-theme="dark"]
   and prefers-color-scheme. Legacy token names kept as aliases pointing to Bloom
   primaries so inline-styled JS and per-page styles keep rendering (and auto-flip). */

/* === Self-hosted web fonts (served at /static/fonts/ by web_monitor; Vietnamese
   subsets included — operator copy is Vietnamese). unicode-range keeps each page
   downloading only the subsets it renders.

   Rotonto / Aeonik / Acumin ship here with synthesised Vietnamese glyphs (see
   scripts/design/): the originals covered only ~19 of the 67 tone marks. Acumin
   is pinned to four static weights rather than its variable axis because the
   synthesised glyphs cannot carry CFF2 blend data. Geist stays in every stack
   as a safety net, but it is no longer load-bearing for Vietnamese. === */
@font-face { font-family: 'Rotonto'; font-style: normal; font-weight: 400; font-display: swap; src: url('/static/fonts/rotonto-400.woff2?v=8a6237a081') format('woff2'); }
@font-face { font-family: 'Aeonik'; font-style: normal; font-weight: 400; font-display: swap; src: url('/static/fonts/aeonik-400.woff2?v=1c2da2abde') format('woff2'); }
@font-face { font-family: 'Aeonik'; font-style: normal; font-weight: 700; font-display: swap; src: url('/static/fonts/aeonik-700.woff2?v=feaa7d6790') format('woff2'); }
@font-face { font-family: 'Aeonik'; font-style: italic; font-weight: 400; font-display: swap; src: url('/static/fonts/aeonik-400-italic.woff2?v=3ea3f5e202') format('woff2'); }
@font-face { font-family: 'Acumin Variable Concept'; font-style: normal; font-weight: 400; font-display: swap; src: url('/static/fonts/acumin-400.woff2?v=4d06ed537a') format('woff2'); }
@font-face { font-family: 'Acumin Variable Concept'; font-style: normal; font-weight: 500; font-display: swap; src: url('/static/fonts/acumin-500.woff2?v=e0362b9088') format('woff2'); }
@font-face { font-family: 'Acumin Variable Concept'; font-style: normal; font-weight: 600; font-display: swap; src: url('/static/fonts/acumin-600.woff2?v=adeca1f297') format('woff2'); }
@font-face { font-family: 'Acumin Variable Concept'; font-style: normal; font-weight: 700; font-display: swap; src: url('/static/fonts/acumin-700.woff2?v=9b4b17e74f') format('woff2'); }
@font-face { font-family: 'Geist'; font-style: normal; font-weight: 400; font-display: swap; src: url('/static/fonts/geist-400-vietnamese.woff2?v=8fa40e5d24') format('woff2'); unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; }
@font-face { font-family: 'Geist'; font-style: normal; font-weight: 400; font-display: swap; src: url('/static/fonts/geist-400-latin-ext.woff2?v=824f485b5d') format('woff2'); unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: 'Geist'; font-style: normal; font-weight: 400; font-display: swap; src: url('/static/fonts/geist-400-latin.woff2?v=19f9c92546') format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: 'Geist'; font-style: normal; font-weight: 500; font-display: swap; src: url('/static/fonts/geist-500-vietnamese.woff2?v=8fa40e5d24') format('woff2'); unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; }
@font-face { font-family: 'Geist'; font-style: normal; font-weight: 500; font-display: swap; src: url('/static/fonts/geist-500-latin-ext.woff2?v=824f485b5d') format('woff2'); unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: 'Geist'; font-style: normal; font-weight: 500; font-display: swap; src: url('/static/fonts/geist-500-latin.woff2?v=19f9c92546') format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: 'Geist'; font-style: normal; font-weight: 600; font-display: swap; src: url('/static/fonts/geist-600-vietnamese.woff2?v=8fa40e5d24') format('woff2'); unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; }
@font-face { font-family: 'Geist'; font-style: normal; font-weight: 600; font-display: swap; src: url('/static/fonts/geist-600-latin-ext.woff2?v=824f485b5d') format('woff2'); unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: 'Geist'; font-style: normal; font-weight: 600; font-display: swap; src: url('/static/fonts/geist-600-latin.woff2?v=19f9c92546') format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: 'Geist'; font-style: normal; font-weight: 700; font-display: swap; src: url('/static/fonts/geist-700-vietnamese.woff2?v=8fa40e5d24') format('woff2'); unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; }
@font-face { font-family: 'Geist'; font-style: normal; font-weight: 700; font-display: swap; src: url('/static/fonts/geist-700-latin-ext.woff2?v=824f485b5d') format('woff2'); unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: 'Geist'; font-style: normal; font-weight: 700; font-display: swap; src: url('/static/fonts/geist-700-latin.woff2?v=19f9c92546') format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: 'Fraunces'; font-style: italic; font-weight: 400; font-display: swap; src: url('/static/fonts/fraunces-400-italic-vietnamese.woff2?v=bfd7d8e0a3') format('woff2'); unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; }
@font-face { font-family: 'Fraunces'; font-style: italic; font-weight: 400; font-display: swap; src: url('/static/fonts/fraunces-400-italic-latin-ext.woff2?v=9eca373fc1') format('woff2'); unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: 'Fraunces'; font-style: italic; font-weight: 400; font-display: swap; src: url('/static/fonts/fraunces-400-italic-latin.woff2?v=f51349995e') format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: 'Fraunces'; font-style: normal; font-weight: 700; font-display: swap; src: url('/static/fonts/fraunces-700-vietnamese.woff2?v=ac8b1488dd') format('woff2'); unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; }
@font-face { font-family: 'Fraunces'; font-style: normal; font-weight: 700; font-display: swap; src: url('/static/fonts/fraunces-700-latin-ext.woff2?v=65499769eb') format('woff2'); unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: 'Fraunces'; font-style: normal; font-weight: 700; font-display: swap; src: url('/static/fonts/fraunces-700-latin.woff2?v=3f3e815263') format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: 'Plus Jakarta Sans'; font-style: normal; font-weight: 700; font-display: swap; src: url('/static/fonts/plus-jakarta-sans-700-vietnamese.woff2?v=4dda300501') format('woff2'); unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; }
@font-face { font-family: 'Plus Jakarta Sans'; font-style: normal; font-weight: 700; font-display: swap; src: url('/static/fonts/plus-jakarta-sans-700-latin-ext.woff2?v=b202ec8789') format('woff2'); unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: 'Plus Jakarta Sans'; font-style: normal; font-weight: 700; font-display: swap; src: url('/static/fonts/plus-jakarta-sans-700-latin.woff2?v=2050755bf4') format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: 'JetBrains Mono'; font-style: normal; font-weight: 400; font-display: swap; src: url('/static/fonts/jetbrains-mono-400-vietnamese.woff2?v=c89b9cc0bc') format('woff2'); unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; }
@font-face { font-family: 'JetBrains Mono'; font-style: normal; font-weight: 400; font-display: swap; src: url('/static/fonts/jetbrains-mono-400-latin-ext.woff2?v=db5ff4db83') format('woff2'); unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: 'JetBrains Mono'; font-style: normal; font-weight: 400; font-display: swap; src: url('/static/fonts/jetbrains-mono-400-latin.woff2?v=83c005d49d') format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: 'JetBrains Mono'; font-style: normal; font-weight: 500; font-display: swap; src: url('/static/fonts/jetbrains-mono-500-vietnamese.woff2?v=c89b9cc0bc') format('woff2'); unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; }
@font-face { font-family: 'JetBrains Mono'; font-style: normal; font-weight: 500; font-display: swap; src: url('/static/fonts/jetbrains-mono-500-latin-ext.woff2?v=db5ff4db83') format('woff2'); unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: 'JetBrains Mono'; font-style: normal; font-weight: 500; font-display: swap; src: url('/static/fonts/jetbrains-mono-500-latin.woff2?v=83c005d49d') format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: 'JetBrains Mono'; font-style: normal; font-weight: 600; font-display: swap; src: url('/static/fonts/jetbrains-mono-600-vietnamese.woff2?v=c89b9cc0bc') format('woff2'); unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; }
@font-face { font-family: 'JetBrains Mono'; font-style: normal; font-weight: 600; font-display: swap; src: url('/static/fonts/jetbrains-mono-600-latin-ext.woff2?v=db5ff4db83') format('woff2'); unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: 'JetBrains Mono'; font-style: normal; font-weight: 600; font-display: swap; src: url('/static/fonts/jetbrains-mono-600-latin.woff2?v=83c005d49d') format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
@font-face { font-family: 'JetBrains Mono'; font-style: normal; font-weight: 700; font-display: swap; src: url('/static/fonts/jetbrains-mono-700-vietnamese.woff2?v=c89b9cc0bc') format('woff2'); unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB; }
@font-face { font-family: 'JetBrains Mono'; font-style: normal; font-weight: 700; font-display: swap; src: url('/static/fonts/jetbrains-mono-700-latin-ext.woff2?v=db5ff4db83') format('woff2'); unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; }
@font-face { font-family: 'JetBrains Mono'; font-style: normal; font-weight: 700; font-display: swap; src: url('/static/fonts/jetbrains-mono-700-latin.woff2?v=83c005d49d') format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }
:root {
    color-scheme: light;

    /* === Bloom primaries — LIGHT === */
    --color-paper:        oklch(96.5% 0.012 80);
    --color-paper-2:      oklch(93.5% 0.014 78);
    --color-paper-3:      oklch(89.5% 0.016 76);
    --color-paper-4:      oklch(85% 0.018 74);
    --color-ink:          oklch(23% 0.020 55);
    --color-ink-2:        oklch(36% 0.020 55);
    --color-ink-3:        oklch(47% 0.020 55);
    --color-rule:         oklch(86% 0.014 75);
    --color-rule-strong:  oklch(68% 0.020 65);
    --color-accent:       oklch(56% 0.120 68);
    --color-accent-2:     oklch(56% 0.160 40);
    --color-accent-soft:  oklch(56% 0.120 68 / 0.11);
    --color-accent-ink:   oklch(98% 0.008 85);
    --color-focus:        oklch(50% 0.130 68);
    --color-ok:           oklch(46% 0.110 150);
    --color-ok-soft:      oklch(46% 0.110 150 / 0.11);
    --color-err:          oklch(50% 0.165 27);
    --color-err-soft:     oklch(50% 0.165 27 / 0.10);
    --color-warn:         oklch(56% 0.120 68);
    --color-warn-soft:    oklch(56% 0.120 68 / 0.11);
    --color-long-tint:    oklch(46% 0.110 150 / 0.06);
    --color-short-tint:   oklch(50% 0.165 27 / 0.06);
    --color-bloom-1:      oklch(70% 0.130 70);
    --color-bloom-2:      oklch(65% 0.120 35);
    --bloom-opacity:      0.10;
    --nav-bg:             oklch(97% 0.010 82 / 0.78);
    --shadow-card:        0 8px 24px -16px oklch(30% 0.03 60 / 0.35);
    --rain-rgb:           150, 110, 50;

    /* === Brand mark — flips with theme (light: dark box+paper; dark: paper box+ink) === */
    --color-brand-box:    #1b140c;
    --color-brand-icon:   #f8f2e7;
    --color-brand-accent: oklch(52% 0.130 68);
    --color-brand-sheen:  oklch(60% 0.150 68 / 0.55);

    /* === Typography === */
    --font-sans:    "Aeonik", "Geist", ui-sans-serif, system-ui, sans-serif;
    --font-display: "Rotonto", "Aeonik", "Geist", ui-sans-serif, system-ui, sans-serif;
    /* Acumin is a grotesque, not a monospace (144 distinct advance widths), so it
       carries UI chrome — labels, badges, buttons, nav — while --font-mono stays a
       real fixed-pitch face for code, logs and numeric columns. */
    --font-mono:    "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
    --font-label:   "Acumin Variable Concept", "Aeonik", "Geist", ui-sans-serif, system-ui, sans-serif;
    --font-brand:   "Rotonto", "Aeonik", "Geist", ui-sans-serif, system-ui, sans-serif;
    --font-fallback:"Geist", ui-sans-serif, system-ui, sans-serif;
    /* legacy aliases — kept so existing component classes keep resolving */
    --font-body:    var(--font-sans);
    --font-accent:  var(--font-display);
    --font-ui:      var(--font-body);

    --text-xs:      0.83rem;
    --text-sm:      0.93rem;
    --text-base:    1.08rem;
    --text-md:      1.22rem;
    --text-lg:      1.44rem;
    --text-xl:      1.875rem;
    --text-2xl:     2.5rem;
    --text-3xl:     3.44rem;
    --text-display: clamp(3.25rem, 8.1vw + 0.5rem, 6.9rem);
    /* 1.15, not the 0.95 a display face would normally take: Rotonto's stacked
       Vietnamese marks rise 0.943em on lowercase, and the line above descends
       0.21em, so anything tighter makes "Tổng"/"Điều" collide with the previous
       line. ALL-CAPS Vietnamese would need 1.4 — headings here are sentence case. */
    --leading-display: 1.15;
    --leading-tight:   1.08;
    --leading-snug:    1.3;
    --leading-body:    1.55;
    --tracking-label:  0.13em;

    /* legacy heading scale (px) — kept for not-yet-ported page styles */
    --text-caption: 10px; --leading-caption: 1.1; --tracking-caption: 0.06px;
    --text-body-lg: 14px; --leading-body-lg: 1.43; --tracking-body-lg: 0.08px;
    --text-heading-sm: 22px; --leading-heading-sm: 1.25; --tracking-heading-sm: -0.08px;
    --text-heading: 26px; --leading-heading: 1.2; --tracking-heading: -0.35px;
    --text-heading-lg: 36px; --leading-heading-lg: 1.1; --tracking-heading-lg: -0.45px;
    --font-weight-regular: 400; --font-weight-medium: 500; --font-weight-semibold: 600; --font-weight-bold: 700;

    /* === Spacing === */
    --space-2xs: 0.25rem; --space-xs: 0.5rem; --space-sm: 0.75rem; --space-md: 1rem;
    --space-lg: 1.5rem; --space-xl: 2.5rem; --space-2xl: 4rem; --space-3xl: 6rem;
    /* legacy px spacing (kept) */
    --spacing-4: 4px; --spacing-5: 5px; --spacing-6: 6px; --spacing-8: 8px; --spacing-10: 10px;
    --spacing-11: 11px; --spacing-12: 12px; --spacing-13: 13px; --spacing-15: 15px; --spacing-16: 16px;
    --spacing-18: 18px; --spacing-20: 20px; --spacing-22: 22px; --spacing-28: 28px; --spacing-43: 43px; --spacing-67: 67px;
    --page-max-width: 1300px; --max-width: 84rem; --page-gutter: clamp(1rem, 3.5vw, 2.5rem);
    --section-gap: 43px; --card-padding: 12px; --element-gap: 8px;

    /* === Motion === */
    --ease-out: cubic-bezier(0.20, 0.80, 0.20, 1.00);
    --ease-in-out: cubic-bezier(0.40, 0.00, 0.20, 1.00);
    --dur-fast: 120ms; --dur-base: 220ms; --dur-slow: 400ms;

    /* === Radii === */
    --rule-hair: 1px;
    --radius-xs: 3px; --radius-sm: 6px; --radius-md: 12px; --radius-pill: 999px;
    --radius-general: 4px; --radius-prominent: 8px; --radius-cards: 4px; --radius-buttons: 4px; --radius-lg: 8px; --radius-xl: 12px;

    /* === Shadows (legacy kept) === */
    --shadow-xl: rgba(0,0,0,0.14) 0px 28px 70px 0px, rgba(0,0,0,0.1) 0px 14px 32px 0px, oklab(0.263084 -0.00230259 0.0124794 / 0.1) 0px 0px 0px 1px;
    --shadow-xl-2: rgba(0,0,0,0.25) 0px 25px 50px -12px, rgba(0,0,0,0.15) 0px 12px 24px -8px, oklab(0.263084 -0.00230259 0.0124794 / 0.1) 0px 0px 0px 0.5px;
    --shadow-subtle: oklab(0.263084 -0.00230259 0.0124794 / 0.1) 0px 0px 0px 1px, rgba(0,0,0,0.08) 0px 2px 4px;

    /* === Legacy color aliases → Bloom primaries (auto-flip light/dark) === */
    --color-canvas-parchment: var(--color-paper);
    --color-inkwell: var(--color-ink);
    --color-muted-stone: var(--color-ink-3);
    --color-deep-shadow: var(--color-ink);
    --color-pebble-gray: var(--color-paper-3);
    --color-highlight-beige: var(--color-rule);
    --color-onyx-outline: var(--color-accent-2);
    --color-chartreuse-alert: var(--color-ok);
    --color-goldenrod-accent: var(--color-accent);
    --color-forest-green-action: var(--color-ok);
    --bg: var(--color-paper);
    --surface-1: var(--color-paper-2);
    --surface-2: var(--color-paper-3);
    --surface-3: var(--color-paper-4);
    --surface-tint: var(--color-accent-soft);
    --surface-canvas-parchment: var(--color-paper);
    --surface-pebble-gray: var(--color-paper-3);
    --surface-highlight-beige: var(--color-rule);
    --text: var(--color-ink);
    --text-muted: var(--color-ink-3);
    --border: var(--color-rule);
    --accent: var(--color-accent);
    --accent-soft: var(--color-accent-soft);
    --gold-soft: var(--color-accent-soft);
    --gold-hover: var(--color-accent-soft);
    --gold-line: var(--color-rule-strong);
    --link: var(--color-accent-2);
    --link-soft: var(--color-accent-soft);
    --action-secondary: var(--color-ok);
    --action-secondary-hover: var(--color-ok);
    --status-ok: var(--color-ok);
    --status-ok-ink: var(--color-ok);
    --status-ok-soft: var(--color-ok-soft);
    --status-ok-border: var(--color-ok);
    --status-error: var(--color-err);
    --status-error-soft: var(--color-err-soft);
    --status-error-border: var(--color-err);
    --status-warn: var(--color-warn);
    --status-warn-soft: var(--color-warn-soft);
    --info: #2b6cb0; --info-hover: #22548a; --info-soft: #ebf3fd;
    --header-bg: var(--nav-bg);
    --color-tint-long: var(--color-long-tint);
    --color-tint-short: var(--color-short-tint);
}

/* === Bloom primaries — DARK === */
[data-theme="dark"] {
    color-scheme: dark;
    --color-paper:        oklch(13% 0.018 50);
    --color-paper-2:      oklch(17% 0.020 50);
    --color-paper-3:      oklch(22% 0.022 50);
    --color-paper-4:      oklch(28% 0.020 50);
    --color-ink:          oklch(95% 0.010 80);
    --color-ink-2:        oklch(78% 0.015 70);
    --color-ink-3:        oklch(63% 0.015 60);
    --color-rule:         oklch(28% 0.018 50);
    --color-rule-strong:  oklch(42% 0.025 55);
    --color-accent:       oklch(78% 0.140 70);
    --color-accent-2:     oklch(70% 0.180 45);
    --color-accent-soft:  oklch(78% 0.140 70 / 0.12);
    --color-accent-ink:   oklch(16% 0.040 60);
    --color-focus:        oklch(84% 0.140 70);
    --color-ok:           oklch(74% 0.150 145);
    --color-ok-soft:      oklch(74% 0.150 145 / 0.13);
    --color-err:          oklch(68% 0.190 25);
    --color-err-soft:     oklch(68% 0.190 25 / 0.14);
    --color-warn:         oklch(78% 0.140 70);
    --color-warn-soft:    oklch(78% 0.140 70 / 0.12);
    --color-long-tint:    oklch(74% 0.150 145 / 0.07);
    --color-short-tint:   oklch(68% 0.190 25 / 0.07);
    --color-bloom-1:      oklch(74% 0.200 60);
    --color-bloom-2:      oklch(58% 0.190 25);
    --bloom-opacity:      0.16;
    --nav-bg:             oklch(17% 0.020 50 / 0.72);
    --shadow-card:        0 10px 30px -18px oklch(5% 0.02 50 / 0.8);
    --rain-rgb:           214, 154, 69;
    --color-brand-box:    #f8f2e7;
    --color-brand-icon:   #241b14;
    --color-brand-accent: oklch(66% 0.150 68);
    --color-brand-sheen:  oklch(66% 0.150 68 / 0.55);
    --info: #8bbcff; --info-hover: #a7ccff; --info-soft: rgba(139,188,255,0.12);
}

@media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) {
        color-scheme: dark;
        --color-paper:        oklch(13% 0.018 50);
        --color-paper-2:      oklch(17% 0.020 50);
        --color-paper-3:      oklch(22% 0.022 50);
        --color-paper-4:      oklch(28% 0.020 50);
        --color-ink:          oklch(95% 0.010 80);
        --color-ink-2:        oklch(78% 0.015 70);
        --color-ink-3:        oklch(63% 0.015 60);
        --color-rule:         oklch(28% 0.018 50);
        --color-rule-strong:  oklch(42% 0.025 55);
        --color-accent:       oklch(78% 0.140 70);
        --color-accent-2:     oklch(70% 0.180 45);
        --color-accent-soft:  oklch(78% 0.140 70 / 0.12);
        --color-accent-ink:   oklch(16% 0.040 60);
        --color-focus:        oklch(84% 0.140 70);
        --color-ok:           oklch(74% 0.150 145);
        --color-ok-soft:      oklch(74% 0.150 145 / 0.13);
        --color-err:          oklch(68% 0.190 25);
        --color-err-soft:     oklch(68% 0.190 25 / 0.14);
        --color-warn:         oklch(78% 0.140 70);
        --color-warn-soft:    oklch(78% 0.140 70 / 0.12);
        --color-long-tint:    oklch(74% 0.150 145 / 0.07);
        --color-short-tint:   oklch(68% 0.190 25 / 0.07);
        --color-bloom-1:      oklch(74% 0.200 60);
        --color-bloom-2:      oklch(58% 0.190 25);
        --bloom-opacity:      0.16;
        --nav-bg:             oklch(17% 0.020 50 / 0.72);
        --shadow-card:        0 10px 30px -18px oklch(5% 0.02 50 / 0.8);
        --rain-rgb:           214, 154, 69;
        --color-brand-box:    #f8f2e7;
        --color-brand-icon:   #241b14;
        --color-brand-accent: oklch(66% 0.150 68);
        --color-brand-sheen:  oklch(66% 0.150 68 / 0.55);
        --info: #8bbcff; --info-hover: #a7ccff; --info-soft: rgba(139,188,255,0.12);
    }
}

/* ═══════════ base ═══════════ */
* { box-sizing: border-box; margin: 0; padding: 0; }
html, body { overflow-x: clip; }
body {
    position: relative;
    background: var(--color-paper);
    color: var(--color-ink-2);
    font-family: var(--font-body);
    font-size: var(--text-base);
    line-height: var(--leading-body);
    min-height: 100vh;
    font-variant-numeric: tabular-nums slashed-zero;
    transition: background var(--dur-base) var(--ease-out), color var(--dur-base) var(--ease-out);
}
/* line-height floor: Rotonto's stacked Vietnamese marks on capitals reach
   1.166em (Ổ, Ể), which collides with the previous line's descenders at 1.2. */
h1, h2, h3, h4 { font-family: var(--font-display); font-style: normal; color: var(--color-ink); overflow-wrap: anywhere; min-width: 0; line-height: 1.35; }
h1 em, h2 em, .serif-accent { font-family: var(--font-accent); font-style: normal; font-weight: 400; color: var(--color-accent); }
a { color: inherit; }
:focus-visible { outline: 2px solid var(--color-focus); outline-offset: 2px; border-radius: var(--radius-xs); }
.tnum { font-variant-numeric: tabular-nums; }
.mono { font-family: var(--font-mono); }
.label { font-family: var(--font-label); font-size: var(--text-xs); letter-spacing: var(--tracking-label); text-transform: uppercase; color: var(--color-ink-3); }
.demo-note { font-family: var(--font-label); font-size: var(--text-xs); color: var(--color-ink-3); }
.wrap { max-width: var(--max-width); margin: 0 auto; padding: 0 var(--page-gutter); }
.skip { position: absolute; left: -9999px; top: 0; background: var(--color-accent); color: var(--color-accent-ink); padding: var(--space-xs) var(--space-md); z-index: 200; }
.skip:focus { left: var(--space-md); }

/* ═══════════ ambient blooms + grain + matrix rain ═══════════ */
.ambient { position: absolute; inset: 0; pointer-events: none; z-index: 0; overflow: clip; }
.matrix-rain-full { position: fixed; inset: 0; width: 100vw; height: 100vh; z-index: 0; pointer-events: none; opacity: 0.5; }
[data-theme="dark"] .matrix-rain-full { opacity: 0.55; }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .matrix-rain-full { opacity: 0.55; } }
.bloom { position: fixed; border-radius: 50%; filter: blur(90px); opacity: var(--bloom-opacity); pointer-events: none; z-index: 0; }
.bloom--1 { width: 55vw; height: 55vw; top: -22vw; right: -14vw; background: radial-gradient(circle, var(--color-bloom-1), transparent 65%); }
.bloom--2 { width: 42vw; height: 42vw; bottom: -18vw; left: -12vw; background: radial-gradient(circle, var(--color-bloom-2), transparent 65%); }
.grain { position: fixed; inset: 0; z-index: 0; pointer-events: none; opacity: 0.5; mix-blend-mode: overlay; background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)' opacity='0.05'/%3E%3C/svg%3E"); }
body > main, body > footer, body > header, .nav, .container { position: relative; z-index: 1; }

/* ═══════════ nav · N6 masthead (logo giữ nguyên) ═══════════ */
.nav { position: sticky; top: var(--space-sm); z-index: 100; display: flex; justify-content: center; padding: var(--space-sm) var(--page-gutter) 0; }
/* One row on desktop: the brand and clock hold their size, the link list is the
   only flexible part and scrolls if 9 sections outgrow the bar. Wrapping is
   re-enabled deliberately in the narrow breakpoint below. */
.nav__inner { display: flex; align-items: center; gap: var(--space-sm); flex-wrap: nowrap; background: var(--nav-bg); backdrop-filter: blur(18px) saturate(1.3); -webkit-backdrop-filter: blur(18px) saturate(1.3); border: var(--rule-hair) solid var(--color-rule); border-radius: var(--radius-md); padding: var(--space-xs) var(--space-md); max-width: 100%; width: 100%; max-width: var(--max-width); }
.brand { display: inline-flex; align-items: center; gap: var(--space-sm); text-decoration: none; flex-shrink: 0; }
.brand__icon { position: relative; width: 36px; height: 36px; border-radius: var(--radius-sm); background: var(--color-brand-box); color: var(--color-brand-icon); display: flex; align-items: center; justify-content: center; overflow: hidden; flex-shrink: 0; }
.brand__icon::after { content: ""; position: absolute; inset: 0; background: linear-gradient(115deg, transparent 30%, var(--color-brand-sheen) 50%, transparent 70%); animation: sheen 4s linear infinite; pointer-events: none; }
.brand__icon svg { width: 20px; height: 20px; fill: currentColor; position: relative; z-index: 1; display: block; }
@media (prefers-reduced-motion: reduce) { .brand__icon::after { animation: none; } }
.brand__text { display: flex; flex-direction: column; line-height: 1.05; gap: 3px; }
.brand__title { font-family: var(--font-brand); font-weight: 700; font-size: 19px; line-height: 1; color: var(--color-ink); letter-spacing: -0.01em; white-space: nowrap; }
.brand__caption { font-family: var(--font-label); font-size: 10.5px; line-height: 1; letter-spacing: 0.13em; text-transform: uppercase; color: var(--color-brand-accent); white-space: nowrap; }
@keyframes sheen { 0% { transform: translateX(-100%); } 60%, 100% { transform: translateX(100%); } }
.nav__links { display: flex; gap: var(--space-2xs); flex-wrap: nowrap; min-width: 0; overflow-x: auto; scrollbar-width: none; }
.nav__links::-webkit-scrollbar { display: none; }
.nav__links a { font-family: var(--font-label); font-size: var(--text-xs); letter-spacing: 0.03em; text-transform: uppercase; color: var(--color-ink-3); text-decoration: none; padding: 3px 5px; border-radius: var(--radius-sm); transition: color var(--dur-fast) var(--ease-out), background var(--dur-fast) var(--ease-out); white-space: nowrap; }
.nav__links a:hover { color: var(--color-ink); background: var(--color-paper-3); }
.nav__links a:active { transform: translateY(1px); }
.nav__links a[aria-current="page"] { color: var(--color-accent); background: var(--color-accent-soft); }
.nav__spacer { margin-left: auto; flex-shrink: 0; }
.nav__clock { display: inline-flex; align-items: center; gap: 5px; font-family: var(--font-mono); font-size: var(--text-xs); color: var(--color-ink-3); white-space: nowrap; }
/* ONE row down to 1024px, keeping BOTH the clock and the "Pine Trading Ecosystem"
   wordmark. At full size the ten sections plus brand, clock and toggle want
   ~1344px, so the row is bought back in tiers — cheapest thing first — rather
   than by wrapping the bar, hiding navigation, or dropping the wordmark:

     wordmark/icon scale down → link size → toggle word

   The clock now carries only the time (no date, no `SV` label — both removed
   outright, since `title` on the clock span still says it is server VN time), so
   it is a fixed ~85px cheaper than the old date-bearing clock at every width and
   is no longer a tier lever. Nothing in the brand lockup is dropped either — the
   wordmark (19 → 16 → 13 → 12px) and the caption (10.5 → 8 → 7.5px, tracking
   0.13 → 0.10 → 0.08em) both scale instead. The lockup identifies the product,
   so it shrinks; the only text that disappears is the toggle's word, still in
   `title`/`aria-label`.

   `.brand__text` is a flex COLUMN, so the brand block is `icon + max(title,
   caption)` — the caption is free until it is wider than the title, which is why
   the full-size 10.5px caption costs nothing over the wordmark. Budgets below
   were measured with the older date-bearing clock, so they are now conservative
   (each has ~85px more slack): 1440 1344/1344 · 1366 1254/1286 · 1280 1169/1200
   · 1200 1054/1120 · 1100 948/1023 · 1024 914/952.

   Below 1024 the deficit stops being recoverable without dropping a section, so
   the link list takes its own full-width scrollable row and the clock and brand
   keep row 1. Re-measure the whole ladder when adding a nav item — a section
   costs ~70px and 1024 breaks first. */
@media (max-width: 1439px) {
    .nav__links a { letter-spacing: 0; padding: 3px 4px; }
    .brand__caption { font-size: 8px; letter-spacing: 0.10em; }
    .brand__title { font-size: 16px; }
}
@media (max-width: 1249px) {
    .brand__title { font-size: 13px; }
    .brand__icon { width: 30px; height: 30px; }
    .brand__icon svg { width: 17px; height: 17px; }
    .nav__links a { font-size: 11px; }
}
@media (max-width: 1149px) {
    .brand__title { font-size: 12px; }
    .brand__icon { width: 28px; height: 28px; }
    .brand__icon svg { width: 16px; height: 16px; }
    .nav__links { gap: 1px; }
    .nav__links a { padding: 3px 3px; }
    .nav__clock-label { display: none; }
    .theme-toggle__label { display: none; }
    .theme-toggle { padding: 5px 9px; }
}
@media (max-width: 1099px) {
    .brand__caption { font-size: 7.5px; letter-spacing: 0.08em; }
    .nav__links a { padding: 3px 2px; }
}
@media (max-width: 1023px) {
    .nav__inner { flex-wrap: wrap; row-gap: var(--space-xs); }
    .nav__links { order: 3; width: 100%; }
}

/* theme toggle (injected by theme.js) — Bloom pill */
.theme-toggle, .mode-toggle { font-family: var(--font-label); font-size: var(--text-xs); cursor: pointer; background: var(--color-paper-3); color: var(--color-ink-2); border: var(--rule-hair) solid var(--color-rule-strong); border-radius: var(--radius-pill); padding: 5px 12px; white-space: nowrap; line-height: 1; transition: background var(--dur-fast) var(--ease-out), border-color var(--dur-fast) var(--ease-out); }
.theme-toggle:hover, .mode-toggle:hover { background: var(--color-paper-4); border-color: var(--color-accent); }
.theme-toggle:active, .mode-toggle:active { transform: translateY(1px); }

/* ═══════════ page head / hero ═══════════ */
.page-head { display: block; background: none; border: 0; box-shadow: none; padding: var(--space-xl) 0 var(--space-lg); }
.rail { display: flex; align-items: center; gap: var(--space-xs); font-family: var(--font-label); font-size: var(--text-xs); letter-spacing: 0.1em; text-transform: uppercase; color: var(--color-ink-3); flex-wrap: wrap; }
.rail__dot { width: 6px; height: 6px; border-radius: 50%; background: var(--color-accent); animation: pulse 2.4s var(--ease-in-out) infinite; }
.page-head h1 { font-size: var(--text-3xl); font-weight: 700; letter-spacing: -0.03em; line-height: var(--leading-tight); margin-top: var(--space-sm); }
.page-head .sub, .hero .sub { color: var(--color-ink-3); font-size: var(--text-base); margin-top: var(--space-sm); max-width: 100%; }
.hero { padding: var(--space-xl) 0 var(--space-lg); }
.hero h1 { font-size: var(--text-display); font-weight: 800; letter-spacing: -0.035em; line-height: var(--leading-display); margin-top: var(--space-md); }
.hero__meta { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(11rem, 100%), 1fr)); border-block: var(--rule-hair) solid var(--color-rule-strong); margin-top: var(--space-xl); }
.hero__cell { padding: var(--space-md); border-inline-start: var(--rule-hair) solid var(--color-rule); }
.hero__cell:first-child { border-inline-start: 0; }
.hero__value { display: block; font-family: var(--font-mono); font-size: var(--text-lg); color: var(--color-ink); margin-top: var(--space-2xs); }
.up { color: var(--color-ok); } .down { color: var(--color-err); }

/* ═══════════ section head ═══════════ */
.section { padding: var(--space-xl) 0; }
.section-eyebrow { font-family: var(--font-label); font-size: var(--text-xs); letter-spacing: var(--tracking-label); text-transform: uppercase; color: var(--color-ink-3); }
.section-eyebrow .num { color: var(--color-accent); }
.section-h { font-size: var(--text-xl); font-weight: 700; letter-spacing: -0.02em; margin-top: var(--space-xs); }
.section-head { margin-bottom: var(--space-lg); }
.section-head .note { color: var(--color-ink-3); font-size: var(--text-sm); margin-top: var(--space-2xs); }

/* ═══════════ os strip ═══════════ */
.os-strip { display: flex; align-items: center; gap: var(--space-md); flex-wrap: wrap; border: var(--rule-hair) solid var(--color-rule); border-radius: var(--radius-md); background: var(--color-paper-2); padding: var(--space-sm) var(--space-md); margin-top: var(--space-lg); }
.os-strip__title { display: inline-flex; align-items: center; gap: var(--space-xs); font-family: var(--font-label); font-size: var(--text-xs); font-weight: 600; letter-spacing: 0.1em; color: var(--color-ink); flex-shrink: 0; }
.os-proc { font-family: var(--font-mono); font-size: var(--text-xs); color: var(--color-ink-2); display: inline-flex; align-items: center; gap: 6px; }
.os-chip { display: inline-flex; align-items: center; gap: 6px; font-family: var(--font-label); font-size: var(--text-xs); color: var(--color-ink-2); white-space: nowrap; }
.os-chip__dot { width: 7px; height: 7px; border-radius: 50%; flex: none; }
/* flex children default to min-width:auto (content-based), which stops a flex-grow
   container from ever shrinking/wrapping below its content's intrinsic width — the
   long AI OS process list then overflows the strip instead of wrapping. */
#os-processes-container, #task-workers-container, #running-tasks-container, #recent-results-container { min-width: 0; }
.os-meta { margin-left: auto; font-family: var(--font-mono); font-size: var(--text-xs); color: var(--color-ink-3); }
.dot { display: inline-block; width: 7px; height: 7px; border-radius: 50%; background: var(--color-ok); flex-shrink: 0; }
.dot--err { background: var(--color-err); } .dot--warn { background: var(--color-warn); } .dot--idle { background: var(--color-ink-3); }

/* ═══════════ badges ═══════════ */
.badge { display: inline-block; font-family: var(--font-label); font-size: var(--text-xs); padding: 2px 9px; border-radius: var(--radius-pill); vertical-align: middle; white-space: nowrap; }
.badge--ok { background: var(--color-ok-soft); color: var(--color-ok); }
.badge--err { background: var(--color-err-soft); color: var(--color-err); }
.badge--warn { background: var(--color-warn-soft); color: var(--color-warn); }
.badge--mut { background: var(--color-paper-3); color: var(--color-ink-3); }

/* legacy badge classes (badge-status / status-badge) mapped to Bloom — used by
   portal card badges, candle template, monitor bot cards, report tables. */
.badge-status, .status-badge { display: inline-block; font-family: var(--font-label); font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; padding: 2px 8px; border-radius: var(--radius-pill); white-space: nowrap; }
.badge-ok, .status-running, .status-badge.status-running { background: var(--color-ok-soft); color: var(--color-ok); }
.badge-fail, .status-crashed, .status-badge.status-crashed { background: var(--color-err-soft); color: var(--color-err); }
.badge-neutral, .status-stopped, .status-badge.status-stopped { background: var(--color-paper-3); color: var(--color-ink-3); }
.badge-live, .status-running-dry, .status-badge.status-running-dry { background: var(--color-warn-soft); color: var(--color-warn); }

/* ═══════════ catalogue rows ═══════════ */
.mod-row { display: grid; grid-template-columns: 3.2rem minmax(0, 1.1fr) minmax(0, 1.8fr) auto; gap: var(--space-md); align-items: baseline; padding: var(--space-lg) var(--space-sm); border-bottom: var(--rule-hair) solid var(--color-rule); text-decoration: none; transition: background var(--dur-base) var(--ease-out); border-radius: var(--radius-sm); }
.mod-row:first-of-type { border-top: var(--rule-hair) solid var(--color-rule-strong); }
.mod-row:hover { background: var(--color-paper-2); }
.mod-row:active { transform: translateY(1px); }
.mod-row .idx { font-family: var(--font-label); font-size: var(--text-sm); color: var(--color-accent); }
.mod-row h3 { font-size: var(--text-lg); font-weight: 600; }
.mod-row .desc { color: var(--color-ink-3); font-size: var(--text-sm); max-width: 58ch; }
.mod-row .go { font-family: var(--font-label); font-size: var(--text-xs); letter-spacing: 0.08em; text-transform: uppercase; color: var(--color-accent); white-space: nowrap; }

/* ═══════════ tables ═══════════ */
.table-scroll { overflow-x: auto; border: var(--rule-hair) solid var(--color-rule); border-radius: var(--radius-md); background: var(--color-paper-2); box-shadow: var(--shadow-card); }
table.data { border-collapse: collapse; width: 100%; min-width: 700px; font-size: var(--text-sm); }
table.data th { font-family: var(--font-mono); font-size: var(--text-xs); font-weight: 500; letter-spacing: 0.1em; text-transform: uppercase; color: var(--color-ink-3); text-align: left; padding: var(--space-sm) var(--space-md); border-bottom: var(--rule-hair) solid var(--color-rule-strong); white-space: nowrap; }
table.data td { padding: var(--space-sm) var(--space-md); border-bottom: var(--rule-hair) solid var(--color-rule); font-variant-numeric: tabular-nums; color: var(--color-ink-2); }
table.data tbody th[scope="row"] { font-family: var(--font-body); font-size: var(--text-sm); font-weight: 600; color: var(--color-ink); text-align: left; padding: var(--space-sm) var(--space-md); border-bottom: var(--rule-hair) solid var(--color-rule); }
table.data tr:last-child td, table.data tr:last-child th[scope="row"] { border-bottom: 0; }
table.data tbody tr:hover td { background: var(--color-paper-3); }
.cell-sub { display: block; font-size: var(--text-xs); color: var(--color-ink-3); margin-top: 2px; }

/* ═══════════ cards ═══════════ */
/* flex-direction:column matters only when JS toggles this element's inline
   style.display to 'flex' (legacy financial-page show/hide pattern) — without
   it the default row direction squeezes content into a single narrow column. */
.card { border: var(--rule-hair) solid var(--color-rule); border-radius: var(--radius-md); background: var(--color-paper-2); box-shadow: var(--shadow-card); padding: var(--space-lg); min-width: 0; flex-direction: column; gap: var(--space-2xs); }
.card-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(19rem, 100%), 1fr)); gap: var(--space-md); }
.overview-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(13rem, 100%), 1fr)); gap: var(--space-sm); }
.overview-card { border: var(--rule-hair) solid var(--color-rule); border-radius: var(--radius-sm); background: var(--color-paper-2); padding: var(--space-sm) var(--space-md); }
.overview-card .value { display: block; font-family: var(--font-mono); font-size: var(--text-md); color: var(--color-ink); margin-top: var(--space-2xs); }
.overview-card .desc { display: block; font-size: var(--text-xs); color: var(--color-ink-3); margin-top: 2px; }
.bot-card { border-left: 1px solid var(--color-rule-strong); }
.bot-card--long { border-left-color: var(--color-ok); background: linear-gradient(var(--color-long-tint), var(--color-long-tint)), var(--color-paper-2); }
.bot-card--short { border-left-color: var(--color-err); background: linear-gradient(var(--color-short-tint), var(--color-short-tint)), var(--color-paper-2); }
.bot-card__head { display: flex; justify-content: space-between; align-items: baseline; gap: var(--space-sm); margin-bottom: var(--space-sm); }
.bot-card__head h3 { font-family: var(--font-label); font-size: var(--text-md); font-weight: 600; }
.bot-card__head .tf { color: var(--color-ink-3); font-size: var(--text-sm); }
.metric-row { display: flex; justify-content: space-between; gap: var(--space-sm); padding: var(--space-2xs) 0; border-bottom: var(--rule-hair) dashed var(--color-rule); font-size: var(--text-sm); }
.metric-row:last-of-type { border-bottom: 0; }
.metric-row > span:first-child { flex-shrink: 0; }
.metric-row .v { font-family: var(--font-mono); color: var(--color-ink); text-align: right; overflow-wrap: anywhere; min-width: 0; }
.card-actions { display: flex; gap: var(--space-xs); flex-wrap: wrap; margin-top: var(--space-md); }

/* setup chips */
.setup-strip { display: flex; gap: var(--space-sm); flex-wrap: wrap; }
.setup-chip { border: var(--rule-hair) solid var(--color-rule); border-radius: var(--radius-sm); padding: var(--space-xs) var(--space-sm); background: var(--color-paper-2); }
.setup-chip--pos { border-left: 1px solid var(--color-ok); }
.setup-chip--neg { border-left: 1px solid var(--color-err); }
.setup-chip .name { font-size: var(--text-sm); font-weight: 600; color: var(--color-ink); }
.setup-chip .stats { display: block; font-family: var(--font-mono); font-size: var(--text-xs); color: var(--color-ink-3); margin-top: 2px; }

/* key-level ladder */
.kl-panel { display: grid; grid-template-columns: minmax(0, 210px) minmax(0, 1fr); gap: var(--space-lg); align-items: stretch; }
.kl-ladder { border: var(--rule-hair) solid var(--color-rule); border-radius: var(--radius-md); background: var(--color-paper-2); box-shadow: var(--shadow-card); padding: var(--space-md) var(--space-sm); min-height: 320px; }
.kl-track { position: relative; height: 100%; min-height: 288px; border-left: 2px dashed var(--color-rule-strong); margin-left: 6px; }
.kl-mark { position: absolute; left: 0; transform: translateY(-50%); display: flex; align-items: center; gap: 6px; white-space: nowrap; }
.kl-mark::before { content: ''; width: 10px; height: 2px; margin-left: -2px; background: var(--color-ink-3); }
.kl-mark-label { font-family: var(--font-label); font-size: 9px; font-weight: 700; text-transform: uppercase; padding: 1px 5px; border-radius: 3px; }
.kl-mark-price { font-size: 10px; font-family: var(--font-mono); color: var(--color-ink-3); }
.kl-mark--res .kl-mark-label, .kl-resistance .kl-mark-label { background: var(--color-err-soft); color: var(--color-err); }
.kl-mark--res::before, .kl-resistance::before { background: var(--color-err); }
.kl-mark--sup .kl-mark-label, .kl-support .kl-mark-label { background: var(--color-ok-soft); color: var(--color-ok); }
.kl-mark--sup::before, .kl-support::before { background: var(--color-ok); }
.kl-mark--vwap .kl-mark-label, .kl-vwap .kl-mark-label { background: transparent; color: var(--color-accent); border: var(--rule-hair) solid var(--color-accent); }
.kl-mark--vwap::before, .kl-vwap::before { background: var(--color-accent); width: 16px; }
.kl-neutral .kl-mark-label { background: var(--color-paper-3); color: var(--color-ink-3); }
.kl-mark--warn .kl-mark-label, .kl-warn .kl-mark-label { outline: var(--rule-hair) solid var(--color-err); }
.kl-close { position: absolute; left: -6px; right: -6px; height: 2px; background: var(--color-ink); transform: translateY(-50%); box-shadow: 0 0 0 1px var(--color-paper-2); }
.kl-close::after { content: '\25C4 gia'; position: absolute; right: -2px; top: -14px; font-family: var(--font-label); font-size: 8px; font-weight: 700; color: var(--color-ink); }

/* regime bar */
.regime-bar { display: flex; align-items: center; gap: var(--space-lg); flex-wrap: wrap; padding: var(--space-md) var(--space-lg); border-radius: var(--radius-md); border: var(--rule-hair) solid var(--color-rule); border-left-width: 1px; background: var(--color-paper-2); box-shadow: var(--shadow-card); }
.regime-bar--long, .regime-bar.regime-long { border-left-color: var(--color-ok); background: linear-gradient(var(--color-long-tint), var(--color-long-tint)), var(--color-paper-2); }
.regime-bar--short, .regime-bar.regime-short { border-left-color: var(--color-err); background: linear-gradient(var(--color-short-tint), var(--color-short-tint)), var(--color-paper-2); }
.regime-bar--rotation, .regime-bar.regime-rotation { border-left-color: var(--color-accent); }
.regime-bar--neutral, .regime-bar.regime-neutral { border-left-color: var(--color-ink-3); }
.regime-verdict { display: flex; flex-direction: column; gap: 2px; flex-shrink: 0; }
.regime-verdict-label { font-family: var(--font-label); font-size: 9px; font-weight: 600; color: var(--color-ink-3); text-transform: uppercase; }
.regime-verdict-value { font-family: var(--font-display); font-size: var(--text-xl); font-weight: 700; letter-spacing: -0.02em; }
.regime-bar--long .regime-verdict-value, .regime-long .regime-verdict-value { color: var(--color-ok); }
.regime-bar--short .regime-verdict-value, .regime-short .regime-verdict-value { color: var(--color-err); }
.regime-bar--rotation .regime-verdict-value, .regime-rotation .regime-verdict-value { color: var(--color-accent); }
.regime-gauge-wrap { display: flex; flex-direction: column; gap: 6px; min-width: 200px; flex-grow: 1; max-width: 360px; }
.regime-gauge { position: relative; height: 8px; border-radius: 4px; background: linear-gradient(90deg, var(--color-err-soft), var(--color-paper-3) 50%, var(--color-ok-soft)); border: var(--rule-hair) solid var(--color-rule-strong); }
.regime-gauge-mid { position: absolute; left: 50%; top: -2px; bottom: -2px; width: 1px; background: var(--color-ink-3); }
.regime-gauge-marker { position: absolute; top: 50%; width: 12px; height: 12px; border-radius: 50%; background: var(--color-ink); border: 2px solid var(--color-paper-2); transform: translate(-50%, -50%); }
.regime-score { font-family: var(--font-mono); font-size: var(--text-xs); color: var(--color-ink-3); }
.regime-na { font-style: italic; }
.regime-factors { display: flex; gap: 6px; flex-wrap: wrap; flex-shrink: 0; }
.regime-factor { font-family: var(--font-label); font-size: var(--text-xs); font-weight: 600; padding: 2px 8px; border-radius: var(--radius-xs); background: var(--color-paper-3); color: var(--color-ink-3); }
.regime-factor--up, .regime-factor-1 { background: var(--color-ok-soft); color: var(--color-ok); }
.regime-factor--down, .regime-factor--1 { background: var(--color-err-soft); color: var(--color-err); }

/* conclusions / scenarios */
.conclusion-item { display: grid; grid-template-columns: minmax(0, 14rem) minmax(0, 1fr); gap: var(--space-sm); padding: var(--space-xs) 0; border-bottom: var(--rule-hair) dashed var(--color-rule); font-size: var(--text-sm); }
.conclusion-item:last-child { border-bottom: 0; }
.conclusion-item .k { color: var(--color-ink-3); }
.scenario { border-left: 1px solid var(--color-rule-strong); padding: var(--space-xs) var(--space-md); margin-top: var(--space-sm); font-size: var(--text-sm); }
.scenario--bull { border-left-color: var(--color-ok); }
.scenario--bear { border-left-color: var(--color-err); }
.scenario .t { font-weight: 600; color: var(--color-ink); display: block; }
.scenario .tgt { font-family: var(--font-mono); font-size: var(--text-xs); color: var(--color-ink-3); display: block; margin-top: 2px; }

/* ═══════════ viewer layout ═══════════ */
.viewer-layout { display: grid; grid-template-columns: minmax(0, 15rem) minmax(0, 1fr); gap: var(--space-lg); align-items: start; padding-bottom: var(--space-2xl); }
.sidebar { position: sticky; top: 5rem; display: flex; flex-direction: column; gap: var(--space-sm); background: none; }
.sidebar-title { font-family: var(--font-label); font-size: var(--text-xs); letter-spacing: var(--tracking-label); text-transform: uppercase; color: var(--color-ink-3); border-bottom: var(--rule-hair) solid var(--color-rule-strong); padding-bottom: var(--space-2xs); margin-top: var(--space-sm); background: none; }
.side-list, .reports-list { display: flex; flex-direction: column; max-height: calc(100vh - 11rem); overflow-y: auto; padding-right: var(--space-2xs); }
.side-item, .sidebar-item { display: flex; justify-content: space-between; gap: var(--space-sm); align-items: baseline; font-size: var(--text-sm); text-align: left; width: 100%; cursor: pointer; background: none; border: 0; border-bottom: var(--rule-hair) solid var(--color-rule); color: var(--color-ink-2); padding: var(--space-xs) var(--space-2xs); transition: background var(--dur-fast) var(--ease-out); border-radius: var(--radius-xs); font-family: var(--font-body); }
.side-item:hover, .sidebar-item:hover { background: var(--color-paper-2); }
.side-item:active, .sidebar-item:active { transform: translateY(1px); }
.side-item.active, .sidebar-item.active { background: var(--color-accent-soft); color: var(--color-ink); border-left: 1px solid var(--color-accent); box-shadow: none; }
.side-item .when { font-family: var(--font-mono); font-size: var(--text-xs); color: var(--color-ink-3); }
.toggle-group { display: flex; border: var(--rule-hair) solid var(--color-rule-strong); border-radius: var(--radius-sm); overflow: hidden; }
.toggle-btn { flex: 1; font-family: var(--font-label); font-size: var(--text-xs); background: var(--color-paper-2); border: 0; color: var(--color-ink-3); padding: var(--space-xs) var(--space-2xs); cursor: pointer; text-transform: uppercase; letter-spacing: 0.06em; transition: background var(--dur-fast) var(--ease-out); }
.toggle-btn + .toggle-btn { border-left: var(--rule-hair) solid var(--color-rule); }
.toggle-btn:hover { background: var(--color-paper-3); }
.toggle-btn.active { background: var(--color-accent); color: var(--color-accent-ink); box-shadow: none; }
.viewer-frame { border: var(--rule-hair) solid var(--color-rule); border-radius: var(--radius-md); background: var(--color-paper-2); box-shadow: var(--shadow-card); min-height: 460px; display: grid; place-content: center; text-align: center; gap: var(--space-xs); padding: var(--space-xl); }
.viewer-frame iframe { width: 100%; height: 100%; border: 0; }

/* skeleton */
.skeleton { position: relative; overflow: hidden; height: 10px; min-height: 10px; border-radius: 5px; background: linear-gradient(90deg, var(--color-paper-3) 25%, var(--color-paper-4) 50%, var(--color-paper-3) 75%); background-size: 200% 100%; animation: shimmer 1.4s linear infinite; }
.skeleton--line { width: 220px; margin: 0 auto; }
.reports-list .skeleton { min-height: 32px; margin: var(--space-2xs) 0; }

/* ═══════════ buttons (8-state) ═══════════ */
.btn, .btn-action, .btn-add, .btn-analyze, .btn-download, .btn-modal { font-family: var(--font-label); font-size: var(--text-xs); letter-spacing: 0.05em; text-transform: uppercase; padding: 8px 16px; border-radius: var(--radius-sm); cursor: pointer; border: var(--rule-hair) solid var(--color-rule-strong); background: var(--color-paper-2); color: var(--color-ink-2); transition: background var(--dur-fast) var(--ease-out), border-color var(--dur-fast) var(--ease-out); display: inline-flex; align-items: center; gap: 6px; white-space: nowrap; }
.btn:hover, .btn-action:hover { background: var(--color-paper-3); }
.btn:active, .btn-action:active { transform: translateY(1px); }
.btn:disabled, .btn-action:disabled { opacity: 0.4; cursor: not-allowed; }
.btn--primary, .btn-add, .btn-analyze, .btn-download { background: var(--color-accent); border-color: var(--color-accent); color: var(--color-accent-ink); font-weight: 600; }
.btn--primary:hover { filter: brightness(1.08); background: var(--color-accent); }
.btn--danger { color: var(--color-err); border-color: var(--color-err); background: var(--color-err-soft); }
.btn[data-state="loading"] { opacity: 0.7; pointer-events: none; }
.btn[data-state="error"] { border-color: var(--color-err); color: var(--color-err); }
.btn[data-state="success"] { border-color: var(--color-ok); color: var(--color-ok); }

/* ═══════════ forms ═══════════ */
.form-row { display: flex; gap: var(--space-md); flex-wrap: wrap; align-items: end; }
.field { display: flex; flex-direction: column; gap: var(--space-2xs); }
.field label { font-family: var(--font-label); font-size: var(--text-xs); letter-spacing: 0.08em; text-transform: uppercase; color: var(--color-ink-3); }
.field input[type="text"], .field select { font-family: var(--font-label); font-size: var(--text-sm); color: var(--color-ink); background: var(--color-paper); border: var(--rule-hair) solid var(--color-rule-strong); border-radius: var(--radius-sm); padding: 7px 10px; transition: border-color var(--dur-fast) var(--ease-out); }
.field input:hover, .field select:hover { border-color: var(--color-ink-3); }
.field input:focus-visible, .field select:focus-visible { outline: 2px solid var(--color-focus); outline-offset: 1px; }
.check { display: inline-flex; align-items: center; gap: var(--space-xs); font-size: var(--text-sm); color: var(--color-ink-2); cursor: pointer; }
.check input { width: 14px; height: 14px; accent-color: var(--color-accent); cursor: pointer; }

/* ═══════════ inline error / empty / ui-state ═══════════ */
.inline-err { display: flex; align-items: center; gap: var(--space-sm); flex-wrap: wrap; border: var(--rule-hair) solid var(--color-err); border-radius: var(--radius-md); background: var(--color-err-soft); color: var(--color-ink-2); padding: var(--space-sm) var(--space-md); font-size: var(--text-sm); margin-top: var(--space-lg); }
.empty-state, .ui-state { text-align: center; color: var(--color-ink-3); font-size: var(--text-sm); padding: var(--space-md); border: 1px dashed var(--color-rule); border-radius: var(--radius-md); background: var(--color-accent-soft); display: flex; flex-direction: column; gap: var(--space-2xs); }
.empty-state b, .ui-state strong { display: block; color: var(--color-ink); font-family: var(--font-display); }
.ui-state.error { color: var(--color-err); border-color: var(--color-err); background: var(--color-err-soft); }
.ui-state button { align-self: flex-start; margin-top: var(--space-2xs); border: var(--rule-hair) solid var(--color-err); background: transparent; color: var(--color-err); border-radius: var(--radius-sm); padding: 5px 9px; cursor: pointer; font-family: var(--font-label); font-size: 10px; font-weight: 700; text-transform: uppercase; }

/* ═══════════ modal ═══════════ */
.modal-demo { border: var(--rule-hair) solid var(--color-rule-strong); border-radius: var(--radius-md); background: var(--color-paper-2); box-shadow: var(--shadow-card); overflow: hidden; }
.modal-demo__head { display: flex; justify-content: space-between; align-items: center; padding: var(--space-sm) var(--space-md); border-bottom: var(--rule-hair) solid var(--color-rule); background: var(--color-paper-3); }
.modal-demo__head h3 { font-size: var(--text-sm); font-weight: 600; }
.log-box { font-family: var(--font-mono); font-size: var(--text-xs); line-height: 1.6; color: var(--color-ink-2); background: var(--color-paper); padding: var(--space-md); overflow-x: auto; white-space: pre; }
.modal-demo__foot { display: flex; justify-content: flex-end; gap: var(--space-xs); padding: var(--space-sm) var(--space-md); border-top: var(--rule-hair) solid var(--color-rule); }

/* ═══════════ checklist ═══════════ */
.checklist { list-style: none; padding: 0; display: flex; flex-direction: column; gap: var(--space-sm); }
.checklist li { display: flex; gap: var(--space-sm); font-size: var(--text-sm); color: var(--color-ink-2); }
.checklist .tick { color: var(--color-ok); font-family: var(--font-label); flex-shrink: 0; }
.checklist strong { color: var(--color-ink); }

/* ═══════════ markdown body ═══════════ */
.markdown-body { font-size: var(--text-sm); color: var(--color-ink-2); max-width: 100%; background: none; overflow-x: auto; }
.markdown-body img { max-width: 100%; height: auto; }
.markdown-body h1, .markdown-body h2, .markdown-body h3 { margin: var(--space-lg) 0 var(--space-xs); }
.markdown-body h3 { font-size: var(--text-md); }
.markdown-body p { margin: var(--space-sm) 0; }
/* Bảng rộng phải cuộn TRONG CHÍNH NÓ. Trước 29/07 chỉ .markdown-body có
   overflow-x, nên thanh cuộn ngang nằm ở đáy CẢ bài — journal cổ phiếu dài 35 KB
   thì người đọc phải cuộn xuống tận cùng mới thấy, còn bảng III.1 (15 cột, rộng
   1075px trong khung 998px ở 1440px, 686px ở 1024px) trông như bị cắt cụt.
   display:block + width:max-content biến mỗi bảng thành một vùng cuộn tại chỗ;
   min-width:100% giữ nguyên dáng full-width cho bảng hẹp. */
.markdown-body table { display: block; width: max-content; min-width: 100%; max-width: 100%; overflow-x: auto; border-collapse: collapse; margin: var(--space-sm) 0; }
.markdown-body th, .markdown-body td { border: var(--rule-hair) solid var(--color-rule); padding: var(--space-2xs) var(--space-xs); font-size: var(--text-xs); font-variant-numeric: tabular-nums; }
.markdown-body th { font-family: var(--font-mono); text-transform: uppercase; letter-spacing: 0.06em; color: var(--color-ink-3); }
.markdown-body code { font-family: var(--font-mono); background: var(--color-paper-3); padding: 0 4px; border-radius: 3px; }

/* ═══════════ footer ═══════════ */
.footer { border-top: var(--rule-hair) solid var(--color-rule-strong); margin-top: var(--space-2xl); padding: var(--space-xl) 0 var(--space-2xl); }
.footer__slogan { font-family: var(--font-label); font-size: var(--text-sm); letter-spacing: 0.18em; text-transform: uppercase; color: var(--color-brand-accent); }
.footer__subslogan { font-family: var(--font-label); font-size: var(--text-xs); letter-spacing: 0.04em; color: var(--color-ink-3); margin-top: var(--space-xs); max-width: 52rem; }
.footer__meta { display: flex; justify-content: space-between; gap: var(--space-md); flex-wrap: wrap; margin-top: var(--space-lg); align-items: baseline; }
.footer__links { display: flex; gap: var(--space-md); list-style: none; padding: 0; flex-wrap: wrap; }
.footer__links a { font-family: var(--font-label); font-size: var(--text-xs); text-transform: uppercase; letter-spacing: 0.08em; color: var(--color-ink-3); text-decoration: none; }
.footer__links a:hover { color: var(--color-accent); }

/* ═══════════ motion ═══════════ */
@keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.35; } }
@keyframes shimmer { to { background-position: -200% 0; } }
@keyframes rise { from { opacity: 0; transform: translateY(14px); } to { opacity: 1; transform: none; } }
.rise { animation: rise var(--dur-slow) var(--ease-out) both; }
.clock-beat { display: inline-block; width: 7px; height: 7px; background-color: var(--color-ok); border-radius: 50%; margin-right: 6px; vertical-align: middle; }
.clock-beat.is-stopped, .os-dot.is-stopped { background-color: var(--color-err) !important; animation: none !important; }

/* ═══════════ responsive ═══════════ */
@media (max-width: 900px) {
    .viewer-layout { grid-template-columns: minmax(0, 1fr); }
    .sidebar { position: static; }
    .kl-panel { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 768px) {
    .nav { position: static; }
    .nav__inner { border-radius: var(--radius-md); flex-wrap: wrap; justify-content: flex-start; gap: var(--space-xs) var(--space-sm); }
    .brand { flex: 1 1 auto; min-width: 0; }
    .brand__text { min-width: 0; }
    .brand__title, .brand__caption { overflow: hidden; text-overflow: ellipsis; }
    .nav__links { order: 3; width: 100%; flex-wrap: nowrap; overflow-x: auto; overscroll-behavior-x: contain; scrollbar-width: thin; padding-bottom: var(--space-2xs); }
    .nav__links a { min-height: 44px; display: inline-flex; align-items: center; }
    .nav__spacer { margin-left: auto; }
    .mod-row { grid-template-columns: 2.4rem minmax(0, 1fr); }
    .mod-row .desc, .mod-row .go { grid-column: 2; }
    .hero__cell { border-inline-start: 0; border-top: var(--rule-hair) solid var(--color-rule); }
    .hero__cell:first-child { border-top: 0; }
    .conclusion-item { grid-template-columns: minmax(0, 1fr); gap: var(--space-2xs); }
}
@media (hover: none) {
    .btn, .btn-action, .btn-add, .btn-analyze, .btn-download, .btn-modal,
    .sidebar-item, .toggle-btn, .theme-toggle, .mode-toggle { min-height: 44px; touch-action: manipulation; }
}
@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after { animation-duration: 0.01ms !important; animation-iteration-count: 1 !important; transition-duration: 0.01ms !important; scroll-behavior: auto !important; }
}

/* ── Hermes Chat Panel ───────────────────────────────────────────────── */
.chatp-fab {
    position: fixed; right: var(--space-md); bottom: var(--space-md); z-index: 80;
    display: inline-flex; align-items: center; gap: var(--space-2xs);
    padding: 0.6rem 0.95rem; border: var(--rule-hair) solid var(--color-rule-strong);
    border-radius: var(--radius-pill); background: var(--color-ink); color: var(--color-paper);
    font-family: var(--font-ui); font-size: var(--text-sm); font-weight: 600;
    cursor: pointer; box-shadow: var(--shadow-card);
    transition: transform var(--dur-fast) var(--ease-out), background var(--dur-fast) var(--ease-out);
}
.chatp-fab:hover { background: var(--color-ink-2); }
.chatp-fab:active { transform: translateY(1px) scale(0.99); }
.chatp-fab:focus-visible { outline: 2px solid var(--color-focus); outline-offset: 2px; }
.chatp-fab[hidden] { display: none; }
.chatp-fab__dot {
    width: 6px; height: 6px; border-radius: var(--radius-pill);
    background: var(--color-bloom-1);
}

/* Thẻ neo góc dưới phải, KHÔNG phải drawer full-height: chat là thứ hỏi kèm
   trong lúc đọc trang, nên nó không được che nội dung hay đè lên thanh điều
   hướng. Cao 40vh; hội thoại dài thì .chatp__log tự cuộn. */
.chatp {
    position: fixed; right: var(--space-md); bottom: var(--space-md); z-index: 80;
    width: min(420px, calc(100vw - var(--space-md) * 2));
    height: clamp(19rem, 40vh, 32rem);
    max-height: calc(100vh - var(--space-md) * 2);
    display: grid; grid-template-rows: auto minmax(0, 1fr) auto;
    background: var(--color-paper);
    border: var(--rule-hair) solid var(--color-rule);
    border-radius: var(--radius-md);
    overflow: hidden;
    box-shadow: 0 18px 44px -26px oklch(30% 0.03 60 / 0.55);
    transform: translateY(0.75rem) scale(0.985); opacity: 0; pointer-events: none;
    transition: transform var(--dur-base) var(--ease-out),
                opacity var(--dur-fast) var(--ease-out);
    font-family: var(--font-ui);
}
.chatp.is-open { transform: none; opacity: 1; pointer-events: auto; }
.chatp[hidden] { display: none; }

.chatp__head {
    display: flex; align-items: center; gap: var(--space-xs);
    padding: var(--space-sm) var(--space-md);
    border-bottom: var(--rule-hair) solid var(--color-rule);
    background: var(--color-paper-2);
}
.chatp__title {
    font-family: var(--font-display); font-size: var(--text-base); font-weight: 650;
    color: var(--color-ink); letter-spacing: -0.01em;
}
.chatp__ctx {
    margin-inline-start: auto;
    display: inline-flex; align-items: center; gap: 0.3rem;
    max-width: 190px; padding: 0.2rem 0.5rem;
    border: var(--rule-hair) solid var(--color-rule);
    border-radius: var(--radius-pill); background: var(--color-paper);
    font-size: var(--text-xs); color: var(--color-ink-3);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.chatp__ctx b { color: var(--color-ink-2); font-weight: 600; }
.chatp__close {
    border: 0; background: transparent; cursor: pointer;
    color: var(--color-ink-3); font-size: var(--text-md); line-height: 1;
    padding: 0.2rem 0.35rem; border-radius: var(--radius-sm);
}
.chatp__close:hover { background: var(--color-paper-3); color: var(--color-ink); }
.chatp__close:active { transform: translateY(1px); }
.chatp__close:focus-visible { outline: 2px solid var(--color-focus); outline-offset: 1px; }

.chatp__log {
    overflow-y: auto; padding: var(--space-md);
    display: flex; flex-direction: column; gap: var(--space-md);
    scroll-behavior: smooth;
}
.chatp__empty {
    margin: auto 0; text-align: center; color: var(--color-ink-3);
    font-size: var(--text-sm); line-height: 1.6;
}
.chatp__empty strong { display: block; color: var(--color-ink-2); font-size: var(--text-base); margin-bottom: 0.35rem; }
.chatp__hints { display: flex; flex-wrap: wrap; gap: var(--space-2xs); justify-content: center; margin-top: var(--space-sm); }
.chatp__hint {
    border: var(--rule-hair) solid var(--color-rule); background: var(--color-paper);
    color: var(--color-ink-2); font-family: var(--font-ui); font-size: var(--text-xs);
    padding: 0.3rem 0.6rem; border-radius: var(--radius-pill); cursor: pointer;
}
.chatp__hint:hover { border-color: var(--color-rule-strong); background: var(--color-paper-2); }
.chatp__hint:active { transform: translateY(1px); }

.chatp-msg { display: grid; gap: 0.3rem; }
.chatp-msg__who {
    font-size: var(--text-xs); text-transform: uppercase; letter-spacing: 0.07em;
    color: var(--color-ink-3);
}
.chatp-msg__body {
    font-size: var(--text-sm); line-height: 1.62; color: var(--color-ink);
    white-space: pre-wrap; word-break: break-word;
}
.chatp-msg--user .chatp-msg__body {
    background: var(--color-paper-2); border: var(--rule-hair) solid var(--color-rule);
    border-radius: var(--radius-md); padding: var(--space-xs) var(--space-sm);
}
.chatp-msg--agent .chatp-msg__body { border-inline-start: 2px solid var(--color-accent-soft); padding-inline-start: var(--space-sm); }
.chatp-msg__listen {
    display: inline-grid; place-items: center; justify-self: start;
    inline-size: 1.875rem; block-size: 1.875rem;
    border: var(--rule-hair) solid var(--color-rule-strong);
    background: var(--color-paper); color: var(--color-ink-2);
    padding: 0; border-radius: var(--radius-sm); cursor: pointer;
    touch-action: manipulation; -webkit-tap-highlight-color: transparent;
}
.chatp-msg__listen:hover { background: var(--color-paper-2); color: var(--color-ink); }
.chatp-msg__listen:active { transform: translateY(1px); }
.chatp-msg__listen:focus-visible { outline: 2px solid var(--color-focus); outline-offset: 1px; }
.chatp-msg__listen.is-playing { background: var(--color-ink); color: var(--color-paper); border-color: var(--color-ink); }
.chatp-msg__listen-icon { inline-size: 1rem; block-size: 1rem; }
.chatp-msg__caret { color: var(--color-accent); animation: chatp-blink 1s steps(2, start) infinite; }
@keyframes chatp-blink { to { visibility: hidden; } }

/* Hoạt động công cụ gộp thành MỘT dòng. Hermes phát cả running lẫn completed
   cho mỗi lệnh, và một câu hỏi thường kéo theo hàng chục lệnh — liệt kê hết thì
   phần đọc được bị đẩy khuất. Mặc định thu gọn, bấm mới mở. */
.chatp-act { display: grid; gap: 0.25rem; }
.chatp-act__line {
    display: inline-flex; align-items: center; gap: 0.35rem;
    align-self: start; padding: 0.12rem 0.5rem;
    border: var(--rule-hair) solid var(--color-rule); border-radius: var(--radius-pill);
    background: var(--color-paper-2); color: var(--color-ink-3);
    font-size: var(--text-xs); font-family: var(--font-ui); cursor: default;
}
.chatp-act__line[data-expandable="1"] { cursor: pointer; }
.chatp-act__line[data-expandable="1"]:hover { border-color: var(--color-rule-strong); color: var(--color-ink-2); }
.chatp-act__line[data-expandable="1"]:active { transform: translateY(1px); }
.chatp-act__spark {
    width: 5px; height: 5px; border-radius: var(--radius-pill);
    background: var(--color-bloom-1); flex: none;
}
.chatp-act__line.is-running .chatp-act__spark { animation: chatp-pulse 1.1s var(--ease-in-out) infinite; }
@keyframes chatp-pulse { 50% { opacity: 0.25; } }
.chatp-act__list {
    margin: 0; padding: 0 0 0 var(--space-sm); list-style: none;
    display: grid; gap: 0.1rem;
    font-family: var(--font-mono); font-size: var(--text-xs); color: var(--color-ink-3);
}
.chatp-act__list[hidden] { display: none; }
.chatp-act__list li { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

.chatp-appr {
    border: var(--rule-hair) solid var(--color-rule-strong);
    border-radius: var(--radius-md); background: var(--color-warn-soft);
    padding: var(--space-sm); display: grid; gap: var(--space-xs);
}
.chatp-appr__top { display: flex; align-items: center; gap: var(--space-2xs); }
.chatp-appr__risk {
    font-size: var(--text-xs); font-weight: 700; text-transform: uppercase; letter-spacing: 0.06em;
    color: var(--color-accent-2);
}
.chatp-appr__expiry { margin-inline-start: auto; font-size: var(--text-xs); color: var(--color-ink-3); }
.chatp-appr__preview {
    font-family: var(--font-mono); font-size: var(--text-xs); line-height: 1.5;
    color: var(--color-ink); background: var(--color-paper);
    border: var(--rule-hair) solid var(--color-rule); border-radius: var(--radius-sm);
    padding: var(--space-xs); white-space: pre-wrap; word-break: break-word;
    max-height: 9rem; overflow-y: auto;
}
.chatp-appr__acts { display: flex; gap: var(--space-2xs); }
.chatp-appr__btn {
    flex: 1; padding: 0.42rem 0.6rem; border-radius: var(--radius-buttons);
    font-family: var(--font-ui); font-size: var(--text-sm); font-weight: 600; cursor: pointer;
    border: var(--rule-hair) solid var(--color-rule-strong); background: var(--color-paper); color: var(--color-ink);
}
.chatp-appr__btn:active { transform: translateY(1px); }
.chatp-appr__btn:focus-visible { outline: 2px solid var(--color-focus); outline-offset: 1px; }
.chatp-appr__btn--ok { background: var(--color-ink); color: var(--color-paper); border-color: var(--color-ink); }
.chatp-appr__btn--ok:hover { background: var(--color-ink-2); }
.chatp-appr__btn--no:hover { background: var(--color-paper-3); }
.chatp-appr__done { font-size: var(--text-xs); color: var(--color-ink-3); }

.chatp-err {
    border: var(--rule-hair) solid var(--color-err); background: var(--color-err-soft);
    border-radius: var(--radius-sm); padding: var(--space-xs) var(--space-sm);
    font-size: var(--text-sm); color: var(--color-ink); display: grid; gap: var(--space-2xs);
}
.chatp-err__retry {
    justify-self: start; border: var(--rule-hair) solid var(--color-rule-strong);
    background: var(--color-paper); color: var(--color-ink);
    font-size: var(--text-xs); padding: 0.25rem 0.55rem; border-radius: var(--radius-buttons); cursor: pointer;
}
.chatp-err__retry:active { transform: translateY(1px); }

.chatp-skel { display: grid; gap: 0.4rem; }
.chatp-skel__bar {
    height: 0.62rem; border-radius: var(--radius-xs);
    background: linear-gradient(90deg, var(--color-paper-2) 25%, var(--color-paper-3) 37%, var(--color-paper-2) 63%);
    background-size: 300% 100%; animation: chatp-shimmer 1.25s ease-in-out infinite;
}
.chatp-skel__bar:nth-child(2) { width: 82%; }
.chatp-skel__bar:nth-child(3) { width: 58%; }
@keyframes chatp-shimmer { from { background-position: 100% 0; } to { background-position: 0 0; } }

.chatp__foot {
    border-top: var(--rule-hair) solid var(--color-rule);
    padding: var(--space-sm) var(--space-md);
    background: var(--color-paper-2); display: grid; gap: var(--space-2xs);
}
.chatp__inputrow {
    display: grid; grid-template-columns: minmax(0, 1fr) auto auto; gap: var(--space-2xs);
    align-items: end;
    border: var(--rule-hair) solid var(--color-rule); border-radius: var(--radius-md);
    background: var(--color-paper); padding: var(--space-2xs);
}
.chatp__inputrow:focus-within { border-color: var(--color-rule-strong); }
.chatp__input {
    border: 0; background: transparent; resize: none; outline: none;
    font-family: var(--font-ui); font-size: var(--text-sm); line-height: 1.5;
    color: var(--color-ink); padding: 0.35rem 0.45rem; max-height: 7rem; min-height: 2.1rem;
}
.chatp__send {
    width: 2rem; height: 2rem; border-radius: var(--radius-sm);
    border: 0; background: var(--color-ink); color: var(--color-paper);
    font-size: var(--text-base); line-height: 1; cursor: pointer;
}
.chatp__send:disabled { background: var(--color-paper-4); color: var(--color-ink-3); cursor: not-allowed; }
.chatp__send:not(:disabled):active { transform: translateY(1px); }
.chatp__send:focus-visible { outline: 2px solid var(--color-focus); outline-offset: 2px; }
.chatp__voice {
    width: 2rem; height: 2rem; border-radius: var(--radius-sm);
    border: var(--rule-hair) solid var(--color-rule); background: var(--color-paper-2);
    color: var(--color-ink-2); font-size: var(--text-sm); line-height: 1; cursor: pointer;
}
.chatp__voice:hover { border-color: var(--color-rule-strong); background: var(--color-paper-3); }
.chatp__voice:active { transform: translateY(1px); }
.chatp__voice:focus-visible { outline: 2px solid var(--color-focus); outline-offset: 2px; }
.chatp__voice:disabled { color: var(--color-ink-3); cursor: not-allowed; opacity: 0.55; }
.chatp__voice[data-state="listening"],
.chatp__voice[data-state="thinking"],
.chatp__voice[data-state="speaking"] {
    background: var(--color-warn-soft); border-color: var(--color-rule-strong); color: var(--color-accent-2);
}
.chatp__voice[data-state="listening"] .chatp__voice-dot {
    display: inline-block; animation: chatp-pulse 1.1s var(--ease-in-out) infinite;
}
.chatp__voice-status { white-space: nowrap; }
.chatp__voice-status[hidden] { display: none; }
.chatp__meta {
    display: flex; align-items: center; gap: var(--space-2xs);
    font-size: var(--text-xs); color: var(--color-ink-3);
}
.chatp__model {
    display: inline-flex; align-items: center; gap: 0.3rem;
    padding: 0.12rem 0.42rem; border-radius: var(--radius-pill);
    border: var(--rule-hair) solid var(--color-rule); background: var(--color-paper);
}
.chatp__stop {
    margin-inline-start: auto; border: var(--rule-hair) solid var(--color-rule);
    background: var(--color-paper); color: var(--color-ink-2);
    font-size: var(--text-xs); padding: 0.15rem 0.5rem; border-radius: var(--radius-pill); cursor: pointer;
}
.chatp__stop[hidden] { display: none; }
.chatp__stop:active { transform: translateY(1px); }

@media (max-width: 560px) {
    /* Màn hẹp: bám hai mép và cao hơn một chút, vì 40vh trên điện thoại chỉ đủ
       khoảng ba lượt trao đổi. */
    .chatp {
        right: var(--space-xs); left: var(--space-xs); bottom: var(--space-xs);
        width: auto; height: min(58vh, calc(100vh - var(--space-xs) * 2));
    }
}
@media (hover: none) {
    .chatp-msg__listen { inline-size: 2.75rem; block-size: 2.75rem; }
}
@media (prefers-reduced-motion: reduce) {
    .chatp { transition: none; }
    .chatp__log { scroll-behavior: auto; }
    .chatp-skel__bar, .chatp-msg__caret, .chatp__voice-dot { animation: none; }
}
