/* public/css/30-timeline.css — The Oracle Foretells
 *
 * 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 timeline rows: the when-column, the kind marks, the two tiers, the horizon mark, and the
 * 30-day strip the rows are wired to. Note the @media (max-width: 420px) override at the bottom —
 * its grid-template-columns track count must match the base rule and the markup.
 */
        /* ══ The timeline ══
              One list, time order, everything that is going to happen. Replaces two cards, a
              fold and a modal. Every row is the same shape whatever it is — when · mark ·
              what · why — so a sunset, a full moon and a planet changing sign are read with
              one habit instead of three. */
        .ft-timeline {
            display: flex;
            flex-direction: column;
            margin-top: 0.7rem;
        }
        .ft-row {
            border-top: 1px solid rgba(255,255,255,0.055);
        }
        .ft-row:first-child { border-top: 0; }
        .ft-summary {
            display: grid;
            /* ── The when-column is back, in the fold's idiom ──
               It was here as a 3.1rem single-line block, removed because it pushed every title
               a third of the way across the card, and the when became a phrase at the head of
               the sub-line instead. That traded one problem for another: "in 3 days · 12 Aug
               18:09 · Sun up" is three unrelated facts chained with identical dots, and the
               reader has to parse the punctuation to find where the date stops.
               "◉ Further ahead" had been doing it properly all along. A column is not the
               problem; a column of one line was. Stacked — relative over real date — the cell
               is narrow enough to leave the titles near the left edge, and the dates form a
               line the eye can run straight down without reading a word.
               `start` rather than `center`: the cell is two lines and the title is one, so
               centring floats the title against the middle of the date block instead of
               aligning it with the top line, which is the one it belongs to. */
            grid-template-columns: 4.5rem 0.85rem 1fr auto;
            align-items: start;
            gap: 0.55rem;
            padding: 0.5rem 0.1rem;
            cursor: pointer;
            list-style: none;
        }
        /* The mark is a 0.6rem dot in a row whose first line is ~0.78rem type. With the grid
           aligned to `start` it would sit on the cap line rather than in the middle of it. */
        .ft-summary > .ft-mark { margin-top: 0.28rem; }
        .ft-summary > .ft-chev { margin-top: 0.15rem; }

        /* ── The when-column itself ──
           Same construction as .ft-distant-when in the fold below, deliberately: these are two
           lists of dated things in one card, and them being built differently is what made
           moving between them feel like moving between two pages. Tabular figures so the dates
           line up as a column of numbers rather than as a ragged stack of words. */
        .ft-when {
            display: flex;
            flex-direction: column;
            gap: 0.05rem;
            min-width: 0;
            font-variant-numeric: tabular-nums;
        }
        .ft-when-rel {
            font-size: 0.62rem;
            letter-spacing: 0.05em;
            text-transform: uppercase;
            color: var(--text-secondary);
            white-space: nowrap;
        }
        /* Dimmer and smaller than the relative line above it, so a glance gets "tomorrow" and a
           second look gets the date to write down. A relative figure never travels without its
           real date on this page — but since 29 Sept the date travels alone past tomorrow: "in
           6 days" over "4 Oct" was two numbers on every row, and Dan wanted the list scannable.
           Today and tomorrow keep their word above it. */
        .ft-when-date {
            font-size: 0.62rem;
            color: var(--text-dim);
            opacity: 0.7;
            white-space: nowrap;
        }
        /* Today reads at full strength. It is the one row in the list you can act on now, and
           the column is the only place that is visible before you read anything. */
        .ft-row[data-month-day="0"] .ft-when-rel { color: var(--accent-cyan); }
        .ft-summary::-webkit-details-marker { display: none; }
        .ft-summary:hover .ft-title { color: var(--text-primary); }
        /* (.ft-sub-when is gone. It styled the when where it used to live — at the head of the
            sub-line, run together with everything else the row had to say. The when has its own
            column again; see .ft-when above for why it went back.) */
        /* ══ Two tiers ═══════════════════════════════════════════════════════════════════════
              This timeline carries two different kinds of thing at once: nights you could go
              outside and watch, and movements through the zodiac that are equally real and
              completely invisible. Given identical weight they read as one long undifferentiated
              feed — a total eclipse set in the same type as "Mercury enters Leo" — and the eye
              has nothing to catch on.
              So the sky rows keep full contrast and take a faint edge, and the chart rows step
              back a notch. Nothing is hidden, nothing is reordered: the list is still strictly
              chronological, and only the emphasis moves. */
        /* ── The tier edge is gone ──
              The sky rows carried a 2px left border and the eclipse row a brighter one. Every
              row in this list ALREADY has a coloured mark (.ft-mark) a few pixels to the right
              of where that border sat, so the edge was a second vertical stripe saying roughly
              the same thing — two rules of furniture per row, on a list whose whole problem was
              looking busy. Contrast alone does the tiering now, which is what it was for. */
        .ft-tier-sky > .ft-summary .ft-title { color: var(--text-primary); }
        .ft-tier-chart > .ft-summary .ft-title { color: var(--text-secondary); opacity: 0.82; }
        .ft-tier-chart > .ft-summary .ft-sub { opacity: 0.75; }
        /* An eclipse is the rarest row this card will ever print — so it keeps the extra weight,
           which reads on its own now that no row has a stripe competing with its mark. */
        .ft-row-eclipse > .ft-summary .ft-title { font-weight: 600; color: var(--accent-amber); }
        /* (.ft-odds is gone with the line it styled — "85% on the type, not the coverage. The
            minute is certain." It was the third attempt at making one hedge readable, and the
            fault was that the hedge was on display at all. The title says "Solar eclipse" now
            when the engine cannot separate total from annular, and the knife-edge geometry is
            in the row's own note where it reads as the best fact on the row.) */

        /* What to do about it, under what it is. This was the entire body of an eclipse row and
           read as nagging; it is a footnote now. Dim and small on purpose — it must be present
           and it must not be the point. */
        .ft-safety {
            margin-top: 0.4rem;
            font-size: 0.66rem;
            letter-spacing: 0.04em;
            color: var(--text-dim);
        }
        /* The mark carries the KIND without a word — same three colours as the strip's legend
           directly above it, so the dot you tapped and the row it opened are visibly the same
           thing. Deliberately a shape, not an emoji: at this size an emoji is a smudge. */
        .ft-mark {
            width: 0.6rem;
            height: 0.6rem;
            border-radius: 50%;
            background: var(--text-dim);
            box-shadow: 0 0 0 3px rgba(255,255,255,0.03);
        }
        .ft-mark-moon { background: #cbd5e1; }
        .ft-mark-ingress { background: var(--accent-cyan); }
        .ft-mark-retro, .ft-mark-direct { background: var(--accent-purple); }
        /* ── The rare ones ──
              Everything else on this timeline is a fact about the zodiac: real, calculated and
              completely invisible — nobody has ever looked up and noticed a retrograde. These
              four are nights the sky actually looks different, so they are marked in the amber
              the page uses for "this one is about you" rather than in a cycle colour, and the
              eclipse gets a ring because it is the rarest thing that will ever appear here. */
        .ft-mark-eclipse {
            background: radial-gradient(circle at 50% 50%, #06060c 0 42%, var(--accent-amber) 46% 100%);
            box-shadow: 0 0 0 2px rgba(244,162,97,0.25), 0 0 10px rgba(244,162,97,0.5);
        }
        .ft-mark-opposition,
        .ft-mark-elongation,
        .ft-mark-pairing { background: var(--accent-amber); }
        /* An eclipse outranks the "your sign" tint — see foretellSubtitle for the same call.
           `.yours` would otherwise repaint the ring flat and lose the one mark that is unlike
           every other mark on the page. */
        .ft-row.yours > .ft-summary .ft-mark-eclipse {
            background: radial-gradient(circle at 50% 50%, #06060c 0 42%, var(--accent-yours) 46% 100%);
        }
        /* (.ft-mark-rainbow is gone with its row — see the note in core.js. It was the only
           legitimate use of a spectrum on this page, which made it a shame to lose and did not
           make the row worth keeping.) */
        .ft-row.yours > .ft-summary .ft-mark { background: var(--accent-yours); }
        /* The sunset's mark is the predicted palette itself — the row's colour IS the
           forecast, which is the most words-free thing on the page. */
        .ft-mark-swatch {
            width: 0.72rem;
            height: 0.72rem;
            border-radius: 3px;
            box-shadow: 0 0 0 1px rgba(255,255,255,0.12), 0 0 10px rgba(244,162,97,0.25);
        }
        .ft-main { min-width: 0; }
        .ft-title {
            display: block;
            font-size: 0.7rem;
            color: var(--text-secondary);
            line-height: 1.3;
            transition: color 0.15s ease;
        }
        .ft-sub {
            display: block;
            font-size: 0.7rem;
            color: var(--text-dim);
            line-height: 1.35;
        }
        /* The sub-line, moved into the fold (29 Sept) — the fold's first line now, so it reads
           as the lede of what follows rather than as a caption left behind. */
        .ft-sub-folded {
            margin-bottom: 0.4rem;
            font-size: 0.74rem;
            color: var(--text-secondary);
            text-wrap: pretty;
        }
        /* ── The horizon mark ──────────────────────────────────────────────────────────────
              An eclipse row's first question is whether you can see it from here, and that was
              four hand-written sentences with the opened fold repeating whichever one you had
              just read. It is one yes/no about one thing — is the body above the horizon at the
              moment it happens — so it is drawn: a line, and a disc on one side of it. The disc
              carries its own fill (amber for the Sun, bone for the Moon, dimmed when it is
              below); the line takes `currentColor`, so it inherits the sub-line's colour and
              picks up the amber automatically on a row landing in the reader's sign.
              The words stay beside it. Nothing on this site may be readable only as a shape.

              Sized in `em`, not in pixels, and the width/height attributes on the element are
              overridden here on purpose: this mark appears in a 0.7rem sub-line AND in a 0.6rem
              distant-row tail, and a fixed 24x18 would tower over the second one. In `em` it
              tracks whatever it is sitting next to and needs no per-context override. */
        .ft-horizon {
            display: inline-block;
            width: 1.5em;
            height: 1.125em;
            vertical-align: -0.28em;
            margin-right: 0.28em;
            opacity: 0.75;
        }
        .ft-horizon.is-up { opacity: 1; }
        /* ── A highlight inside a section of highlights ──
              Dan: "we already add the 'in libra' badge to 'your' events, highlighting all the
              text is too much — it's in the Oracle Foretells section because it IS a highlight,
              so highlighting highlights makes this section look a bit fussy."

              This used to repaint the title in the sign colour at weight 600 AND repaint the
              subtitle underneath it. Two lines of coloured text, a tinted mark, and a badge
              saying "in Libra" — four devices for one fact, on a row whose neighbours are an
              eclipse and a meteor shower. The row was shouting over rows that had more to say.

              What survives is the badge (which says it in words, the accessibility rule worth
              never breaking) and the tinted mark below (a dot, not text). `display: flex` STAYS
              and is not decoration: .ft-yours-tag positions itself with `margin-left: auto`,
              which does nothing outside a flex container, so dropping this would send the badge
              back against the title instead of out to the right edge. */
        .ft-row.yours > .ft-summary .ft-title { display: flex; }
        .ft-chev {
            font-size: 0.7rem;
            color: var(--text-dim);
            transition: transform 0.18s ease;
        }
        .ft-row[open] > .ft-summary .ft-chev { transform: rotate(90deg); }
        .ft-row[open] > .ft-summary { background: rgba(255,255,255,0.02); }
        .ft-body {
            padding: 0.2rem 0.1rem 0.75rem 1.5rem;
        }
        .ft-body p {
            font-size: 0.74rem;
            line-height: 1.6;
            color: var(--text-secondary);
            margin-bottom: 0.4rem;
            text-wrap: pretty;
        }
        /* The actionable line in a row that has one — where to stand, which way to face. Lit,
           because everything above it in the fold is explanation and this is the instruction. */
        .ft-body p.ft-tip { color: var(--text-primary); }
        .ft-listen-wrap { margin: 0.5rem 0 0.2rem; }
        /* ── Four columns here too, and this rule has burned us once already ──
              The track count in this media query MUST match the number of children .ft-summary
              actually has. It said `2.6rem 0.7rem 1fr auto` for a while after the when-column was
              taken out of the markup, and that is what broke every row under 420px: four tracks
              declared, three children left, so the mark took the 2.6rem column, .ft-main was
              dropped into the 0.7rem one, and a title and a sub-line squeezed into eleven pixels
              wrapped a word at a time. The row appeared to have stacked vertically. It only ever
              reproduced on a phone, because this is the only place the rule applies — which is
              why it survived review.
              The when-column is back, so this is four tracks again. If the markup changes, change
              BOTH rules or the same fault returns in the same invisible place.
              4.1rem holds "TOMORROW" and "12 Aug 18:09" at the sizes set above; below that the
              date wraps and the two-line cell becomes three. */
        @media (max-width: 420px) {
            .ft-summary { grid-template-columns: 4.1rem 0.7rem 1fr auto; gap: 0.4rem; }
            .ft-body { padding-left: 0.6rem; }
        }
        .cd-earth-vantage {
            font-style: italic;
            color: var(--text-dim) !important;
            font-size: 0.7rem !important;
        }

        /* ══ "Next in <your sign>" ══
              The question anyone with a star sign actually has, and the page never answered it.
              Shut by default with the soonest arrival on the summary line, so it says something
              useful without being opened. */
        /* ── The visits list, no longer a fold of its own ──
              It used to be a bordered card with its own summary row, nested inside the sign
              report, which was itself inside the planets card. Three levels of disclosure for
              ten rows of dates. The sign report is the fold now (one shared .cd-fold, like
              every other section head on the page) and this is simply a titled list inside it,
              so opening one thing shows you everything rather than revealing another door. */
        .cd-visits-title {
            margin-top: 0.8rem;
            margin-bottom: 0.35rem;
            font-size: 0.62rem;
            letter-spacing: 0.14em;
            text-transform: uppercase;
            color: var(--accent-yours);
        }
        .cd-visits-body { padding: 0; }
        .cd-visit-row {
            display: flex;
            align-items: baseline;
            justify-content: space-between;
            gap: 0.6rem;
            padding: 0.22rem 0.1rem;
            font-size: 0.74rem;
            border-bottom: 1px solid rgba(255,255,255,0.04);
        }
        .cd-visit-body-name { color: var(--text-secondary); }
        .cd-visit-when { color: var(--accent-yours); font-variant-numeric: tabular-nums; }
        /* Past the model's precision horizon — dimmed, because "the 2210s" is a different kind
           of claim from "in 13 days" and shouldn't look equally confident. */
        .cd-visit-row.far .cd-visit-when { color: var(--text-dim); font-style: italic; }
        /* Flat — it lives inside .cd-signbox now, which supplies the border and the tint. It
           kept its own rounded tinted panel for a while after moving in, which put a box inside
           a box for no reason anyone could see. */
        .cd-visits-remind {
            display: flex;
            align-items: baseline;
            gap: 0.45rem;
            font-size: 0.68rem;
            line-height: 1.45;
            color: var(--text-secondary);
        }
        .cd-visits-remind-icon { color: var(--accent-yours); }
        .cd-visits-remind-body { display: flex; flex-direction: column; gap: 0.45rem; flex: 1; }

        /* ── The reminder opt-in ── */
        .push-btn {
            display: inline-flex;
            align-items: center;
            gap: 0.45rem;
            padding: 0.4rem 0.75rem;
            border-radius: 999px;
            border: 1px solid rgba(37,180,243,0.5);
            background: rgba(37,180,243,0.08);
            color: var(--accent-yours);
            font-family: inherit;
            font-size: 0.68rem;
            letter-spacing: 0.05em;
            cursor: pointer;
            transition: background 0.18s ease, border-color 0.18s ease;
        }
        .push-btn:hover { background: rgba(37,180,243,0.16); }
        .push-btn:disabled { opacity: 0.6; cursor: default; }
        .push-btn-dot {
            width: 0.45rem;
            height: 0.45rem;
            border-radius: 50%;
            background: transparent;
            border: 1px solid var(--accent-yours);
        }
        /* Filled and glowing once it's actually on — the difference between "you can turn this
           on" and "this is on" should be visible without reading the label. */
        .push-btn.on .push-btn-dot {
            background: var(--accent-yours);
            box-shadow: 0 0 8px var(--accent-yours);
        }
        .push-note {
            margin-top: 0.35rem;
            font-size: 0.62rem;
            line-height: 1.5;
            color: var(--text-dim);
            text-wrap: pretty;
        }
        .cd-visits-remind strong { color: var(--accent-yours); font-weight: 600; }
        .cd-visits-note {
            margin-top: 0.4rem;
            font-size: 0.62rem;
            line-height: 1.45;
            color: var(--text-dim);
            text-wrap: pretty;
        }
        /* (A .cd-station-alert selector dangled here too — same retired component, same bad
           sweep. Nothing below it depended on it.) */

        /* (The standalone moon illumination bar is gone — the moon hero's segmented phase
            bar carries the same fact once, instead of illumination, phase and cycle progress
            each drawing their own line.) */

        /* (The labelled cycle-row family went with the Solar Term — every tab is a hero and
            one bar now, so there is no second kind of row to style. What survives is the
            plain fallback bar and the one-line explainer beneath a hero's bar.) */
        /* ── The evocative word, lit ──
              A planet's function ("your mind"), an hour's character ("love and beauty"), a
              season's theme. Amber because the purple accent is already doing "this one is
              yours / this one is active", and these aren't state — they're the words worth
              landing on. Weight rather than a background, so a sentence still reads as a
              sentence. */
        .cd-keyword {
            color: var(--accent-cyan);
            font-weight: 600;
        }

        /* ── Segmented cycle bar — the whole round drawn out, current segment lit ── */
        .cd-segbar {
            display: flex;
            gap: 3px;
            margin-top: 0.5rem;
            align-items: flex-end;
        }
        .cd-segbar-cell {
            flex: 1 1 0;
            min-width: 0;
            display: flex;
            flex-direction: column;
            align-items: center;
            gap: 0.22rem;
        }
        /* Three rungs — future, past, now — and they have to stay in that order. The
           readability sweep raised the base from 0.35 to 0.62, which put an UNVISITED cell
           brighter than a visited one and quietly inverted the bar. Lifted as a set instead,
           so every mark is more legible than it was and the ranking survives. */
        .cd-segbar-mark {
            font-size: 0.62rem;
            line-height: 1;
            color: var(--text-dim);
            opacity: 0.5;
            transition: opacity 0.2s ease, color 0.2s ease;
        }
        .cd-segbar-cell.past .cd-segbar-mark { opacity: 0.78; }
        .cd-segbar-cell.active .cd-segbar-mark {
            opacity: 1;
            color: var(--accent-purple);
            font-size: 0.78rem;
            text-shadow: 0 0 8px rgba(167,139,250,0.5);
        }
        .cd-segbar-tick {
            display: block;
            position: relative;
            width: 100%;
            height: 4px;
            border-radius: 2px;
            background: rgba(167,139,250,0.09);
            /* Was `overflow: hidden`, which existed only to round the fill's ends against the
               track. The fill rounds itself now (below), and the clipping had to go so the
               leading-edge arrowhead — which is deliberately taller than the 4px track — is not
               sliced into a sliver. Nothing else here overflows: the fill is never wider than
               100%, and every band is computed inside its own cell's bounds. */
            overflow: visible;
        }

        /* ── A named stretch of the bar ──
              Golden hour is the reason this exists. It used to be a sentence carrying three
              numbers — "in 14h 11m — 20:12 to 21:02, 50 minutes of it" — which asked the reader
              to assemble a mental picture of where in the day it fell. The bar can just show it:
              a gold stripe at 95% of the way along, which is both when it is and how much of
              the day is left, without a single number to hold.

              Drawn per cell, inside the tick, so it inherits the tick's exact position and
              rounding rather than guessing them from an overlay. Sits above the progress fill,
              because the fill is where you are and this is where you're going. */
        .cd-segbar-band {
            position: absolute;
            top: 0;
            bottom: 0;
            z-index: 1;
            border-radius: 2px;
            pointer-events: none;
        }
        .cd-segbar-band.golden {
            background: linear-gradient(90deg, rgba(255,196,92,0.85), rgba(255,150,70,0.95));
            box-shadow: 0 0 7px rgba(255,180,80,0.65);
        }
        /* ── True dark: the same fact, drawn the opposite way ──────────────────────────────
              Astronomical night, and it started life as golden hour's twin — one solid stripe,
              cold and pale rather than gold, deliberately without the glow (a stripe that
              SHINES to say "properly dark" is the one place decoration would contradict the
              fact). That reasoning still holds for the colour. It did not hold for the shape,
              because the two windows are nothing like the same size:

                  golden hour      about 4% of the day bar
                  true dark        42% in August, 74% in December

              At three quarters of the width a solid stripe stops annotating the bar and simply
              becomes the bar. It buries all four cell colours, it hides the progress fill —
              which is the "you are here" — and the labels underneath then line up with nothing
              the eye can see. Flagged in exactly those terms: "'Properly dark' is such a large
              section, it sort of makes the stepped progress bars a bit confusing".

              So a long band draws its BOUNDARIES instead of its extent, which is the useful
              half anyway: what you want off this bar is when the dark starts and when it ends.
              A faint wash between, and a bright cap on each true edge — see the band-start /
              band-end classes, which mark the pieces holding the real ends rather than the
              per-cell cuts in the middle. Golden hour keeps the solid stripe: at 4% wide its
              two edges are touching, and a stripe is what two touching edges look like. */
        .cd-segbar-band.dark {
            background: rgba(150,185,255,0.17);
        }
        .cd-segbar-band.dark.band-start { border-left: 2px solid rgba(165,200,255,0.95); }
        .cd-segbar-band.dark.band-end { border-right: 2px solid rgba(165,200,255,0.95); }
        .cd-segbar-cell.past .cd-segbar-tick { background: rgba(167,139,250,0.38); }
        .cd-segbar-cell.active .cd-segbar-tick { background: rgba(167,139,250,0.15); }
        .cd-segbar-fill {
            display: block;
            position: relative;
            height: 100%;
            /* Rounds itself now that the track no longer clips it — see .cd-segbar-tick. */
            border-radius: 2px;
            background: linear-gradient(90deg, var(--accent-purple), var(--accent-cyan));
            transition: width 1s ease;
        }
        /* ── The leading edge, as an arrow ──────────────────────────────────────────────────
              Dan: "the leading edge of the stepped progress bars — eg showing the planets going
              from one constellation to the next — could be a right arrow."

              A filled stretch of track says how far through you are and says nothing about which
              way you are going. On the Day bar that is fine, because everybody knows which way a
              day runs; on a planet's passage through a sign it is the actual question — the row
              is about a crossing, and the reader has to take the direction on trust from a
              caption underneath. An arrowhead says it on the bar itself.

              Deliberately NOT the fill's own colour. Every bar tints its fill differently (the
              signs by element, the seasons by season, the Sun's fuel in ash) and an arrow that
              joined in would be read as more fill rather than as a marker. One pale head with a
              dark rim reads as "here, heading this way" against all of them.

              Every bar on the site advances left-to-right, including the two that look like they
              might not: the Sun's fuel burns forward in time, and buildSignBar puts a retrograding
              planet's destination on the RIGHT (see fromSign there), so the head never has to
              turn round. If a future bar does run backwards it needs its own rule, not a flip
              here. */
        .cd-segbar-fill::after {
            content: '';
            position: absolute;
            right: -5px;
            top: 50%;
            width: 0;
            height: 0;
            transform: translateY(-50%);
            border-left: 6px solid rgba(240,243,247,0.95);
            border-top: 4.5px solid transparent;
            border-bottom: 4.5px solid transparent;
            /* drop-shadow follows the alpha silhouette, so it rims the triangle rather than
               boxing it — which is what keeps the head legible on a gold band or a lit cell. */
            filter: drop-shadow(0 0 3px rgba(0,0,0,0.85));
            pointer-events: none;
        }
        /* Nothing to point at. A cycle sitting exactly on its own start has no travel behind the
           head, and an arrow floating at the left edge of an empty cell reads as a rendering
           fault rather than as a position. */
        .cd-segbar-fill[style*="width:0%"]::after { display: none; }
        /* ── Cell labels ──
              Printed under the cell, because the bar is naming things nobody can infer from a
              colour. Small, tight, and centred; the active one brightens so "you are here" is
              still readable at a glance without reading all of them. Wraps to two lines rather
              than truncating — "Small hours" losing its second word would be worse than a
              slightly taller bar. */
        /* ── One line, always ──
              A cell label that wraps makes its cell taller than its neighbours, and since the
              cells sit in a row the whole bar grows a second line for the sake of one word.
              On a phone that was "Early morning" and "Late morning" wrapping while "Afternoon"
              and "Evening" did not, so the bar gained a line and shoved everything below it
              down. The labels are shortened at source too (see DAY_STAGE_META's `short`); this
              is the guard that stops a future long one doing the same thing. The full name is
              on the cell's title attribute either way. */
        .cd-segbar-name {
            display: block;
            margin-top: 0.28rem;
            font-size: 0.65rem;
            line-height: 1.25;
            letter-spacing: 0.03em;
            text-align: center;
            white-space: nowrap;
            overflow: hidden;
            text-overflow: ellipsis;
            color: var(--text-dim);
            opacity: 0.75;
            hyphens: auto;
            transition: color 0.2s ease, opacity 0.2s ease;
        }
        .cd-segbar-cell.active .cd-segbar-name {
            color: var(--text-primary);
            opacity: 1;
            font-weight: 600;
        }
        .cd-segbar-cell.past .cd-segbar-name { opacity: 0.62; }
        @media (max-width: 360px) {
            .cd-segbar-name { font-size: 0.62rem; letter-spacing: 0; }
        }

        /* ── The sky's own colour, tinting the segment itself ──
              These are roughly the real colours: gold low in the morning, near-white as the sun
              climbs, orange as it leans, violet at the seam, deepening blue through the night.
              Read as a row it is a sunrise-to-sunrise gradient, which is the thing itself rather
              than a description of it.

              The Day bar used to draw this colour as a separate block ABOVE the generic tick
              track, so each cell carried two stacked bars — a coloured one and a filling one —
              and the eye had to work out that they were one cell. The Year bar never had the
              problem because it tints the tick directly and lets the fill grow inside it, which
              is one object doing both jobs. Same treatment here now: the segment IS the bar.

              Driven off a per-stage --sky triple so the three states (future, past, current)
              are three rules rather than three per stage. */
        .cd-segbar-cell[class*="sky-"] .cd-segbar-tick { background: rgba(var(--sky), 0.16); }
        .cd-segbar-cell[class*="sky-"].past .cd-segbar-tick { background: rgba(var(--sky), 0.5); }
        .cd-segbar-cell[class*="sky-"].active .cd-segbar-tick { background: rgba(var(--sky), 0.18); }
        .cd-segbar-cell[class*="sky-"].active .cd-segbar-fill {
            background: rgb(var(--sky));
            box-shadow: 0 0 8px rgba(var(--sky), 0.55);
        }
        /* The mark span stays empty and out of the way — the colour lives in the tick now. */
        .cd-segbar-cell[class*="sky-"] .cd-segbar-mark { display: none; }

        .cd-segbar-cell.sky-early-morning { --sky: 255,215,154; }
        .cd-segbar-cell.sky-late-morning  { --sky: 255,244,207; }
        .cd-segbar-cell.sky-afternoon     { --sky: 255,201,120; }
        .cd-segbar-cell.sky-early-evening { --sky: 255,154,94; }
        .cd-segbar-cell.sky-late-evening  { --sky: 168,107,191; }
        .cd-segbar-cell.sky-night         { --sky: 77,95,181; }
        .cd-segbar-cell.sky-small-hours   { --sky: 43,52,116; }
        .cd-segbar-cell.sky-before-dawn   { --sky: 106,126,203; }
        /* Retired stage keys, kept so a cached payload from before the split still tints. */
        .cd-segbar-cell.sky-dawn          { --sky: 243,166,160; }
        .cd-segbar-cell.sky-morning       { --sky: 255,215,154; }
        .cd-segbar-cell.sky-midday        { --sky: 255,244,207; }

        /* ── Seasonal tinting on the Year bar ──
              Twelve cells in four runs of three. The season reads as a block of colour without
              anyone having to count, and the month still reads exactly — which is why the bar
              stayed at twelve cells rather than dropping to four seasons. Cool blue through
              green, gold, then amber-brown, so the run of colour is itself the year turning.
              Only the ticks are tinted; the marks stay neutral so the letters stay legible. */
        .cd-segbar-cell.season-winter .cd-segbar-tick { background: rgba(125,170,225,0.16); }
        .cd-segbar-cell.season-spring .cd-segbar-tick { background: rgba(120,210,150,0.16); }
        .cd-segbar-cell.season-summer .cd-segbar-tick { background: rgba(240,200,110,0.16); }
        .cd-segbar-cell.season-autumn .cd-segbar-tick { background: rgba(215,140,95,0.16); }
        .cd-segbar-cell.season-winter.past .cd-segbar-tick { background: rgba(125,170,225,0.5); }
        .cd-segbar-cell.season-spring.past .cd-segbar-tick { background: rgba(120,210,150,0.5); }
        .cd-segbar-cell.season-summer.past .cd-segbar-tick { background: rgba(240,200,110,0.5); }
        .cd-segbar-cell.season-autumn.past .cd-segbar-tick { background: rgba(215,140,95,0.5); }
        .cd-segbar-cell.season-winter.active .cd-segbar-fill { background: rgb(125,170,225); }
        .cd-segbar-cell.season-spring.active .cd-segbar-fill { background: rgb(120,210,150); }
        .cd-segbar-cell.season-summer.active .cd-segbar-fill { background: rgb(240,200,110); }
        .cd-segbar-cell.season-autumn.active .cd-segbar-fill { background: rgb(215,140,95); }

        /* (The birthday-season block is gone with the line it styled: "Libra puts your
            birthday in autumn" told the reader something they knew the moment they picked
            Libra. The sign lens still earns its amber in the planets card, where it says
            which planets are in your sign now and when the next one arrives.) */

        /* A one-line "why it's called that", shut by default. Same idea as the awakening's
           theme fold: the etymology is the reward for tapping, never the thing in your way. */
        .cd-lore-fold { margin-top: 0.5rem; }
        .cd-lore-summary {
            display: inline-block;
            font-size: 0.62rem;
            letter-spacing: 0.1em;
            text-transform: uppercase;
            color: var(--text-dim);
            cursor: pointer;
            list-style: none;
            border-bottom: 1px dotted rgba(94,234,212,0.35);
            padding-bottom: 1px;
            transition: color 0.2s ease;
        }
        .cd-lore-summary::-webkit-details-marker { display: none; }
        .cd-lore-summary::after { content: ' ▸'; }
        .cd-lore-fold[open] .cd-lore-summary::after { content: ' ▾'; }
        .cd-lore-summary:hover { color: var(--accent-cyan); }
        .cd-lore-body {
            margin-top: 0.35rem;
            font-size: 0.72rem;
            line-height: 1.6;
            color: var(--text-secondary);
            text-wrap: pretty;
        }

