/* public/css/50-reading.css — The readings
 *
 * 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.
 *
 * Colour roles in the planets grid, the telemetry view, the daily reading card and its poem
 * setting, the signal panel, the month strip, and the Ask reading.
 */
        /* ══ Colour roles in the planets grid ══
              Amber used to mean four unrelated things at once — the row you tapped, your sign,
              a retrograde planet, and an upcoming station — while "in your sign" was ALSO
              signalled by a purple row tint. So the one colour that was supposed to mean
              "this concerns you" appeared on nearly every row for reasons that had nothing to
              do with you, and the eye had no way to sort them.

              Four roles, four treatments, no overlap:

                SELECTION (the row you opened) → neutral lift + a purple edge. It's chrome,
                  not content, so it doesn't get to spend a meaning colour.
                MOTION NOW (retrograde, stationary) → purple, solid. What the sky is doing.
                CHANGE COMING (station soon, ingress soon) → cyan, dashed. Same family as
                  motion but not yet — dashed IS the "not yet", so the two never compete.
                ABOUT YOU (your sign, a planet arriving in it) → amber, and nothing else on
                  this page is amber. It now appears once or twice on the whole grid, which
                  is the entire reason it works.

              Amber stayed the personal colour rather than moving to cyan because cyan is now
              the page's *information* colour — it's on the meaning keyword in every single
              row, the lore label, the sun times. A personal flag in cyan would be one of nine;
              in amber it is the only one. */
        .cd-planet-item[open] > .cd-planet-row {
            background: rgba(255,255,255,0.045);
            border-left-color: rgba(167,139,250,0.8);
        }
        /* Two lines: the planet, then its one-word meaning indented beneath. The keyword used to be
           a third COLUMN, which put "feelings" immediately after "Sagittarius" and left it
           genuinely unclear whose word it was. Under the name it can only belong to the name. */
        .cd-planet-name {
            display: flex;
            flex-direction: row;
            gap: 0.05rem;
            /* White, not purple. The grid was carrying purple names, an amber keyword, a
               coloured sign and coloured badges all at once — the names are the plainest fact
               in the row and were the easiest thing to hand back to the text colour, which
               lets the keyword and the your-sign highlight actually stand out. */
            color: var(--text-primary);
            font-size: 0.78rem;
            white-space: nowrap;
            width: 34%;
        }
        .cd-planet-name-line { display: flex; align-items: center; gap: 0.4rem; }
        /* Pixel disc — 14×14 buffer scaled up blocky. Fixed square so every row's disc is the
           same size and the names start on one vertical line. */
        .cd-planet-px {
            width: 20px;
            height: 20px;
            image-rendering: pixelated;
            image-rendering: crisp-edges;
            flex: 0 0 auto;
        }
        /* The exact position now, not "in Sign" — give it room and tabular figures so the
           degrees line up down the list. Flexes to fill the middle; the name column stays fixed
           so every position string still starts on one vertical line. */
        .cd-planet-sign {
            color: var(--text-secondary);
            font-size: 0.7rem;
            white-space: nowrap;
            flex: 1 1 auto;
            font-variant-numeric: tabular-nums;
        }
        /* Four columns plus up to three badges is a lot for a phone. The sign glyph is the
           first thing to go: it's decoration sitting next to the word it stands for, so
           dropping it costs nothing and buys the badges room to breathe. */
        /* MOTION NOW, not ABOUT YOU — retrograde is a fact about the sky, and dressing it in
           the personal colour is most of why the grid felt like it was shouting. */
        .cd-planet-flags {
            display: flex;
            align-items: center;
            gap: 0.35rem;
            justify-content: flex-end;
            flex-wrap: wrap;
            margin-left: auto;
        }
        .cd-planet-badge {
            font-size: 0.62rem;
            letter-spacing: 0.05em;
            /* text-transform: uppercase; */
            padding: 0.1rem 0.4rem;
            border-radius: 20px;
            white-space: nowrap;
            border-width: 1px;
        }
        /* MOTION NOW — solid purple. What this planet is doing at this moment. */
        .cd-planet-badge.retro {
            color: var(--accent-purple);
            background: rgba(167,139,250,0.12);
            /* border: 1px solid rgba(167,139,250,0.35); */
        }
        .cd-planet-badge.stationary {
            color: var(--accent-purple);
            background: rgba(167,139,250,0.08);
            /* border: 1px solid rgba(167,139,250,0.28); */
        }
        /* HAPPENING NOW, AND UNUSUAL — only the Sun wears this, only during a live SWPC alert.
           Red is otherwise unused in this grid, which is the point: it appears a handful of
           days a year and means the one thing on the page that is genuinely a warning. */
        .cd-planet-badge.alert {
            color: var(--accent-red);
            background: rgba(239,83,80,0.14);
        }
        /* CHANGE COMING — cyan, dashed, fainter. One family for "not yet", whether it's a
           station or a sign change: the dashes carry "hasn't happened", and the badge TEXT
           already says which it is ("retro in 3d" / "→ Scorpio 12d"), so colour doesn't need
           to split them as well. This is where the old green went — a third hue for
           direct-vs-retrograde was distinguishing something the words had already said. */
        .cd-planet-badge.soon {
            background: transparent;
            /* border-style: dashed; */
            border: none;
            opacity: 0.8;
            color: var(--accent-cyan);
            border-color: rgba(94,234,212,0.38);
            background: rgba(94,234,212,0.06);
        }
        .cd-planet-badge.soon.retro,
        .cd-planet-badge.soon.direct { color: var(--accent-purple); border-color: rgba(94,234,212,0.38); background:rgba(167,139,250,0.12); }
        /* An imminent sign change ("→ Scorpio 12d") — cyan, matching the ingress rows in the
           foretelling card so the same event reads the same colour in both places. Spelled
           out rather than glyphed: ♏ at 0.58rem is a smudge you can't identify. */
        .cd-planet-badge.soon.ingress { color: var(--accent-cyan); border-color: rgba(94,234,212,0.38); }
        /* …unless it's walking into the reader's own sign, which is the one arrival on this
           grid that's about them. Amber, solid-weight, full opacity — it should win the row. */
        .cd-planet-badge.soon.ingress.yours {
            color: var(--accent-yours);
            /* border-color: rgba(37,180,243,0.7); */
            background: rgba(37,180,243,0.12);
            opacity: 1;
            font-weight: 600;
        }
        /* Narrow screens: drop the arcminute column rather than let four tracks crush together.
           The track change goes on the list now, since that's where the tracks live. */
        @media (max-width: 420px) {
            .cd-planets { grid-template-columns: minmax(4.5rem, 1fr) 1fr auto; }
            .cd-planet-row { gap: 0.4rem; }
            /* .cd-planet-pos { display: none; } */
            @supports not (grid-template-columns: subgrid) {
                .cd-planets { grid-template-columns: 1fr; }
                .cd-planet-row { grid-template-columns: minmax(4.5rem, 1fr) 1fr auto; }
            }
        }

        .cd-tel-note {
            font-size: 0.62rem;
            color: var(--text-dim);
            font-style: italic;
            line-height: 1.35;
        }

        /* ── Planet Telemetry Card ── */
        .cd-planet-telemetry {
            margin: 0.3rem 0 1rem;
            padding-top: 0.8rem;
            /* border-top: 1px solid rgba(167,139,250,0.07); */
        }
        /* Purple, matching .cd-planet-meaning-head — this is the same thing (the heading of the
           tapped detail panel) wearing a different mode. It was a mustard yellow that appeared
           nowhere else on the site and was not a palette token at all. */
        .cd-planet-telemetry-head {
            font-size: 0.7rem;
            font-weight: 700;
            color: var(--accent-purple);
            letter-spacing: 0.06em;
            margin-bottom: 0.6rem;
            font-family: inherit;
        }
        .cd-planet-telemetry-grid {
            display: grid;
            grid-template-columns: 1fr 1fr;
            gap: 0.55rem;
        }
        .cd-tel-item {
            display: flex;
            flex-direction: column;
            border-top: 1px solid rgba(167,139,250,0.08);
            padding-top: 0.35rem;
        }
        .cd-tel-label {
            font-size: 0.66rem;
            color: var(--text-dim);
            text-transform: uppercase;
            letter-spacing: 0.04em;
            margin-bottom: 0.1rem;
        }
        .cd-tel-value {
            font-size: 0.85rem;
            font-weight: 600;
            color: var(--text-secondary);
            font-variant-numeric: tabular-nums;
        }
        .cd-tel-unit {
            font-size: 0.7rem;
            color: var(--text-dim);
            font-weight: normal;
        }
        .cd-space-alert-dot {
            width: 7px;
            height: 7px;
            border-radius: 50%;
            flex-shrink: 0;
            animation: pulse-alert 2s infinite;
        }
        .cd-space-alert-dot.level-info { background-color: #38a169; }
        .cd-space-alert-dot.level-warning { background-color: #d69e2e; }
        .cd-space-alert-dot.level-alert { background-color: #dd6b20; }
        .cd-space-alert-dot.level-critical { background-color: #e53e3e; }

        @keyframes pulse-alert {
            0% { opacity: 0.4; }
            50% { opacity: 1; }
            100% { opacity: 0.4; }
        }

        /* ── Today's Signal (daily context) — deliberately outside the main dashboard
           card and visually quiet: background material the Oracle reads, not a
           headline metric people need to look at. ── */
        .cd-daily-context {
            margin: 0.9rem 0.3rem 0;
            padding: 0.8rem 0.2rem 0;
            opacity: 0.8;
        }
        /* Inside its fold the summary already provides the top spacing, and the head row moved
           up into that summary — so the block starts flush. */
        .cd-signal-fold .cd-daily-context { margin-top: 0; padding-top: 0; }
        /* (The signal's own header row is gone — its title and lens are the fold's summary
            line now, so there is nothing left inside the block to head.) */
        .cd-daily-context-lens {
            font-size: 0.62rem;
            text-transform: uppercase;
            letter-spacing: 0.14em;
            color: var(--text-dim);
            opacity: 0.75;
        }
        .cd-daily-context-answer {
            font-size: 0.78rem;
            color: var(--text-dim);
            line-height: 1.6;
            margin: 0 0 0.5rem;
        }
        .cd-daily-context-events-title {
            font-size: 0.7rem;
            color: var(--text-dim);
            letter-spacing: 0.06em;
            text-transform: uppercase;
            margin-bottom: 0.3rem;
        }
        .cd-daily-context-events {
            list-style: none;
            margin: 0;
            padding: 0;
        }
        .cd-daily-context-events li {
            font-size: 0.76rem;
            color: var(--text-dim);
            line-height: 1.55;
            padding: 0.1rem 0;
        }
        .cd-daily-context-events li strong {
            color: var(--text-secondary);
            font-weight: 600;
        }
        .cd-daily-context-highlight-copy {
            color: var(--text-dim);
            opacity: 0.9;
        }
        .cd-daily-context-year {
            color: var(--text-secondary);
        }

        /* (The instrument panel — .cd-instruments and the .cd-gauge family — is gone with
           the "Near Earth" fold it was built for. It was the only 2-column gauge grid on the
           page and nothing else adopted it.) */

        @keyframes formulaFade {
            0%, 85%, 100% { opacity: 0.7; }
            42%            { opacity: 1; }
        }

        /* (The dashboard refresh button is gone. It read as "press for new data" on a page
           whose data only changes when the device wakes — the reload is the browser's job.) */

        /* ── Unified history ── */
        .unified-history-wrap { margin-top: 0.5rem; }
        /* The Today card since 29 Sept — the reading and tonight in one frame. The 28px purple
           glow it wore as the reading card is gone: Dan asked for "less of a highlight", and a
           card at the top of the page does not need a halo to say it is at the top. */
        .daily-reading-card {
            background: linear-gradient(135deg, rgba(167,139,250,0.16) 0%, rgba(12,14,26,0.98) 100%);
            border: 1px solid rgba(167,139,250,0.35);
            border-radius: 14px;
            padding: 1rem 1.2rem;
            margin-bottom: 0.85rem;
            /* animation: fadeIn 0.45s ease both; */
        }

        /* ══ THE TODAY CARD'S LEAD ══════════════════════════════════════════════════════════
              The notification's shape, because that is what people tap through from: tonight's
              sky on the left, today's word beside it. See buildTodayCard in divine.js. */
        .today-card { position: relative; }
        .today-lead {
            display: flex;
            align-items: center;
            gap: 1rem;
            margin: 0.15rem 0 0.9rem;
            padding-bottom: 0.85rem;
            border-bottom: 1px solid rgba(167,139,250,0.14);
        }
        .today-lead-words { flex: 1 1 auto; min-width: 0; }
        /* No reading between the lead and tonight (a record with no awakening at all): one rule
           between them, not the lead's and tonight's stacked a rule apart. */
        .today-lead + .cd-headline { margin-top: 0; padding-top: 0; border-top: 0; }
        /* The word's own rule and gap belong to the lead row now, not to the word. */
        .today-lead .daily-word { margin: 0; padding-bottom: 0; border-bottom: 0; }
        .today-lead .daily-takeaway { margin: 0; padding-bottom: 0; }

        /* ── The Sunset card — its own card under Today since 30 Sept ──
              Dan: "our cards are quite large, for readability split seperate cards instead of just
              divider". The same card as Today (.daily-reading-card) and the same head, so the two
              read as a pair: the day's word, then the evening's forecast. See buildSunsetCard in
              core.js. Inside: the verdict, the sentence, the colours, the author line; then the
              record of whether it has been right (.sunset-history), open; then two folds. */
        .sunset-card .cd-headline-rating { margin: 0.1rem 0 0.6rem; }
        .sunset-card .sunset-history { margin: 1rem 0 0; }
        .sunset-folds { margin-top: 0.8rem; }

        /* ── Tonight's sky ──
              The notification's own image (/api/og?card=icon), shown at half its 192px so every
              cell of its 48-cell grid is exactly two CSS pixels — pixel art only survives being
              scaled by whole numbers. `pixelated` so a 3x phone does not smooth the cells into a
              blur. A plain picture: it was a button that opened the sunset's row on the Day tab,
              and since 30 Sept the forecast in full is right under it instead. */
        .today-sky {
            flex: 0 0 auto;
            display: flex;
            flex-direction: column;
            align-items: center;
            gap: 0.35rem;
            width: 96px;
        }
        .today-sky-img {
            display: block;
            width: 96px;
            height: 96px;
            border-radius: 6px;
            image-rendering: pixelated;
            box-shadow: 0 0 0 1px rgba(255,255,255,0.07);
        }
        /* Before /api/cosmic lands: the picture's footprint, so the card does not jump. */
        .today-sky-wait {
            height: calc(96px + 1.2rem);
            border-radius: 6px;
            background: rgba(255,255,255,0.03);
            cursor: default;
        }
        /* The palette's name. It is the picture's caption, and the words that say what the
           colours are — colour is never the only thing carrying the meaning here. */
        .today-sky-cap {
            max-width: 100%;
            font-size: 0.62rem;
            line-height: 1.3;
            letter-spacing: 0.02em;
            color: var(--text-dim);
            text-align: center;
            text-wrap: balance;
        }
        /* Three quarters on a small phone: 72px is 1.5 CSS px a cell, which a 2x screen still
           draws as whole device pixels. The word beside it needs the width more than it does. */
        @media (max-width: 420px) {
            .today-lead { gap: 0.8rem; }
            .today-sky { width: 72px; }
            .today-sky-img { width: 72px; height: 72px; }
            .today-sky-wait { height: calc(72px + 1.2rem); }
        }

        /* ── The reminder, under the card it sends ──
              Dan: "pull notifications sign up out of the constellations section, it's more
              related to the daily message". It lived in the sign box on the planets card; the
              thing it sends is this card. Outside the card's frame, as a quiet line, and in
              static markup (index.html) so no repaint ever wipes the control push.js drew. */
        .today-remind { margin: -0.3rem 0 1.1rem; padding: 0 0.3rem; }
        .today-remind #push-toggle {
            display: flex;
            align-items: center;
            flex-wrap: wrap;
            gap: 0.35rem 0.7rem;
        }
        .today-remind .push-note { margin-top: 0; }
        .daily-reading-card h3 {
            font-size: 0.66rem;
            letter-spacing: 0.16em;
            text-transform: uppercase;
            color: rgba(167,139,250,0.95);
            margin-bottom: 0.65rem;
        }
        /* ── Card header — title left, Listen right ──
              The audio is an alternative to reading the card, not a footnote to it, so it can't
              live at the bottom of a fold the listener never opens. Every daily telling wears
              the same header, so "there's a voice for this one" is a shape you learn once. */
        .daily-card-head {
            display: flex;
            align-items: center;
            gap: 0.7rem;
            margin-bottom: 0.65rem;
        }
        .daily-card-head h3 { margin-bottom: 0; }
        /* ── The skull, at the head of anything it actually said ──
              These two cards carry the only text on the page the Oracle WROTE; everything else
              is calculated, and a calculated thing has no speaker. So the mark that used to be
              a ✦ — the same ✦ six other blocks use — is the device itself, which is also the
              only place the object appears on a site that is entirely about it.
              Drawn by drawPixelSkull in planets-pixel.js: sixteen squares by sixteen, same hand
              as the planets. The turquoise is the real stone inside it.

              A flex sibling of the h3 rather than a glyph inside it: the head is already a flex
              row, so alignment costs nothing, the heading stays pure text for a screen reader,
              and the icon is free to be taller than the 0.66rem caps beside it.
              Sized in px, not em, and never below 16: the sprite IS 16 squares, so anything
              smaller drops whole rows of it — the one scaling direction pixel art cannot take. */
        .daily-card-skull {
            width: 24px;
            height: 24px;
            flex-shrink: 0;
            margin-right: -0.3rem;
            image-rendering: pixelated;
            image-rendering: crisp-edges;
            animation: skullBreathe 5.5s ease-in-out infinite;
        }
        /* Slow enough to be noticed only if you look — the device idles, it doesn't blink at
           you. Two LEDs' worth of glow, matching the crystal it is drawn with. */
        @keyframes skullBreathe {
            0%, 100% { filter: drop-shadow(0 0 3px rgba(94,234,212,0.18)); }
            50%      { filter: drop-shadow(0 0 8px rgba(94,234,212,0.45)); }
        }
        @media (prefers-reduced-motion: reduce) {
            .daily-card-skull {
                animation: none;
                filter: drop-shadow(0 0 4px rgba(94,234,212,0.25));
            }
        }
        .daily-card-listen {
            margin-left: auto;
            flex-shrink: 0;
            padding: 0.25rem 0.6rem;
            font-size: 0.62rem;
        }
        /* ── The date, in the card's own head ──
              Dan: "not obvious if it's a new message or still yesterday, show today's date
              clearly at top." It sits immediately after the heading rather than opposite it,
              because it is part of the same statement — "Today's Reading · Sat 30 Aug" reads as
              one label, where the same words pushed to the far edge read as two.
              The Listen button keeps the right edge (margin-left:auto above), so this has to
              stay out of its way: no auto margin here, and the head is allowed to wrap on a
              narrow phone rather than squeezing three things onto one line.
              0.62rem is the floor, not a choice — this is the smallest type the cascade allows,
              which is right for a stamp and is why it must not be nudged down later. */
        .daily-card-head { flex-wrap: wrap; }
        .daily-card-date {
            font-size: 0.62rem;
            letter-spacing: 0.08em;
            color: var(--text-dim);
            white-space: nowrap;
        }
        /* ── Why the reading is not today's ──
              Only rendered when it is true, so it never becomes furniture. Amber because it is
              the state of the reader's own device rather than a fact about the sky — the same
              reason the stale dot in the page header is amber — and the words carry it too, so
              colour is never the only thing saying so. */
        .daily-card-stale {
            margin-top: 0.9rem;
            padding: 0.45rem 0.7rem;
            font-size: 0.66rem;
            line-height: 1.5;
            color: var(--accent-amber);
            background: rgba(244, 162, 97, 0.07);
            border-radius: 8px;
            text-wrap: pretty;
        }
        /* (.cd-foretell, .cd-foretell-head and .cd-foretell-count were here: The Oracle Foretells
            as an amber-ruled section of the planets card, with an "N ahead" count. Since 30 Sept
            it is a card of its own with the heading every card has — Dan: "split oracle foretells
            from 'where they are' card" — so the rule, the amber head and the count went.) */

        /* ── The strip ──
              Thirty cells, today on the left. Marks not glyphs: a sign symbol at 15px is the
              same smudge the planet badges used to carry. This carries the *shape* of the
              month — clusters, quiet stretches, how far off the next thing is. */
        /* ── No well ──
              This sat in the recessed, amber-bordered box the sunset trend chart uses, on the
              argument that bare on the card the strip read as a sketch next to two finished
              things. In place it did the opposite: a boxed panel directly above a list of rows
              read as a separate instrument bolted to the top of them, and it was the busiest
              thing on the card. The strip is one of several bars on this dashboard and none of
              the others is in a box. */
        .cd-month-panel {
            display: block;
            margin-top: 0.7rem;
        }
        .cd-month-panel-head {
            display: flex;
            align-items: center;
            justify-content: space-between;
            gap: 0.5rem;
            flex-wrap: wrap;
            margin-bottom: 0.45rem;
            font-size: 0.62rem;
            letter-spacing: 0.09em;
            text-transform: uppercase;
            color: var(--text-dim);
        }
        /* (.cd-month-legend* is gone with the legend it styled. It taught a colour code that
           nobody has to crack: every event the strip colours is named in full on its own row a
           few pixels below it, and what the strip is FOR is shape, which reads without a key.) */
        /* ── "Further ahead" ──
              The events too rare to fit a thirty-day strip: eclipses, oppositions, greatest
              elongations. A plain data row — how far off, what it is, and the one qualifier that
              decides whether it is worth your evening. Folded, with the next eclipse named on
              the summary line, because that is the answer most people came for. */
        .ft-distant { margin-top: 0.7rem; }
        .ft-distant-row {
            display: flex;
            align-items: baseline;
            gap: 0.55rem;
            padding: 0.4rem 0;
            border-bottom: 1px solid rgba(255,255,255,0.05);
        }
        .ft-distant-row:last-of-type { border-bottom: none; }
        .ft-distant-when {
            display: flex;
            flex-direction: column;
            gap: 0.05rem;
            flex: 0 0 5.6rem;
            font-variant-numeric: tabular-nums;
        }
        .ft-distant-rel {
            font-size: 0.62rem;
            letter-spacing: 0.05em;
            text-transform: uppercase;
            color: var(--text-dim);
        }
        .ft-distant-date {
            font-size: 0.62rem;
            color: var(--text-dim);
            opacity: 0.62;
            white-space: nowrap;
        }
        .ft-distant-glyph { flex: 0 0 auto; font-size: 0.8rem; line-height: 1; }
        .ft-distant-main { min-width: 0; }
        .ft-distant-label {
            display: block;
            font-size: 0.7rem;
            color: var(--text-secondary);
        }
        .ft-distant-tail {
            display: block;
            font-size: 0.62rem;
            color: var(--text-dim);
        }
        .ft-distant-row.yours .ft-distant-label { color: var(--accent-yours); }

        .cd-month-strip {
            display: flex;
            gap: 2px;
            align-items: flex-end;
        }
        .cd-month-cell {
            flex: 1 1 0;
            min-width: 0;
            height: 22px;
            display: flex;
            flex-direction: column;
            justify-content: flex-end;
            align-items: center;
            gap: 3px;
            border-bottom: 2px solid rgba(244,162,97,0.14);
            padding-bottom: 2px;
        }
        /* A slightly stronger rule every seventh cell, so "about a fortnight" is readable
           without counting — the only calendar structure the strip needs. */
        .cd-month-cell.week-start { border-left: 1px solid rgba(255,255,255,0.07); }
        .cd-month-cell.today { border-bottom-color: var(--accent-amber); }
        .cd-month-cell-dot {
            width: 5px;
            height: 5px;
            border-radius: 50%;
            background: transparent;
            transition: transform 0.15s ease;
        }
        /* Same four colours as the timeline rows and the key above — see the note there. A
           direct station is a station, so it shares purple rather than being a fifth colour
           nobody could look up. */
        .cd-month-cell.marked .cd-month-cell-dot { background: var(--text-dim); }
        .cd-month-cell.marked.moon .cd-month-cell-dot { background: #cbd5e1; }
        .cd-month-cell.marked.ingress .cd-month-cell-dot { background: var(--accent-cyan); }
        .cd-month-cell.marked.retro .cd-month-cell-dot,
        .cd-month-cell.marked.direct .cd-month-cell-dot { background: var(--accent-purple); }
        /* Anything landing in the reader's own sign — same amber shout as the planet badges. */
        .cd-month-cell.marked.yours .cd-month-cell-dot {
            background: var(--accent-amber);
            box-shadow: 0 0 7px rgba(244,162,97,0.85);
            transform: scale(1.35);
        }
        /* The four visible-sky events, matching their timeline marks. Last in the file on
           purpose: an eclipse landing in your sign should still read as an eclipse, because it
           is the rarest thing this strip will ever show and the only one worth a plan. */
        .cd-month-cell.marked.opposition .cd-month-cell-dot,
        .cd-month-cell.marked.elongation .cd-month-cell-dot,
        .cd-month-cell.marked.pairing .cd-month-cell-dot { background: var(--accent-amber); }
        .cd-month-cell.marked.eclipse .cd-month-cell-dot {
            background: var(--accent-amber);
            box-shadow: 0 0 0 1.5px rgba(6,6,12,0.9), 0 0 9px rgba(244,162,97,0.95);
            transform: scale(1.45);
        }
        /* Marked days are targets: they light their row and take a hover state to say so.
           Unmarked days aren't, so they don't pretend to be. */
        .cd-month-cell.marked { cursor: pointer; }
        .cd-month-cell.marked:hover .cd-month-cell-dot,
        .cd-month-cell.marked:focus-visible .cd-month-cell-dot { transform: scale(1.6); }
        .cd-month-cell.marked:hover { border-bottom-color: rgba(244,162,97,0.5); }
        .cd-month-cell.is-selected {
            border-bottom-color: var(--accent-amber);
            background: rgba(244,162,97,0.1);
            border-radius: 3px 3px 0 0;
        }
        .cd-month-cell.is-selected .cd-month-cell-dot { transform: scale(1.6); }
        .cd-month-cell:focus-visible { outline: 1px solid rgba(244,162,97,0.6); outline-offset: 1px; }
        .cd-month-scale {
            display: flex;
            justify-content: space-between;
            margin-top: 0.3rem;
            width: 100%;
            font-size: 0.62rem;
            letter-spacing: 0.1em;
            text-transform: uppercase;
            color: var(--text-dim);
            opacity: 0.7;
        }
        /* ── "Keep this between us" — opt out of the reading being stored at all ── */
        .secret-toggle {
            display: flex;
            align-items: flex-start;
            gap: 0.5rem;
            margin-top: 0.6rem;
            padding: 0.5rem 0.65rem;
            border: 1px dashed rgba(94,234,212,0.28);
            border-radius: 8px;
            background: rgba(94,234,212,0.04);
            cursor: pointer;
        }
        .secret-toggle input {
            accent-color: var(--accent-cyan);
            margin: 0.15rem 0 0;
            cursor: pointer;
            flex-shrink: 0;
        }
        .secret-toggle-text { display: flex; flex-direction: column; gap: 0.15rem; }
        .secret-toggle-title {
            font-size: 0.68rem;
            color: var(--accent-cyan);
            letter-spacing: 0.04em;
        }
        .secret-toggle-sub {
            font-size: 0.62rem;
            color: var(--text-dim);
            line-height: 1.4;
        }
        .secret-toggle:has(input:checked) {
            border-style: solid;
            background: rgba(94,234,212,0.09);
        }
        /* ── Unavailable, and saying so ──
              "Keep this between us" cannot be promised on a birthday: the blessing is cached in
              a public blob so a shared link always shows the same words. The box is therefore
              unticked and disabled while the birthday box is on, and this is what that looks
              like. AFTER the :checked rule on purpose — it has to be able to take the lit
              background off a box that was ticked a moment ago.
              Dimmed to 0.72, not below: the type floor across this cascade is 0.62 and a
              disabled control is exactly where that gets forgotten. The state is in words on the
              sub-line as well, so colour is never the only thing carrying it. */
        .secret-toggle-off,
        .secret-toggle-off:has(input:checked) {
            opacity: 0.72;
            background: none;
            border-style: dashed;
            cursor: default;
        }
        .secret-toggle-off .secret-toggle-title { color: var(--text-dim); }
        /* Reassurance on the reading itself, so "was that actually private?" is answerable
           without leaving the result. */
        .oracle-secret-note {
            display: flex;
            align-items: center;
            justify-content: center;
            gap: 0.35rem;
            margin-top: 0.7rem;
            font-size: 0.62rem;
            color: var(--accent-cyan);
            letter-spacing: 0.04em;
        }

        /* ── The day's word ──
              The awakening's headword, where the mantra used to be. It is the page's standard
              label-over-value shape — small-caps label, the thing itself underneath — rather
              than the quoted italic line it replaced, because a word in quotation marks reads
              as something being spoken and this is something being handed over.

              Not centred: everything else in this card is left-aligned and a lone centred word
              would read as a heading for the card rather than as part of it. Amber is not used
              here on purpose — amber means "this is about you" across the whole page, and the
              word is about the DAY. The purple is the reading card's own colour. */
        .daily-word {
            display: flex;
            flex-direction: column;
            gap: 0.28rem;
            margin: 0.15rem 0 0.9rem;
            padding-bottom: 0.8rem;
            border-bottom: 1px solid rgba(167,139,250,0.14);
        }
        .daily-word-label {
            font-size: 0.62rem;
            letter-spacing: 0.16em;
            text-transform: uppercase;
            color: rgba(167,139,250,0.75);
        }
        .daily-word-value {
            font-size: 1.6rem;
            line-height: 1.15;
            font-weight: 600;
            letter-spacing: 0.02em;
            color: var(--text-primary);
        }

        /* The day's takeaway line — a synopsis of the reading, so it leads rather than
           trails it. Sits directly under the theme block, above the body text.
           Still live: it is the ASK reading's mantra, and every awakening in the history blob
           written before the word replaced it. */
        .daily-takeaway {
            font-size: 1.15rem;
            line-height: 1.4;
            /* color: rgba(167,139,250,0.95); */
            font-weight: 600;
            font-style: italic;
            /* text-align: center; */
            margin: 0.15rem 0 0.7rem;
            padding-bottom: 0.7rem;
            /* border-bottom: 1px solid rgba(167,139,250,0.16); */
        }
        .daily-takeaway::before { content: '\201C'; }
        .daily-takeaway::after { content: '\201D'; }
        .daily-takeaway-essence {
            font-size: 0.75rem;
            letter-spacing: 0.12em;
            text-transform: uppercase;
            font-style: normal;
            color: rgba(167,139,250,0.85);
        }
        .daily-takeaway-essence::before,
        .daily-takeaway-essence::after { content: none; }
        /* The separators between essence words — present, but not competing with the words. */
        .daily-takeaway-symbol { color: rgba(167,139,250,0.5); }
        /* Some days arrive as a couplet or three-line poem — give the breaks room. */
        .daily-reading-body { white-space: normal; }
        .daily-reading-body br { line-height: 2; }

        /* ── The awakening is a poem now, so it gets set as one ──
              Prose and verse want opposite things from a text block. Prose wants a measure wide
              enough to keep the ragged edge quiet; verse wants the line the poet chose to be the
              line you read, which means it must not wrap. So this is narrow, and the wrap that
              does happen on a small phone is made to look deliberate — a wrapped line hangs
              indented, the way a printed poem marks a line that ran out of page.
              `line-height: 2` on a <br> does nothing (a break has no box to give height to), so
              the spacing that comment intended lives here on the block instead.
              Only applied when the entry actually is one: the history blob is full of prose
              readings from before this change, and hanging indents on a paragraph look broken. */
        .daily-poem {
            line-height: 1.85;
            max-width: 34ch;
            padding-left: 1.4em;
            text-indent: -1.4em;   /* first line back to the margin; wrapped lines stay indented */
            white-space: normal;
        }
        /* The provenance tag is a block that follows the verse — it must not inherit the
           hanging indent, or the model name sits a stop further in than every line above it. */
        .daily-poem .oracle-source-tag { text-indent: 0; margin-left: -1.4em; }

        /* ── The awakening's signal theme ──
              The label sits above the name it labels, the emoji sits beside rather than on top,
              and the rationale is a gloss rather than a third heading. Same shape as the hero
              captions and the "so what" blocks on the dashboard, so the page reads as one hand. */
        /* ── Above the reading card, not inside it ──
              This was a bordered panel sitting as the first thing INSIDE the card, so the card
              opened on metadata about the reading rather than on the reading, and the words
              people came for started a screenful down on a phone.
              Out here it is a heading for the day — the lens the reading was written through —
              so it loses the box: a panel above a card reads as two cards competing, where
              bare text above a card reads as its title. */
        /* The Oracle's working, folded away. Open by tap only — the card's job is the reading,
           and two grey paragraphs of justification above it were the main reason the whole
           thing read as a wall of words. */

        /* Which form today's awakening came in — couplet, small joke, permission slip. Same
           small-caps label grammar as the theme label above it, so it reads as a caption on
           the reading rather than as another heading competing with it. */
        .daily-form-label {
            font-size: 0.62rem;
            letter-spacing: 0.16em;
            text-transform: uppercase;
            color: var(--text-dim);
            margin-bottom: 0.25rem;
        }

        /* ══ The Ask reading ══
              The modal's result used to be a pile of inline styles that predated everything
              else on the page, so the thing people came for looked older than the dashboard
              behind it. It's assembled from the daily cards' parts now — same header, same
              takeaway, same prophecy — inside its own bordered card. */
        .divine-reading {
            padding: 1rem 1.1rem;
            border: 1px solid rgba(167,139,250,0.28);
            border-radius: 14px;
            background: linear-gradient(135deg, rgba(167,139,250,0.12) 0%, rgba(12,14,26,0.98) 100%);
            box-shadow: 0 0 28px rgba(167,139,250,0.1);
            animation: fadeIn 0.45s ease both;
        }
        .divine-reading .daily-card-head h3 {
            font-size: 0.66rem;
            letter-spacing: 0.16em;
            text-transform: uppercase;
            color: rgba(167,139,250,0.95);
            margin-bottom: 0;
        }
        /* Your question, quoted back at you — set like a prompt, so it reads as the thing you
           said rather than as another line the Oracle wrote. */
        .divine-question {
            font-size: 0.75rem;
            font-style: italic;
            line-height: 1.5;
            color: var(--text-dim);
            text-align: center;
            margin-bottom: 0.55rem;
            text-wrap: pretty;
        }
        .divine-question-caret { color: var(--accent-purple); opacity: 0.62; }
        .divine-body {
            font-size: 1.02rem;
            line-height: 1.65;
            color: var(--text-secondary);
            padding: 0.2rem 0 0.1rem;
            text-wrap: pretty;
        }
        .divine-body-silent { color: var(--text-dim); font-style: italic; }
        .divine-meta {
            display: flex;
            justify-content: center;
            flex-wrap: wrap;
            gap: 1rem;
            margin-top: 0.8rem;
            font-size: 0.68rem;
            color: var(--text-dim);
        }
        /* The seed receipt — proof your touch picked this reading and not a shuffle. Folded,
           because it's evidence for the curious, not part of what the Oracle said. */
        .divine-seed-fold { margin-top: 0.8rem; }
        .divine-seed-summary {
            list-style: none;
            cursor: pointer;
            font-size: 0.62rem;
            letter-spacing: 0.1em;
            text-transform: uppercase;
            color: var(--text-dim);
        }
        .divine-seed-summary::-webkit-details-marker { display: none; }
        .divine-seed-summary::before { content: '▸ '; }
        .divine-seed-fold[open] .divine-seed-summary::before { content: '▾ '; }
        .divine-seed-summary:hover { color: var(--accent-purple); }
        .divine-seed {
            margin-top: 0.4rem;
            padding: 0.4rem 0.6rem;
            border: 1px solid rgba(167,139,250,0.12);
            border-radius: 6px;
            font-family: var(--mono);
            font-size: 0.62rem;
            line-height: 1.5;
            color: var(--text-dim);
            word-break: break-all;
        }
        .divine-again { margin-top: 1rem; text-align: center; }

        /* The prophecy whisper — was a wall of inline style; the amber dashed treatment is the
           same one the "into your sign" lines wear, since both are the Oracle nudging you. */
        .daily-prophecy {
            margin-top: 1.75rem;
            padding: 0.5rem 0.8rem;
            font-size: 0.76rem;
            line-height: 1.45;
            /* text-align: center; */
            color: var(--accent-purple);
            background: rgba(167,139,250,0.08);
            /* border: 1px dashed rgba(244,162,97,0.28); */
            border-radius: 8px;
            text-wrap: balance;
        }
        /* In the history list, where it's one line of an old reading rather than today's news. */
        .daily-prophecy-compact {
            margin-top: 0.6rem;
            padding: 0.4rem 0.6rem;
            font-size: 0.7rem;
            line-height: 1.35;
            border-radius: 6px;
            background: rgba(244,162,97,0.04);
            border-color: rgba(244,162,97,0.2);
        }

        .ask-history-wrap {
            margin-top: 1rem;
        }
        .ask-history-card {
            border-color: rgba(167,139,250,0.22);
            background: rgba(8,10,20,0.75);
        }
        .ask-history-empty {
            color: var(--text-dim);
            font-size: 0.74rem;
            line-height: 1.6;
            padding: 0.35rem 0.1rem;
        }

