/* public/css/00-base.css — Tokens, page shell, header, About cards
 *
 * Part of the old public/oracle.css, which reached 4,761 lines. Split at its own section
 * boundaries; no rule was reordered, reindented or rewritten, so the cascade is unchanged.
 * THE FILES ARE ORDER-DEPENDENT. index.html links them in numeric order and that order is the
 * cascade — concatenating them in it reproduces the original file byte for byte, which is
 * asserted in test/stylesheet.test.js. Renumbering or reordering the <link> tags changes which
 * rules win.
 *
 * The custom properties every other file reads. This one MUST load first: :root lives here, and
 * a var() that resolves before its definition falls back to nothing.
 */
/* ======================
           THE ORACLE
           ====================== */

        :root {
            --bg-deep: #06060c;
            --bg-card: #0c0d14;
            --bg-card-alt: #08090f;
            --border: #1a1f2e;
            --text-primary: #e8eaed;
            --text-secondary: #a0aab8;
            /* ── Lifted from #6d7a8e ──
               Dan: "some of the small faded text certainly is difficult to see." He is right,
               and the arithmetic agrees: the old value was 4.6:1 on this background, which is a
               pass on paper and only on paper — most places using it also carried an opacity
               below 0.5 and a font size under 10px, and 4.6 × 0.45 is not a colour anybody can
               read. This is 6.1:1, still clearly a rung below --text-secondary (8.7:1) and two
               below --text-primary (14.6:1), so the three-step hierarchy is intact.
               The sizes and opacities were raised in the same pass — see the floors below. */
            --text-dim: #828e9f;
            --accent-cyan: #5eead4;
            --accent-amber: #f4a261;
            --accent-purple: #a78bfa;
            /* ABOUT YOU. Was amber, which is a warning colour by every convention going — so
               the one thing on the page that is a gift ("this is yours") read as an alert, and
               it was loud enough that amber couldn't be spent on anything else. This is the
               a clear blue — far enough from the informational cyan beside it to never be
               confused with it, but still cool and complementary rather than an alert. The
               first attempt sat too close to cyan and the two blurred together. Amber is now
               free for genuine emphasis elsewhere. */
            --accent-yours: #25b4f3;
            --accent-red: #f87171;
            --accent-green: #34d399;
            --glow-cyan: rgba(94, 234, 212, 0.15);
            --glow-amber: rgba(244, 162, 97, 0.12);
            --mono: 'JetBrains Mono', 'SF Mono', 'Fira Code', 'Cascadia Code', monospace;
            /* ══ The reading face ═══════════════════════════════════════════════════════════
               Dan: "I'm wondering if this UI, the console font etc is making it difficult to
               read."

               Mono is the site's identity and it is genuinely the right face for most of what
               is on it: every label, every clock time, every score, every bar axis is a value
               being scanned, and tabular figures that do not jitter between repaints are worth
               a lot on a page that repaints itself. What mono is bad at is SENTENCES. Reading
               speed drops in monospace because the even advance width removes the word-shape
               cue the eye uses to skip ahead — which is precisely the four places on this site
               where somebody is reading rather than scanning: the daily reading, the Oracle's
               line about tonight, the About modal's paragraphs, and the headline's sentence.

               So the split is by JOB, not by taste. Values stay mono. Prose gets this.

               ── And it was tried, and it is off ──
               Dan, looking at it: "the half and half font style looks a bit broken and loses
               style/unique feeling." That is the answer, and it is the answer to the version of
               the argument above that was wrong: readability was treated as the only thing at
               stake, when the console face is doing a second job the reasoning never priced —
               it is the reason the page looks like a machine talking, which is the entire point
               of a site whose claim is that everything on it was computed. A site that reads
               more easily and looks like a blog has lost more than it gained.

               So this is `var(--mono)` and the whole site is monospace, exactly as it was. The
               four rules at the foot of 60-mobile.css still fire — they carry the size and
               leading changes, which helped independently of the family and are keeping — and
               they now set mono to mono, which is deliberate. Putting a real stack back here is
               the whole of the experiment if it is ever worth re-running.

               The readability problem it was aimed at is fixed at source instead: --text-dim
               went from 4.6:1 to 6.1:1, and floors of 0.62rem and 0.62 opacity were applied
               across the cascade. That was always the half Dan called certain. */
            --sans: var(--mono);
        }

        * { margin: 0; padding: 0; box-sizing: border-box; }
        html {
            font-size: 17px;
        }
        body {
            background: var(--bg-deep);
            color: var(--text-primary);
            font-family: var(--mono);
            min-height: 100vh;
            padding: 1rem;
            font-size: 16px;
            line-height: 1.65;
            position: relative;
            text-wrap: pretty;
        }

        body.modal-open {
            overflow: hidden;
        }

        ::-webkit-scrollbar { width: 4px; }
        ::-webkit-scrollbar-track { background: var(--bg-deep); }
        ::-webkit-scrollbar-thumb { background: var(--border); border-radius: 2px; }

        .container { max-width: 560px; margin: 0 auto; }

        /* (.top-actions was here: the two actions as a centred band of their own between the
           header and the Today card. They live in the header now — .header-actions, below.) */

        .top-action-btn {
            display: inline-flex;
            align-items: center;
            justify-content: center;
            text-decoration: none;
            border: 1px solid rgba(167,139,250,0.3);
            background: rgba(12,13,20,0.9);
            color: var(--text-primary);
            font-family: var(--mono);
            letter-spacing: 0.08em;
            text-transform: uppercase;
            font-size: 0.68rem;
            padding: 0.7rem 1.05rem;
            border-radius: 8px;
            cursor: pointer;
            transition: all 0.22s ease;
        }

        .top-action-btn:hover {
            transform: translateY(-1px);
            box-shadow: 0 8px 20px rgba(167,139,250,0.12);
        }
        @keyframes oracleBorderShift {
            0%, 100% { background-position: 0% 50%; }
            50% { background-position: 100% 50%; }
        }
        @keyframes oracleGlowPulse {
            0%, 100% { opacity: 0.5; }
            50% { opacity: 1; }
        }

        /* (.top-action-btn-secondary is gone — it was the treatment BOTH buttons wore, which
           meant there was no primary and no secondary, just two boxes.) */

        /* The build notes, as a link rather than a button. It is worth reaching once and never
           worth the same weight as the thing the site is for — and a bordered box next to
           another bordered box reads as a decision the reader has to make before they can get
           on with anything. */
        .top-action-link {
            border: 0;
            background: none;
            padding: 0.35rem 0.2rem;
            color: var(--text-dim);
            font-family: var(--mono);
            font-size: 0.62rem;
            letter-spacing: 0.1em;
            cursor: pointer;
            border-bottom: 1px dotted rgba(148,163,184,0.35);
            transition: color 0.2s ease, border-color 0.2s ease;
        }
        .top-action-link:hover {
            color: var(--text-secondary);
            border-bottom-color: rgba(148,163,184,0.6);
        }

        /* --- Header ---
           The name and the device's last wake on the left, the two actions on the right, one
           rule under all of it. Flex rather than a grid so the right column is exactly as wide
           as its button, and the name keeps whatever is left. */
        .header {
            display: flex;
            align-items: center;
            justify-content: space-between;
            gap: 1rem;
            text-align: left;
            padding: 1.5rem 0 1.2rem;
            border-bottom: 1px solid var(--border);
            margin-bottom: 1.2rem;
        }
        .header-main { min-width: 0; }
        /* Button above, link under it, both to the right edge — stacked rather than side by side
           so the pair fits beside the name at phone width (a row of both needs ~280px, and at
           390px the name needs ~170px of what is left). */
        .header-actions {
            display: flex;
            flex-direction: column;
            align-items: flex-end;
            gap: 0.3rem;
            flex-shrink: 0;
        }
        .header-actions .top-action-btn { padding: 0.55rem 0.9rem; }
        .header h1 {
            font-size: 1.15rem;
            font-weight: 600;
            color: var(--accent-cyan);
            letter-spacing: 0.08em;
            text-shadow: 0 0 20px var(--glow-cyan);
        }
        .header .subtitle {
            font-size: 0.77rem;
            color: var(--text-secondary);
            margin-top: 0.3rem;
            letter-spacing: 0.15em;
            text-transform: uppercase;
        }
        /* The version was an inline style attribute on a bare span. As a chip it reads as a
           label rather than as smaller text that lost its formatting. */
        /* ── "device last woke 6h ago" ──
              The device is the conduit: nothing on this page is newer than its last boot. Saying
              that in the header is what makes the rest of the page trustworthy rather than
              ambiguous — and it's why there's no refresh button and no live-looking polling. */
        .header-awakening {
            display: flex;
            align-items: center;
            gap: 0.4rem;
            margin-top: 0.45rem;
            font-size: 0.62rem;
            letter-spacing: 0.08em;
            text-transform: uppercase;
            color: var(--text-dim);
        }
        .header-awakening:empty { display: none; }
        .header-awakening-dot {
            width: 6px;
            height: 6px;
            border-radius: 50%;
            flex-shrink: 0;
            background: var(--accent-green);
            box-shadow: 0 0 6px rgba(52,211,153,0.6);
        }
        /* No boot in a day and a half — the device is flat, or away. Not an error, but not
           "everything's fine" either, so it goes amber rather than green. */
        .header-awakening-dot.stale {
            background: var(--accent-amber);
            box-shadow: 0 0 6px rgba(244,162,97,0.55);
        }

        /* --- Shared card base --- */
        .card, .insight-card {
            background: var(--bg-card);
            border: 1px solid var(--border);
            border-radius: 2px;
            padding: 1.2rem;
            margin-bottom: 0.8rem;
            position: relative;
            animation: fadeIn 0.4s ease both;
        }
        /* About cards: grimoire flow — no border, no background */
        .about-card {
            background: transparent;
            border: none;
            border-radius: 0;
            padding: 0.8rem 0.2rem;
            margin-bottom: 0;
            position: relative;
            animation: fadeIn 0.4s ease both;
        }

        /* Card top-edge glow */
        .card::before, .insight-card::before {
            content: '';
            position: absolute;
            top: 0; left: 0; right: 0;
            height: 1px;
            /* A 1px hairline, not text — the readability floor does not apply to it and a
               sweep raised it once by mistake. */
            opacity: 0.15;
        }
        .card::before { background: linear-gradient(90deg, transparent, var(--accent-cyan), transparent); }

        /* Shared card heading */
        .card h2, .insight-card h2 {
            font-size: 0.85rem;
            font-weight: 600;
            letter-spacing: 0.18em;
            text-transform: uppercase;
            margin-bottom: 0.8rem;
        }
        .card h2 { color: var(--accent-cyan); }
        .card h2::before, .insight-card h2::before { content: '// '; color: var(--text-dim); }

        /* Spellbook headings — arcane grimoire style */
        /* Grimoire headings — kept centred and ceremonial (this modal is deliberately a
           different register from the dashboard), but dialled back from 1.1rem/700/0.2em,
           which shouted over the prose it was introducing. */
        .about-card h2 {
            font-size: 0.95rem;
            font-weight: 600;
            letter-spacing: 0.16em;
            text-transform: uppercase;
            color: var(--accent-purple);
            text-align: center;
            margin-bottom: 0.9rem;
        }
        .about-card h2::before { content: none; }
        .about-card h2::after {
            content: '⸻ ✦ ⸻';
            display: block;
            font-size: 0.62rem;
            color: var(--text-dim);
            letter-spacing: 0.35em;
            margin-top: 0.4rem;
            opacity: 0.62;
            font-weight: 300;
        }

        .card:nth-child(2) { animation-delay: 0.05s; }
        .card:nth-child(3) { animation-delay: 0.1s; }
        .card:nth-child(4) { animation-delay: 0.15s; }
        .card:nth-child(5) { animation-delay: 0.2s; }
        .confidence { font-size: 0.75rem; color: var(--text-secondary); margin-top: 0.25rem; }
        .palette-name { font-size: 0.8rem; color: var(--text-secondary); font-style: italic; text-align: center; margin-top: 0.5rem; }

        /* --- About cards --- */
        .about-card p { font-size: 0.8rem; color: var(--text-secondary); line-height: 1.7; margin-bottom: 0.6rem; }
        .about-card p:last-child { margin-bottom: 0; }
        .modes-list { font-size: 0.78rem; color: var(--text-secondary); line-height: 2; margin-top: 0.5rem; }
        .modes-list b { font-weight: 500; }

        /* --- Details / expandable ---
           SCOPED TO .about-card ON PURPOSE. This used to be a bare `details summary` rule, which
           reached every fold on the site: the sunset telling and the space-weather block were
           each rendering a stray cyan "[+]" next to their own ▸ chevron, and inheriting an
           uppercase transform that shouted "TONIGHT 20:41" at you. The grimoire disclosure
           belongs to the About modal; every other fold styles its own summary. */
        .about-card details { margin-top: 0.8rem; }
        .about-card summary {
            display: flex;
            align-items: center;
            gap: 0.45rem;
            font-size: 0.7rem;
            color: var(--text-secondary);
            cursor: pointer;
            letter-spacing: 0.12em;
            text-transform: uppercase;
            transition: color 0.2s;
            list-style: none;
        }
        .about-card summary::-webkit-details-marker { display: none; }
        .about-card summary::marker { content: ''; }
        /* The same rotating chevron the rest of the site uses, rather than [+] / [-]. */
        .about-card summary::before {
            content: '▸';
            color: var(--accent-cyan);
            opacity: 0.62;
            font-size: 0.75rem;
            transition: transform 0.15s ease;
        }
        .about-card details[open] summary::before { transform: rotate(90deg); }
        .about-card summary:hover { color: var(--accent-cyan); }
        .about-card details[open] summary { margin-bottom: 0.6rem; }

        /* The deep-dive text behind each fold — set as an aside, with a rule down its side, so
           opening one reads as stepping into a footnote rather than as more body copy. */
        .scoring-note {
            font-size: 0.78rem;
            color: var(--text-dim);
            line-height: 1.7;
            padding: 0.7rem 0.85rem;
            border-left: 2px solid rgba(94,234,212,0.3);
            border-radius: 0 10px 10px 0;
            background: rgba(94,234,212,0.03);
            text-wrap: pretty;
        }
        .scoring-note code {
            display: inline-block; background: rgba(94,234,212,0.06);
            padding: 0.25rem 0.5rem; border-radius: 6px; margin: 0.3rem 0;
            border: 1px solid var(--border); color: var(--accent-cyan); font-size: 0.75rem;
        }

        /* --- Footer --- */
        .footer { text-align: center; padding: 1.5rem 0; font-size: 0.7rem; color: var(--text-secondary); line-height: 1.6; }
        .footer a { color: var(--text-dim); text-decoration: none; border-bottom: 1px solid var(--border); transition: color 0.2s; }
        .footer a:hover { color: var(--accent-cyan); }
        .updated { font-size: 0.75rem; color: var(--text-secondary); text-align: center; margin-top: 0.5rem; }

        /* --- Loading / Error --- */
        .loading { text-align: center; padding: 3rem 0; color: var(--text-dim); font-size: 0.8rem; }
        .loading .spinner {
            display: inline-block; width: 20px; height: 20px;
            border: 1px solid var(--border); border-top-color: var(--accent-cyan);
            border-radius: 50%; animation: spin 0.8s linear infinite;
        }
        .error-msg { text-align: center; color: var(--accent-red); font-size: 0.8rem; padding: 2rem 0; opacity: 0.7; }

        /* --- TTS listen button --- */
        .tts-play-btn {
            display: inline-flex; align-items: center; gap: 0.35rem;
            padding: 0.3rem 0.7rem; background: rgba(94,234,212,0.06);
            border: 1px solid var(--accent-cyan); border-radius: 3px;
            color: var(--accent-cyan); font-family: var(--mono);
            font-size: 0.65rem; letter-spacing: 0.06em; text-transform: uppercase;
            cursor: pointer; transition: all 0.2s ease;
            box-shadow: 0 0 8px var(--glow-cyan);
            animation: ttsPulse 2.5s ease-in-out infinite;
        }
        .tts-play-btn:hover { background: rgba(94,234,212,0.12); box-shadow: 0 0 14px rgba(94,234,212,0.3); }
        .tts-play-btn.playing { background: rgba(94,234,212,0.12); box-shadow: 0 0 14px rgba(94,234,212,0.3); animation: none; }
        .tts-play-btn .tts-icon { font-size: 0.75rem; line-height: 1; }

        /* --- Animations --- */
        @keyframes spin { to { transform: rotate(360deg); } }
        @keyframes fadeIn { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: translateY(0); } }
        @keyframes ttsPulse { 0%, 100% { box-shadow: 0 0 8px var(--glow-cyan); } 50% { box-shadow: 0 0 14px rgba(94,234,212,0.35); } }

