* { box-sizing:border-box; }
  body { margin:0; background:var(--cream); color:var(--ink);
         font-family:var(--font-sans); font-size:15px; line-height:1.6; }
  /* Grid and flex children default to min-width:auto, which lets a wide table
     push the whole page sideways. This is the rule the signed-in mockup was
     missing on all seventeen routes. */
  .l-wrap > *, .l-sec > * { min-width:0; }
  .l-wrap { max-width:var(--wrap); margin:0 auto; padding:0 16px; }
  .l-sec { padding:38px 0; }
  .l-alt { background:var(--surface-2); border-block:1px solid var(--line-soft); }
  .l-sub { font-size:var(--text-base); line-height:1.62; color:var(--ink-2);
           margin:0; max-width:66ch; }
  /* A link in a lede had no colour and came out in the browser's own
     -webkit-link — rgb(158,158,255) in dark, #0000EE in light. .l-sub is on
     every page, so this was one page today and any page that adds a link to a
     lede tomorrow. Set here rather than on the page that happened to have
     one. */
  .l-sub a { color:var(--gold-dk); text-underline-offset:2px; }
  /* A CENTRED SECTION, for pages whose head is centred too. Lives here rather
     than in a page's stylesheet because two clusters use it now — it was
     .ai-c in ai_astrologer.py, and pages/dasha.py picked up the class without
     the rule, so its ledes rendered left under centred heads and looked like
     an oversight. margin-inline is not optional: .l-sub caps at 66ch, so
     centring the text without centring the box leaves a centred column
     sitting on the left of the wrap.
     Only the lede. Lists, tables and cards inside a .l-ctr stay left —
     centred body copy is ragged on both edges and a centred bulleted list
     stops forming a column to scan. */
  .l-ctr .l-sub { text-align:center; margin-inline:auto; }
  /* TWO LEDES GO SIDE BY SIDE. One is fine stacked: 66ch keeps a line
     readable and the grid or panel under it carries the width. Two of them
     stacked is not — they fill the left half of the band, the right half is
     empty, and under a full-width heading with a full-width panel below it
     the pair reads as a column that has been cut off rather than as air.
     Measured at 1280: 582px of a 1180px section, 49% of it, twice over.

     A track each, so both keep the SAME measure they had — this is a layout
     fix, not a wider line. Stretching one paragraph across 1180px would give
     150 characters to a line that is already at 74.

     auto-fit rather than two fixed columns, because the home page has a pair
     inside a half-width column; there they stack again rather than becoming
     two forty-character ribbons.

     .l-sub KEEPS ITS 66ch. Each track comes out at 552px against a 582px
     cap, so the track is what governs in two columns and the cap is what
     governs when it falls back to one — which is the width it has today.
     Overriding the cap to none looked tidier and gave a 736px tablet a
     93-character line, which is the fault this rule exists to avoid.

     min(400px, 100%), NOT 400px. A minimum track wider than the container
     does not shrink — it overflows it, and at 320px the whole page scrolled
     sideways by 26px. min() caps the floor at whatever room there is. */
  .l-lede { display:grid; gap:10px 44px; margin-bottom:20px;
            grid-template-columns:repeat(auto-fit, minmax(min(400px, 100%), 1fr)); }
  .l-mb { margin-bottom:20px; }
  .l-mt { margin-top:22px; }
  .l-signin, .l-signup { text-decoration:none; white-space:nowrap; }
  .l-act-u, .l-act-a { display:flex; align-items:center; gap:8px; }
  /* The drawer carries Sign in and Sign up and nothing else now — the theme
     toggle moved to top_nav's `bar`, which is the header at every width. Its
     own display and gap belong to the component, in ui.py, so the breakpoint
     that hides it there is not overruled from here. */
  .c-drawer-a .l-signin, .c-drawer-a .l-signup {
      flex:1; min-height:44px; padding:0 15px; justify-content:center; }
  /* Date and time are one question, asked once. Both values are short enough
     to sit side by side even at 360px, and pairing them stops the form
     reading as five separate chores. */
  /* Date and time side by side, and STACKED on the narrowest phones. The two
     were always a 1fr 1fr grid; what changed is that the time trigger now
     reads 09:15 PM as four flex spans rather than one string, so its
     min-content is wider than half of a 288px card and the card grew to 311 —
     7px of sideways scroll on the page the whole site links to. minmax(0,1fr)
     alone would have kept the row and clipped the readout instead. */
  .l-dt { display:grid; grid-template-columns:1fr; gap:10px; }
  @media (min-width:360px) {
    .l-dt { grid-template-columns:minmax(0,1fr) minmax(0,1fr); }
  }
  /* Part of the hero's left column, not a band of its own. It anchors the
     bottom of that column so it finishes level with the form card. */
  /* Inside the form card the list sits under the button, separated by a rule
     rather than by more whitespace — it is what pressing the button gets you,
     so it should read as part of the button's promise. */
  .l-cardsub { margin:2px 0 14px; }
  .l-cardinc { margin-top:14px; padding-top:14px;
               border-top:1px solid var(--line-soft); }
  .l-inc { list-style:none; margin:0; padding:0; display:grid; gap:9px; }
  .l-inc li { display:flex; align-items:flex-start; gap:9px; }
  .l-inc svg { flex:none; margin-top:2px; color:var(--gold-dk); }
  .l-inc span { font-size:14px; line-height:1.45; color:var(--ink-2); }

  .l-samp { display:flex; align-items:center; gap:13px; padding:14px 16px;
            text-decoration:none; color:var(--ink); border:1px solid var(--line);
            border-radius:var(--r-card); background:var(--surface); }
  .l-samp:hover { border-color:var(--gold); background:var(--gold-bg); }
  /* Between the two-column breakpoint and 1024 the left column runs 9px past
     the card, because the headline takes an extra line before the columns are
     wide enough. Four pixels off the padding and four off the stack gap close
     it without anyone being able to tell the difference. */

  .l-samp > svg:first-child { flex:none; color:var(--gold-dk); }
  .l-samp > svg:last-child { flex:none; color:var(--ink-3); margin-left:auto; }
  .l-samp span { min-width:0; }
  .l-samp b { display:block; font-size:14.5px; font-weight:700; }
  .l-samp i { display:block; font-style:normal; font-size:12.5px;
              color:var(--ink-3); margin-top:2px; line-height:1.45; }
  .l-dt .c-pf { margin-bottom:0; }
  .l-dth { margin:6px 0 var(--space-3); }
  .l-mb2 { margin-bottom:16px; }

  .l-mark { display:block; width:34px; height:34px; flex:none; }
  .l-mark img { display:block; width:100%; height:100%; border-radius:19%; }

  /* proof row */
  .l-proof { background:var(--gold-bg); border-block:1px solid var(--line); }
  .l-pfr { display:grid; grid-template-columns:repeat(2,1fr); gap:0;
           padding:4px 0; }
  .l-pf { padding:18px 4px 18px 18px; }
  /* Hairlines, not a colour change, do the separating — and only between
     cells that are actually side by side, which changes at each breakpoint. */
  .l-pf:nth-child(2n) { border-left:1px solid var(--line); }
  .l-pf:nth-child(n+3) { border-top:1px solid var(--line); }
  .l-pf:first-child { padding-left:0; }
  .l-pf b { display:block; font-family:var(--font-serif); font-size:29px;
            line-height:1.05; font-weight:600; color:var(--gold-dk);
            letter-spacing:-.015em; }
  .l-pf span { display:block; font-size:13.5px; font-weight:650; margin-top:5px;
               color:var(--ink); }
  .l-pf i { display:block; font-style:normal; font-size:12.5px; color:var(--ink-3);
            margin-top:2px; }
  @media (min-width:760px) {
    .l-pfr { grid-template-columns:repeat(4,1fr); }
    .l-pf:nth-child(n+3) { border-top:0; }
    .l-pf:nth-child(n+2) { border-left:1px solid var(--line); }
  }

  /* panchang */
  .l-panch { display:grid; gap:8px; grid-template-columns:repeat(2,1fr); }
  .l-pc { padding:13px 14px; border:1px solid var(--line); border-radius:var(--r-in);
          background:var(--surface); }
  .l-pc span { display:block; font-family:var(--font-mono); font-size:9px;
               letter-spacing:.13em; color:var(--ink-3); }
  .l-pc b { display:block; font-size:15px; margin-top:5px; }
  .l-pc i { display:block; font-style:normal; font-size:12px; color:var(--ink-3); }
  .l-pc.c-t-good b { color:var(--good); } .l-pc.c-t-bad b { color:var(--bad); }
  @media (min-width:700px) { .l-panch { grid-template-columns:repeat(3,1fr); } }
  @media (min-width:1000px) { .l-panch { grid-template-columns:repeat(6,1fr); } }

  /* rashifal */
  .l-rsg { display:grid; gap:7px; grid-template-columns:repeat(3,1fr); }
  .l-rs { display:flex; flex-direction:column; align-items:center; gap:1px;
          min-height:98px; justify-content:center; padding:12px 5px;
          border:1px solid var(--line); border-radius:var(--r-in);
          background:var(--surface); text-decoration:none; color:var(--ink);
          text-align:center; }
  .l-rs:hover { border-color:var(--gold); background:var(--gold-bg); }
  .l-rs .c-sym { color:var(--gold-dk); margin-bottom:4px; }
  .l-rs b { font-size:12.5px; font-weight:650; }
  .l-rs i { font-style:normal; font-size:10.5px; color:var(--ink-3); }
  .l-rs u { text-decoration:none; font-size:12px; color:var(--gold-dk); }
  @media (min-width:560px) { .l-rsg { grid-template-columns:repeat(4,1fr); } }
  @media (min-width:900px) { .l-rsg { grid-template-columns:repeat(6,1fr); } }

  /* tools */
  .l-tools { display:grid; gap:12px; }
  .l-ti { display:grid; place-items:center; width:40px; height:40px;
          border-radius:11px; color:var(--gold-dk); background:var(--gold-bg);
          margin-bottom:11px; }
  .l-tl { display:flex; flex-wrap:wrap; gap:6px; margin-top:13px; }
  .l-tl a { display:inline-flex; align-items:center; min-height:44px;
            font-size:12.5px; font-weight:600; padding:0 14px;
            border-radius:var(--r-pill); color:var(--ink-2);
            border:1px solid var(--line); background:var(--surface);
            text-decoration:none; }
  .l-tl a:hover { color:var(--gold-dk); border-color:var(--gold);
                  background:var(--gold-bg); }
  @media (min-width:720px) { .l-tools { grid-template-columns:repeat(2,1fr); } }

  /* astrologers */
  /* .h-astro in home.py sets display on top of this and is the only caller,
     so anything layout-ish added here is dead. The phone rail lives there. */
  .l-astro { display:grid; gap:11px; grid-template-columns:repeat(1,1fr); }
  .l-ah { display:flex; align-items:center; gap:11px; }
  .l-an { display:block; font-size:15px; font-weight:700; }
  .l-as { display:block; font-size:12.5px; color:var(--ink-3); }
  .l-am { display:flex; gap:5px; margin-top:12px; }
  @media (min-width:600px) { .l-astro { grid-template-columns:repeat(2,1fr); } }
  @media (min-width:1000px) { .l-astro { grid-template-columns:repeat(4,1fr); } }

  /* The unknown-birth-time escape hatch belongs inside the time picker, where
     someone reaches it at the exact moment they realise they cannot answer. */
  .l-unk { margin-top:14px; padding-top:12px; border-top:1px solid var(--line-soft); }
  .l-faq { margin-top:16px; }


/* ── page head ────────────────────────────────────────── */
.s-crumb { padding-top:16px; }
.s-top { padding:22px 0 6px; }
.s-head { max-width:64ch; }
/* With a form beside it the header is the full width and the two columns
   share it, so the reading underneath is not squeezed into a rail. */
.s-head-2 { max-width:none; display:grid; gap:26px;
            grid-template-columns:minmax(0,1fr); align-items:start; }
.s-head-2 > * { min-width:0; }
@media (min-width:960px) {
  .s-head-2 { grid-template-columns:minmax(0,1fr) minmax(0,380px); }
}
.s-head-t { max-width:64ch; }
.s-eyebrow { display:inline-block; font-family:var(--font-mono); font-size:10px;
             letter-spacing:.14em; text-transform:uppercase; color:var(--gold-dk);
             padding:5px 10px; border-radius:var(--r-pill);
             background:var(--gold-bg); margin-bottom:14px; }
.s-h1 { font-family:var(--font-serif); font-size:clamp(27px,5.2vw,42px);
        line-height:1.08; letter-spacing:-.021em; font-weight:600;
        margin:0 0 13px; text-wrap:balance; }
.s-h1 em { font-style:normal; color:var(--gold-dk); }
.s-dek { font-size:var(--text-md); line-height:1.62; color:var(--ink-2);
         margin:0; max-width:58ch; }
/* What the page gives back, named. See page_head() for why it is only on the
   fourteen with a full birth-details form. */
.s-ret { margin-top:18px; max-width:58ch; }
.s-ret ul { margin:8px 0 0; padding:0; list-style:none; display:grid;
            gap:5px; }
.s-ret li { position:relative; padding-left:18px; font-size:14px;
            line-height:1.55; color:var(--ink-2); }
.s-ret li::before { content:''; position:absolute; left:2px; top:9px;
                    width:5px; height:5px; border-radius:50%;
                    background:var(--gold-solid); }
@media (min-width:960px) {
  .s-head-fill { align-items:stretch; }
  .s-head-fill > .s-head-t { display:flex; flex-direction:column; }
  .s-head-fill .s-meta { margin-top:auto; padding-top:16px; }
}
/* The facts a dek would otherwise carry as adjectives. Mono, so they read as
   data rather than as more sentence. */
/* THE CENTRED HEAD, for pages that are not asking for a birth time. The
   default sits beside a form card and runs to 64ch down the left; a page
   whose top is a choice rather than a form leaves that whole right-hand
   column empty, and the text reads as the caption of something that failed
   to load. Two pages want this — the tarot hub, whose top half is six
   readings, and the astrologer pages, whose top half is a roster — so it
   lives here rather than being written twice. */
.s-head-c { max-width:700px; margin-inline:auto; text-align:center; }
.s-head-c .s-eyebrow { font-size:11.5px; letter-spacing:.09em; font-weight:700;
          border:1px solid var(--gold-lt); padding:5px 13px; margin-bottom:16px; }
.s-head-c .s-h1 { font-size:clamp(30px,5.6vw,46px); }
.s-head-c .s-dek { margin-inline:auto; max-width:62ch; }
.s-head-c .s-meta { justify-content:center; }

.s-meta { display:flex; flex-wrap:wrap; gap:8px 18px; margin-top:16px;
          font-family:var(--font-mono); font-size:11px; letter-spacing:.04em;
          color:var(--ink-3); }
.s-meta span { display:flex; align-items:center; gap:7px; }
.s-meta span + span::before { content:''; width:3px; height:3px; flex:none;
          border-radius:50%; background:var(--line); margin-left:-11px; }

/* ── related ──────────────────────────────────────────── */
.s-rel { display:grid; gap:10px; grid-template-columns:1fr; }
@media (min-width:620px) { .s-rel { grid-template-columns:repeat(2,1fr); } }
@media (min-width:960px) { .s-rel { grid-template-columns:repeat(3,1fr); } }
.s-rel > * { min-width:0; }
.s-rel-i { display:flex; align-items:flex-start; gap:12px; padding:14px 16px;
           min-height:44px; text-decoration:none; color:var(--ink);
           background:var(--surface); border:1px solid var(--line);
           border-radius:var(--r-card); }
.s-rel-i:hover { border-color:var(--gold); background:var(--gold-bg); }
.s-rel-k { flex:none; display:grid; place-items:center; width:32px; height:32px;
           border-radius:9px; background:var(--gold-bg); color:var(--gold-dk); }
.s-rel-x { min-width:0; display:flex; flex-direction:column; line-height:1.4; }
.s-rel-x b { font-size:14px; font-weight:650; }
.s-rel-x i { font-style:normal; font-size:12.5px; color:var(--ink-3);
             margin-top:2px; }

/* ── closing CTA ──────────────────────────────────────── */
.s-cta { display:grid; gap:20px; align-items:center; padding:28px;
         border-radius:var(--r-card); border:1px solid var(--gold-lt);
         background:
           radial-gradient(120% 140% at 88% 0%, var(--gold-bg) 0%, transparent 64%),
           var(--surface); }
@media (min-width:820px) {
  .s-cta { grid-template-columns:1fr auto; gap:34px; padding:32px 36px; } }
.s-cta > * { min-width:0; }
.s-cta h2 { font-family:var(--font-serif); font-size:clamp(21px,3.4vw,28px);
            line-height:1.16; letter-spacing:-.018em; font-weight:600;
            margin:0 0 9px; text-wrap:balance; }
.s-cta p { font-size:var(--text-base); line-height:1.6; color:var(--ink-2);
           margin:0; max-width:52ch; }
.s-cta-b { display:flex; flex-wrap:wrap; gap:10px; }
.s-cta-b > * { flex:1 1 auto; }
.s-cta-alt { display:inline-flex; align-items:center; justify-content:center;
             gap:8px; text-decoration:none; white-space:nowrap; }
.s-cta-alt svg { color:var(--gold-dk); }

  /* ── the thumb-zone bar ── */
  /* PHONES ONLY, by width AND pointer. A 600px-wide desktop window is not a
     phone, and pinning a bar to the bottom of one is a website cosplaying as
     an app. `hidden` is honoured because nothing here sets display on it
     except this rule — a class that set display would outrank the attribute,
     which is how three other components on this site ended up painting while
     hidden. */
  .h-bar { display:none; }
  @media (max-width:640px) and (pointer:coarse) {
    .h-bar { display:flex; align-items:center; gap:11px;
             position:fixed; left:0; right:0; bottom:0; z-index:60;
             padding:9px 14px calc(9px + env(safe-area-inset-bottom));
             background:var(--surface); border-top:1px solid var(--line);
             box-shadow:0 -6px 20px rgba(0,0,0,.10); }
    .h-bar[hidden] { display:none; }
    /* THE SPACER BELONGS TO THE FOOTER, NOT TO THE BODY.
       body{padding-bottom:78px} reserved the room, and the body's background
       is not the footer's — --cream against --surface-2 — so the difference
       between my 78px guess and the bar's actual 65px painted a 13px strip
       of the wrong colour between the two. On a dark theme that reads as a
       glowing seam above the bar.
       Padding the FOOTER instead fills the same room with the footer's own
       background, so the colour runs unbroken to the top of the bar and the
       exact height stops mattering. */
    .c-foot { padding-bottom:calc(90px + env(safe-area-inset-bottom)); }
  }
  .h-bar-p { flex:none; line-height:1.12; }
  .h-bar-p b { display:block; font-size:16px; font-weight:750;
               font-family:var(--font-mono); letter-spacing:-.02em; }
  .h-bar-p b i { font-style:normal; font-size:11px; font-weight:600; }
  .h-bar-p > span { display:block; font-size:10.5px; color:var(--ink-3); }
  .h-bar-c { flex:1; min-height:46px; display:grid; place-items:center;
             border-radius:12px; background:var(--gold); color:var(--pill-ink);
             font-size:15px; font-weight:750; text-decoration:none; }

  /* Section 02 used to be four calculator-category cards under a heading that
     said "start with your kundli". The heading promised one thing and the body
     delivered a tool directory — and at ~900px it was the heaviest block on a
     page whose job is getting people to an astrologer. It shows the actual
     thing now: a real chart for the birth details the hero form is prefilled
     with, and what comes back with it. */
  /* One card, not two objects side by side. A kundli IS a single document —
     chart, readings and the settings it was cast with belong in the same
     frame. As two blocks it left a 134px dead strip on the right, misaligned
     the columns by 13px, and orphaned the settings line under the chart. */
  .h-doc { border:1px solid var(--line); border-radius:var(--r-card);
           background:var(--surface); overflow:hidden; }
  .h-doc-h { display:flex; flex-wrap:wrap; align-items:baseline; gap:4px 12px;
             padding:14px 18px; border-bottom:1px solid var(--line-soft);
             background:var(--surface-2); }
  .h-doc-h b { font-size:14px; font-weight:700; }
  .h-doc-b { display:grid; gap:0; }
  .h-doc-ch { display:grid; place-items:center; padding:20px; }
  .h-doc-rd { padding:20px; border-top:1px solid var(--line-soft); }
  /* ── ON A PHONE, THE CHART AND NOTHING ELSE ──
     The readout beside it is eight labelled facts — LAGNA, RASHI, NAKSHATRA
     and the rest — set at 9px, which is the size that made this section a
     column of unreadable captions under a shrunk diagram. All eight are
     already IN the chart, and the chart is the thing being sold: somebody
     deciding whether to cast one wants to see what they get, not read a
     summary of it.
     So the readout goes and the diamond takes the full width. The footer
     line stays: the ayanamsa and the bhava system are the provenance, one
     line, and they are the reason to believe the picture. */
  @media (max-width:640px) {
    .h-doc-rd { display:none; }
    .h-doc-ch { padding:14px; }
    .h-doc-ch .c-nc { max-width:none; }
  }
  @media (min-width:820px) {
    .h-doc-b { grid-template-columns:auto minmax(0,1fr); }
    .h-doc-ch { border-right:1px solid var(--line-soft); }
    .h-doc-rd { border-top:0; }
  }
  .h-doc-f { display:flex; flex-wrap:wrap; justify-content:space-between; gap:6px 18px;
             padding:13px 18px; border-top:1px solid var(--line-soft);
             background:var(--surface-2); font-size:12.5px; color:var(--ink-3); }
  .h-doc-more { color:var(--ink-2); }
  .h-rd { display:grid; gap:8px; grid-template-columns:repeat(2,minmax(0,1fr)); }
  @media (min-width:520px) { .h-rd { grid-template-columns:repeat(3,minmax(0,1fr)); } }
  .h-rd-i { position:relative; padding:13px 14px; border:1px solid var(--line);
            border-radius:var(--r-in); background:var(--surface-2); }
  .h-rd-i .c-sym, .h-rd-i .h-rd-k {
                   position:absolute; top:11px; right:11px; width:22px; height:22px;
                   color:var(--gold-lt); }
  .h-rd-l { display:block; font-family:var(--font-mono); font-size:9px;
            letter-spacing:.13em; color:var(--ink-3); }
  .h-rd-i b { display:block; font-size:17px; font-weight:750; margin-top:5px;
              letter-spacing:-.01em; }
  .h-rd-i i { display:block; font-style:normal; font-size:12px; color:var(--ink-3);
              margin-top:2px; }
  /* The two dasha cells carry a date range: a whole row on a phone, and their
     own column once there is width for one. */
  .h-rd-w { grid-column:span 2; }
  @media (min-width:520px) { .h-rd-w { grid-column:span 3; } }
  @media (min-width:1000px) { .h-rd-w { grid-column:span 1; }
                              .h-rd-w i { font-size:11.5px; } }
  .h-pan { margin-top:14px; padding-top:14px; border-top:1px solid var(--line-soft); }
  .h-pan-l { display:block; font-family:var(--font-mono); font-size:9px;
             letter-spacing:.13em; color:var(--ink-3); margin-bottom:9px; }
  .h-pan-g { display:grid; gap:9px 16px;
             grid-template-columns:repeat(2,minmax(0,1fr)); }
  @media (min-width:520px) { .h-pan-g { grid-template-columns:repeat(3,minmax(0,1fr)); } }
  @media (min-width:1000px) { .h-pan-g { grid-template-columns:repeat(6,minmax(0,1fr)); } }
  .h-pan-g i { display:block; font-style:normal; font-size:11px; color:var(--ink-3); }
  .h-pan-g b { display:block; font-size:13px; font-weight:650; margin-top:1px; }
  .h-conj { margin:13px 0 0; font-size:13px; line-height:1.55; color:var(--ink-2); }
  .h-conj b { font-weight:700; color:var(--ink); }
  /* Two readings of the same day, so they share one frame and one height.
     A tab that changes the page height on click makes everything below it
     jump; the wrapper is sized to the taller panel so nothing moves. */
  .h-tabs-b { display:flex; flex-wrap:wrap; gap:8px; margin-bottom:18px; }
  .h-tab { display:inline-flex; align-items:center; gap:9px; min-height:44px;
           padding:0 16px; cursor:pointer; font-size:14px; font-weight:650;
           color:var(--ink-2); border:1px solid var(--line);
           border-radius:var(--r-pill); background:var(--surface); }
  .h-tab:hover { border-color:var(--gold-lt); color:var(--gold-dk); }
  .h-tab svg { color:var(--ink-3); }
  #tday-panchang:checked ~ * label[for="tday-panchang"],
  #tday-rashi:checked ~ * label[for="tday-rashi"] {
    background:var(--gold-solid); border-color:var(--gold-solid);
    color:var(--gold-solid-text); }
  #tday-panchang:checked ~ * label[for="tday-panchang"] svg,
  #tday-rashi:checked ~ * label[for="tday-rashi"] svg { color:currentColor; }
  .h-tab-w { display:grid; }
  /* HEIGHT FOLLOWS THE OPEN TAB — and this reverses an earlier decision, so
     the reasoning on both sides is worth keeping.
     Both panes used to share one grid cell and stay laid out (visibility,
     not display) specifically to stop the page below jumping: the note here
     measured it at up to 193px per tab click. That was the right call when
     the two panes were within 193px of each other.
     They are not any more. The rashifal pane is now the /horoscope/ block —
     twelve panes, a radar and a period bar — and stacking it means the
     Panchang tab renders a screen and a half of blank page underneath
     itself. A jump when you click beats a hole you did not ask for and
     cannot dismiss.
     min-width:0 stays, and is not optional: a grid item defaults to
     min-width:auto, so the marquee's 7,200px max-content track sized its own
     cell instead of being clipped by it and the page ran 7,718px wide.
     display:none cannot be transitioned, so the crossfade becomes a fade-IN
     by animation on the pane that is arriving — which also fixes the old
     trade noted here, that links in the hidden pane stayed focusable. */
  .h-tab-p { display:none; grid-area:1 / 1; min-width:0; }
  #tday-panchang:checked ~ * .h-tab-p-panchang,
  #tday-rashi:checked ~ * .h-tab-p-rashi {
    display:block; animation:h-tab-in .22s ease both; }
  @keyframes h-tab-in { from { opacity:0 } to { opacity:1 } }
  @media (prefers-reduced-motion:reduce) {
    #tday-panchang:checked ~ * .h-tab-p-panchang,
    #tday-rashi:checked ~ * .h-tab-p-rashi { animation:none; } }

  /* Spacing for the link under the block; the block sizes itself. */
  .h-rf-a { display:flex; justify-content:center; margin-top:18px; }
  .h-per-b { display:flex; flex-wrap:wrap; gap:8px; margin-bottom:16px; }
  .h-per-t { display:flex; flex-direction:column; min-height:44px;
             justify-content:center; padding:6px 15px; cursor:pointer;
             font-size:13.5px; font-weight:700; color:var(--ink-2);
             border:1px solid var(--line); border-radius:var(--r-in);
             background:var(--surface); }
  .h-per-t i { font-style:normal; font-size:10.5px; font-weight:500;
               color:var(--ink-3); margin-top:1px; }
  .h-per-t:hover { border-color:var(--gold-lt); }
  #per-daily:checked ~ * label[for="per-daily"],
  #per-weekly:checked ~ * label[for="per-weekly"],
  #per-monthly:checked ~ * label[for="per-monthly"] {
    background:var(--gold-bg); border-color:var(--gold); color:var(--gold-dk); }
  #per-daily:checked ~ * label[for="per-daily"] i,
  #per-weekly:checked ~ * label[for="per-weekly"] i,
  #per-monthly:checked ~ * label[for="per-monthly"] i { color:var(--gold-dk); }
  /* Same trick as the outer tabs: all three panels share one grid cell so the
     wrapper is as tall as the tallest and switching cannot move the page. */
  .h-per-w { display:grid; }
  .h-per-p { grid-area:1 / 1; min-width:0; visibility:hidden; opacity:0;
             pointer-events:none; transition:opacity .16s; }
  #per-daily:checked ~ * .h-per-p-daily,
  #per-weekly:checked ~ * .h-per-p-weekly,
  #per-monthly:checked ~ * .h-per-p-monthly {
    visibility:visible; opacity:1; pointer-events:auto; }
  @media (prefers-reduced-motion:reduce) { .h-per-p { transition:none; } }
  /* Two equal columns, and the left one centres its own content so the halves
     read as a matched pair rather than a wall of left-aligned text beside a
     centred device. */
  /* start, not center. Centring a 487px column against a 689px phone pushed
     the copy 100px down the section and left a hole under the heading. */
  /* ONE alignment axis for the left column: left.
     It was running two at once — text-align:center on the container while the
     feature cells were internally left-aligned — which is why the block read as
     scattered however carefully it was spaced. Centred text over a left-aligned
     grid gives the eye two edges to follow and it settles on neither.
     Vertically centred against the phone, so the two columns balance. The
     earlier objection was to centring a LOOSE column — once the left side was
     structured on one axis, the mass on each side matches and centring reads
     as symmetry rather than as a hole under the heading. */
  .l-app2 { display:grid; gap:26px; align-items:center; text-align:left; }
  @media (min-width:880px) {
    .l-app2 { grid-template-columns:minmax(0,1.08fr) minmax(300px,.92fr); gap:44px; }
  }
  .l-app2 > div:first-child { max-width:520px; }
  /* ── A PHONE DOES NOT NEED A PICTURE OF A PHONE ──
     This band was 1,455px at 390px wide — 1.7 screens, the longest section
     on the page, for "we also have an app". 689px of that is .c-sim, a
     simulated chat screen inside a phone frame. On a desktop it shows a
     reader what the app looks like; on a phone it is a drawing of the
     device they are holding, and it costs them four fifths of a screen to
     scroll past.
     The second lede goes with it. The first says everything carries over
     and you never type your birth details twice, which is the reason to
     install; the second re-argues the pitch of the whole page — that the
     answer is read off your own chart — three sections after the page has
     already made it. */
  @media (max-width:640px) {
    /* THE CONVERSATION STAYS. It was hidden here once — 689px of simulated
       chat inside a phone frame, on a phone — and put back, because what it
       shows is not the device, it is what an answer looks like. That is the
       one thing this band is selling and the rest of the page only describes.
       Scaled instead of removed: the frame is capped so it reads as a sample
       rather than as a second copy of the app, and the section lands near
       800px instead of 1,455. */
    .l-app2 .l-sub + .l-sub { display:none; }
    .l-app2 { gap:18px; }
    /* 250px was too tight — at that width the bubbles wrap every three or
       four words and the frame reads as a thumbnail of a chat rather than as
       a chat. The column instead, capped at the width the desktop gives it,
       which is the widest a phone can show and still look like a phone. */
    .l-app2-p { max-width:100%; min-width:0; margin-inline:auto; }
    /* Four one-per-row feature cells is 287px of list above a conversation
       that is the actual argument. Two up halves it and they still read. */
    /* .l-app2 .l-appl — the base .l-appl is declared LATER in this block, so
       a bare selector here loses at equal specificity. Sixth time. */
    .l-app2 .l-appl { grid-template-columns:1fr 1fr; gap:8px; }
    .l-app2 .l-appl li { padding:11px 12px; }
    /* min-width:0 on both, or the frame keeps its intrinsic width and the
       PAGE scrolls sideways: at a 320px viewport the column is 288 and the
       simulator rendered 310, six pixels of horizontal scroll on the whole
       document. A flex item's default min-width:auto is the usual cause and
       it is the rule .l-wrap already carries for the same reason. */
    .l-app2-p .c-sim { width:100%; max-width:330px; min-width:0; }
  }
  /* The heading moves INTO the left column so the whole side is one block that
     centres against the phone. Left outside it, the head sat alone at the top
     of the section with 180px of air between it and the copy it introduces. */
  .l-app2 .c-sh { margin-top:0; margin-bottom:var(--space-4); }
  .l-app2 .l-sub + .l-sub { margin-top:var(--space-3); }
  .l-app2 .l-sub { max-width:50ch; }
  /* min-width:0 on both. A flex item defaults to min-width:auto, so the
     simulator's min-content width sized the column and the page ran 26px over
     at 320. Third time this exact trap has bitten in this file — grid item,
     marquee, now flex item. */
  .l-app2-p { display:flex; justify-content:center; min-width:0; }
  .l-app2-p > * { min-width:0; }
  /* Rhythm: the paragraph is separated from the proof, and the action sits
     close to what justifies it. Equal gaps everywhere left the badges looking
     detached from the grid above them. */
  .l-app2 .l-sub { margin-bottom:var(--space-5); }
  .l-app2 .c-st-g { justify-content:flex-start; margin-top:var(--space-4); }
  /* CENTRED ON A PHONE. Left-aligned is right on the wide layout, where the
     badges sit under a left-aligned paragraph in a two-column band. On a phone
     that band is one centred column — heading, lede and the two simulators all
     centre — and the badges were the only thing still hanging off the left
     edge. AFTER the rule it overrides, not before: a media query adds no
     specificity, and .l-app2 .c-st-g placed above would have won on order and
     the block would have done nothing. */
  @media (max-width:640px) {
    .l-app2 .c-st-g { justify-content:center; }
  }
  .l-sims { display:grid; gap:26px; justify-items:center; }
  @media (min-width:760px) { .l-sims { grid-template-columns:repeat(2,1fr); } }
  /* A grid item defaults to min-width:auto, so the figure sized itself to the
     simulator's min-content (330px) instead of the 288px column — 26px of
     page overflow at 320. */
  .l-sims { min-width:0; }
  .l-sims figure { margin:0; min-width:0; width:100%; }
  .l-sims figcaption { margin-top:12px; text-align:center; font-size:13px;
                       font-weight:700; color:var(--ink-3); }
  .l-app3 { margin-top:30px; align-items:center; }
  .l-app3 .l-appl { margin:0; grid-template-columns:1fr; }
  @media (min-width:620px) { .l-app3 .l-appl { grid-template-columns:repeat(2,1fr); } }
  /* A 2x2 grid, each cell left-aligned inside. Four centred lines stacked in a
     column have no shared edge for the eye to follow, so they read as scattered
     however neatly they are spaced — the structure has to come from alignment,
     not from spacing. The block stays centred; its contents line up. */
  .l-appl { list-style:none; margin:0; padding:0; display:grid; gap:10px;
            grid-template-columns:1fr; text-align:left; }
  @media (min-width:520px) { .l-appl { grid-template-columns:repeat(2,1fr); } }
  .l-appl li { display:flex; align-items:flex-start; gap:10px; padding:13px 14px;
               border:1px solid var(--line); border-radius:var(--r-in);
               background:var(--surface); }
  .l-appl svg { flex:none; margin-top:1px; color:var(--gold-dk); }
  .l-appl b { display:block; font-size:13.5px; font-weight:700; line-height:1.3; }
  .l-appl i { display:block; font-style:normal; font-size:12px; color:var(--ink-3);
              margin-top:2px; line-height:1.4; }
  .h-prev-a { display:flex; flex-wrap:wrap; gap:10px; margin-top:18px; }
  /* ── TWO BUTTONS, ONE ROW, SHORTER WORDS ──
     "Cast my free kundli" and "See this whole sample" are 19 and 21
     characters; side by side at 390px they do not fit, so flex-wrap dropped
     the second onto its own line and the pair read as a stack with a gap.
     Shrinking the type to make them fit would make two 15px buttons out of a
     hero's primary action.
     So the words get shorter instead, and only here. Both labels are in the
     markup and the breakpoint chooses — not two <a> elements, which would be
     two links to the same place for a crawler and a screen reader to
     reconcile, and two sets of hrefs to keep in step. */
  .h-narrow { display:none; }
  @media (max-width:640px) {
    .h-prev-a { flex-wrap:nowrap; }
    .h-prev-a > .c-btn { flex:1 1 0; min-width:0; padding-inline:12px; }
    .h-wide { display:none; }
    .h-narrow { display:inline; }
  }
  .h-astro { display:grid; gap:12px; grid-template-columns:1fr; }
  /* A RAIL ON A PHONE, like the service strip above it. One column of
     full-width cards makes four astrologers four screens, and a reader has to
     scroll past every one to reach the section after. A row costs one screen,
     and the swipe says there are more — which there are, twenty more behind
     "See all 24".
     Bleeds past .l-wrap's 16px gutter, put back as the scroller's padding, so
     the first card still lines up with the heading AND a card can sit half
     off the right edge. A rail that stops at the gutter reads as a row that
     has ended. */
  @media (max-width:640px) {
    .h-astro { display:flex; overflow-x:auto; scroll-snap-type:x mandatory;
               scrollbar-width:none; margin-inline:-16px;
               padding:2px 16px 8px; scroll-padding-inline:16px; }
    .h-astro::-webkit-scrollbar { display:none; }
    .h-astro > * { flex:0 0 272px; scroll-snap-align:start; }
  }
  @media (min-width:640px) { .h-astro { grid-template-columns:repeat(2,1fr); } }
  @media (min-width:1000px) { .h-astro { grid-template-columns:repeat(3,1fr); } }
  .h-cta { display:flex; flex-wrap:wrap; gap:10px; }
  /* A GRID, NOT A WRAPPED ROW OF PILLS. Measured at 1280 the left column
     finished 93px above the orbit beside it — the exact hole ui.hero()'s
     docstring says it was rebuilt to close, reopened by this row being the
     shortest thing that could sit here. Four questions in two columns fill
     it, and they read as a considered block rather than as pills that
     happened to wrap; two rows of two also answer the six cards on the
     right instead of trailing off under them. */
  /* ── the question ticker ────────────────────────────────────── */
  /* FULL BLEED AND CSS ONLY. Two identical copies of the twenty-five sit in
     one track, and the track translates by -50% — a percentage of the
     TRANSFORMED element, so half a two-copy track is exactly one copy and
     the loop restarts on a seam there is nothing to see at. Translating a
     single copy by the same amount would slide the only content off and
     leave a gap. */
  /* The strip's own band.
     It is back to 0 now that the hero box itself is 50px shorter: at -30 the
     orbit cleared the strip by only 4px, which is a collision waiting for a
     longer name in the roster. */
  /* The section is just spacing now. The band inside it carries the rail and
     the border, and it sits in l-wrap, so its edges line up with the hero
     above and the cards below instead of running off both sides of the
     screen. */
  .h-tk { position:relative; }
  /* Square corners, by decision. The band is a rule across the column, not a
     card sitting in it — rounding it made it read as a third card between the
     hero and the grid below. */
  .h-tk-b { border:1px solid var(--line);
            background:var(--rail); overflow:hidden; }
  /* The label is outside the strip now, in the page's own column, so the
     moving band holds nothing but the questions. */
  .h-tk-w { padding-top:2px; }
  .h-tk-l { display:block; font-family:var(--font-mono); font-size:9.5px;
            letter-spacing:.13em; text-transform:uppercase; color:var(--ink-3);
            margin-bottom:5px; }
  /* AFTER the rule it overrides. A media query adds no specificity, so the
     later of two equal rules wins — written above it, this floor did
     nothing, twice. See the type floor in ui.py for why 9.5px is too small
     to read in a hand. */
  @media (max-width:640px) { .h-tk-l { font-size:11px; } }
  /* NO PAUSE BUTTON, by decision. What is left is :hover for a pointer,
     :focus-within for a keyboard and :active for the moment a thumb lands on
     a pill — plus prefers-reduced-motion, which stops it outright for anyone
     who has asked their system for that. The gap this leaves is a phone user
     who has NOT set that preference and wants it to stop: WCAG 2.2.2 wants a
     control for exactly that case and there is now no CSS-only one. Recorded
     here rather than quietly dropped. */
  /* Shorter: the strip is 44px of pill and 16px of air, not 72.
     The mask goes on the inner track, not on .h-tk-b — a mask on the box
     would fade its border away at both ends along with the pills. Now that
     the band has a hard edge, a pill sliding under it needs to fade rather
     than be guillotined at the corner. */
  .h-tk-m { overflow:hidden; padding:8px 0;
            -webkit-mask-image:linear-gradient(to right, transparent 0,
                #000 26px, #000 calc(100% - 26px), transparent 100%);
            mask-image:linear-gradient(to right, transparent 0,
                #000 26px, #000 calc(100% - 26px), transparent 100%); }
  .h-tk-t { display:flex; width:max-content;
            animation:h-tk-run 90s linear infinite; }
  @keyframes h-tk-run { to { transform:translateX(-50%); } }
  /* Every way there is to stop it, because each covers a case the others do
     not: hover for a pointer, focus-within for a keyboard, active for the
     moment a thumb lands on a pill, and the checkbox for everyone else. */
  .h-tk:hover .h-tk-t, .h-tk:focus-within .h-tk-t,
  .h-tk:active .h-tk-t { animation-play-state:paused; }
  /* min-width so the seam survives a shorter list than today's twenty-five:
     each copy is at least a screen wide, so the two halves are always equal
     and -50% always lands on the join. */
  .h-tk-c { display:flex; align-items:center; gap:9px; flex:0 0 auto;
            min-width:100vw; width:max-content; padding-right:9px; }
  .h-tk-c a { flex:0 0 auto; display:inline-flex; align-items:center;
              min-height:44px; padding:0 16px; border:1px solid var(--line);
              border-radius:var(--r-pill); background:var(--surface);
              font-size:13px; font-weight:600; color:var(--ink-2);
              text-decoration:none; white-space:nowrap; }
  /* ── NOT ON A PHONE AT ALL ──
     This was a marquee that clipped its pills mid-word at 390px, then a rail
     to fix that. It is gone instead: twenty-five questions that all lead to
     the same place, between a hero that has just made the offer and the
     section that lists what the site does. On a wide screen it is a band of
     movement under the fold; on a phone it is a whole screen of scrolling
     between the two things a reader came for.
     The section stays in the markup and stays indexable — only the display
     goes, and only under 640px.
     .h-tk-w AS WELL, because the label lives outside the strip. Hiding only
     .h-tk left "People are asking" standing on a phone with nothing under it
     — a heading for a band that is not there, introducing the next section by
     accident. The two are one thing and go together. */
  @media (max-width:640px) { .h-tk, .h-tk-w { display:none; } }
  .h-tk-c a:hover, .h-tk-c a:focus-visible { border-color:var(--gold);
              background:var(--gold-bg); color:var(--gold-dk); }
  /* Nothing moves, and the duplicate goes rather than printing the
     twenty-five twice down the page. */
  @media (prefers-reduced-motion:reduce) {
    /* display:block, not flex-wrap. The track was a flex row and the copy
       inside it a flex ITEM at flex:0 0 auto, so the copy sized to its own
       max-content and its flex-wrap:wrap never had a width to wrap against —
       seven of the twenty-five questions showed and the other eighteen were
       clipped with no way to reach them. As a block the copy fills the band
       and wraps for real. */
    .h-tk-t { animation:none; display:block; width:auto; }
    .h-tk-c { min-width:0; width:auto; flex-wrap:wrap; padding-right:0; }
    .h-tk-c[aria-hidden="true"] { display:none; }
    /* Nothing slides under the edge, so a fade there just looks like a fault. */
    .h-tk-m { -webkit-mask-image:none; mask-image:none; }
  }

  /* Below 1100 the two buttons cannot sit side by side without the labels
     wrapping, so they stack deliberately rather than raggedly. */
  .h-cta .c-btn { flex:1 1 100%; }
  @media (min-width:440px) { .h-cta .c-btn { flex:1 1 auto; min-width:190px; } }
  .h-alt { display:inline-flex; align-items:center; justify-content:center; gap:9px;
           text-decoration:none; }
  .h-alt svg { color:var(--gold-dk); }

  /* The panchang tab keeps the day_timeline it always had; only the data
     behind it changed. */
  .h-pan-a { display:flex; flex-wrap:wrap; align-items:center; gap:12px 26px;
             margin-top:18px; }
  .h-pan-w { display:flex; flex-direction:column; gap:1px; }
  .h-pan-w i { font-style:normal; font-family:var(--font-mono); font-size:9.5px;
               letter-spacing:.11em; text-transform:uppercase; color:var(--gold-dk); }
  .h-pan-w b { font-family:var(--font-mono); font-size:14px; font-weight:650;
               font-variant-numeric:tabular-nums; }
  .h-pan-a .c-btn { margin-left:auto; }

  /* ── 08 blog ─────────────────────────────────────────── */
  /* Three across, not four. Six posts in a four-column grid leaves a two-card
     orphan row; two rows of three finish square. */
  /* Same three-and-an-orphan problem as the reports grid. Three posts fit
     from 560px; 600 gives the titles a little more room before they start
     running to four lines. */
  .l-blg { display:grid; gap:16px; grid-template-columns:1fr; }
  @media (min-width:600px) { .l-blg { grid-template-columns:repeat(3,minmax(0,1fr)); } }
  .l-blg > * { min-width:0; }
  .l-blga { display:flex; justify-content:center; margin-top:22px; }

  /* ── 09 testimonials ─────────────────────────────────── */
  /* The row itself is ui.quote_marquee — a shared component, so its CSS lives
     with it. Nothing left to say here but the inline <code> in the lede. */
  .l-sub code { font-family:var(--font-mono); font-size:.9em; padding:1px 5px;
                border-radius:5px; background:var(--rail); color:var(--ink); }

.c-sim-m, .c-sim-typing { animation-duration:15.1s; animation-iteration-count:infinite; animation-fill-mode:both; }
.c-sim-m[style*="--i:0;"] { animation-name:c-sim-in0; }
@keyframes c-sim-in0 {
  0%,3.31% { opacity:0; max-height:0; transform:translateY(6px); }
  5.51%,92.05% { opacity:1; max-height:200px; transform:none; }
  99.5% { opacity:0; max-height:200px; }
  100% { opacity:0; max-height:0; } }
.c-sim-m[style*="--i:1;"] { animation-name:c-sim-in1; }
@keyframes c-sim-in1 {
  0%,9.93% { opacity:0; max-height:0; transform:translateY(6px); }
  12.13%,92.05% { opacity:1; max-height:200px; transform:none; }
  99.5% { opacity:0; max-height:200px; }
  100% { opacity:0; max-height:0; } }
.c-sim-m[style*="--i:2;"] { animation-name:c-sim-in2; }
@keyframes c-sim-in2 {
  0%,22.52% { opacity:0; max-height:0; transform:translateY(6px); }
  24.72%,92.05% { opacity:1; max-height:200px; transform:none; }
  99.5% { opacity:0; max-height:200px; }
  100% { opacity:0; max-height:0; } }
.c-sim-m[style*="--i:3;"] { animation-name:c-sim-in3; }
@keyframes c-sim-in3 {
  0%,29.14% { opacity:0; max-height:0; transform:translateY(6px); }
  31.34%,92.05% { opacity:1; max-height:200px; transform:none; }
  99.5% { opacity:0; max-height:200px; }
  100% { opacity:0; max-height:0; } }
.c-sim-m[style*="--i:4;"] { animation-name:c-sim-in4; }
@keyframes c-sim-in4 {
  0%,41.72% { opacity:0; max-height:0; transform:translateY(6px); }
  43.92%,92.05% { opacity:1; max-height:200px; transform:none; }
  99.5% { opacity:0; max-height:200px; }
  100% { opacity:0; max-height:0; } }
.c-sim-m[style*="--i:5;"] { animation-name:c-sim-in5; }
@keyframes c-sim-in5 {
  0%,48.34% { opacity:0; max-height:0; transform:translateY(6px); }
  50.54%,92.05% { opacity:1; max-height:200px; transform:none; }
  99.5% { opacity:0; max-height:200px; }
  100% { opacity:0; max-height:0; } }
.c-sim-m[style*="--i:6;"] { animation-name:c-sim-in6; }
@keyframes c-sim-in6 {
  0%,60.93% { opacity:0; max-height:0; transform:translateY(6px); }
  63.13%,92.05% { opacity:1; max-height:200px; transform:none; }
  99.5% { opacity:0; max-height:200px; }
  100% { opacity:0; max-height:0; } }
.c-sim-m[style*="--i:7;"] { animation-name:c-sim-in7; }
@keyframes c-sim-in7 {
  0%,67.55% { opacity:0; max-height:0; transform:translateY(6px); }
  69.75%,92.05% { opacity:1; max-height:200px; transform:none; }
  99.5% { opacity:0; max-height:200px; }
  100% { opacity:0; max-height:0; } }
.c-sim-m[style*="--i:8;"] { animation-name:c-sim-in8; }
@keyframes c-sim-in8 {
  0%,80.13% { opacity:0; max-height:0; transform:translateY(6px); }
  82.33%,92.05% { opacity:1; max-height:200px; transform:none; }
  99.5% { opacity:0; max-height:200px; }
  100% { opacity:0; max-height:0; } }
.c-sim-typing[style*="--i:2;"] { animation-name:c-sim-typ2; }
@keyframes c-sim-typ2 {
  0%,16.56% { opacity:0; max-height:0; }
  17.96%,22.52% { opacity:1; max-height:44px; }
  23.72%,100% { opacity:0; max-height:0; } }
.c-sim-typing[style*="--i:4;"] { animation-name:c-sim-typ4; }
@keyframes c-sim-typ4 {
  0%,35.76% { opacity:0; max-height:0; }
  37.16%,41.72% { opacity:1; max-height:44px; }
  42.92%,100% { opacity:0; max-height:0; } }
.c-sim-typing[style*="--i:6;"] { animation-name:c-sim-typ6; }
@keyframes c-sim-typ6 {
  0%,54.97% { opacity:0; max-height:0; }
  56.37%,60.93% { opacity:1; max-height:44px; }
  62.13%,100% { opacity:0; max-height:0; } }
.c-sim-typing[style*="--i:8;"] { animation-name:c-sim-typ8; }
@keyframes c-sim-typ8 {
  0%,74.17% { opacity:0; max-height:0; }
  75.57%,80.13% { opacity:1; max-height:44px; }
  81.33%,100% { opacity:0; max-height:0; } }
.c-dm-pane .c-sim-m, .c-dm-pane .c-sim-typing { animation-play-state:paused; }
#dm-acharya_parashara:checked ~ * .c-dm-pane-acharya_parashara { visibility:visible; opacity:1; pointer-events:auto; }
#dm-acharya_parashara:checked ~ * .c-dm-pane-acharya_parashara .c-sim-m,
#dm-acharya_parashara:checked ~ * .c-dm-pane-acharya_parashara .c-sim-typing { animation-play-state:running; }
#dm-acharya_parashara:checked ~ * label[for="dm-acharya_parashara"] { background:var(--gold-bg); border-color:var(--gold); }
#dm-astro_radha:checked ~ * .c-dm-pane-astro_radha { visibility:visible; opacity:1; pointer-events:auto; }
#dm-astro_radha:checked ~ * .c-dm-pane-astro_radha .c-sim-m,
#dm-astro_radha:checked ~ * .c-dm-pane-astro_radha .c-sim-typing { animation-play-state:running; }
#dm-astro_radha:checked ~ * label[for="dm-astro_radha"] { background:var(--gold-bg); border-color:var(--gold); }
#dm-astro_arjun:checked ~ * .c-dm-pane-astro_arjun { visibility:visible; opacity:1; pointer-events:auto; }
#dm-astro_arjun:checked ~ * .c-dm-pane-astro_arjun .c-sim-m,
#dm-astro_arjun:checked ~ * .c-dm-pane-astro_arjun .c-sim-typing { animation-play-state:running; }
#dm-astro_arjun:checked ~ * label[for="dm-astro_arjun"] { background:var(--gold-bg); border-color:var(--gold); }
#dm-astro_madhavi:checked ~ * .c-dm-pane-astro_madhavi { visibility:visible; opacity:1; pointer-events:auto; }
#dm-astro_madhavi:checked ~ * .c-dm-pane-astro_madhavi .c-sim-m,
#dm-astro_madhavi:checked ~ * .c-dm-pane-astro_madhavi .c-sim-typing { animation-play-state:running; }
#dm-astro_madhavi:checked ~ * label[for="dm-astro_madhavi"] { background:var(--gold-bg); border-color:var(--gold); }
#dm-astro_kuber:checked ~ * .c-dm-pane-astro_kuber { visibility:visible; opacity:1; pointer-events:auto; }
#dm-astro_kuber:checked ~ * .c-dm-pane-astro_kuber .c-sim-m,
#dm-astro_kuber:checked ~ * .c-dm-pane-astro_kuber .c-sim-typing { animation-play-state:running; }
#dm-astro_kuber:checked ~ * label[for="dm-astro_kuber"] { background:var(--gold-bg); border-color:var(--gold); }
#dm-astro_nidhi:checked ~ * .c-dm-pane-astro_nidhi { visibility:visible; opacity:1; pointer-events:auto; }
#dm-astro_nidhi:checked ~ * .c-dm-pane-astro_nidhi .c-sim-m,
#dm-astro_nidhi:checked ~ * .c-dm-pane-astro_nidhi .c-sim-typing { animation-play-state:running; }
#dm-astro_nidhi:checked ~ * label[for="dm-astro_nidhi"] { background:var(--gold-bg); border-color:var(--gold); }
#dm-astro_siddhi:checked ~ * .c-dm-pane-astro_siddhi { visibility:visible; opacity:1; pointer-events:auto; }
#dm-astro_siddhi:checked ~ * .c-dm-pane-astro_siddhi .c-sim-m,
#dm-astro_siddhi:checked ~ * .c-dm-pane-astro_siddhi .c-sim-typing { animation-play-state:running; }
#dm-astro_siddhi:checked ~ * label[for="dm-astro_siddhi"] { background:var(--gold-bg); border-color:var(--gold); }
#dm-astro_dhyan:checked ~ * .c-dm-pane-astro_dhyan { visibility:visible; opacity:1; pointer-events:auto; }
#dm-astro_dhyan:checked ~ * .c-dm-pane-astro_dhyan .c-sim-m,
#dm-astro_dhyan:checked ~ * .c-dm-pane-astro_dhyan .c-sim-typing { animation-play-state:running; }
#dm-astro_dhyan:checked ~ * label[for="dm-astro_dhyan"] { background:var(--gold-bg); border-color:var(--gold); }.c-sim-m, .c-sim-typing { animation-duration:15.1s; animation-iteration-count:infinite; animation-fill-mode:both; }
.c-sim-m[style*="--i:0;"] { animation-name:c-sim-in0; }
@keyframes c-sim-in0 {
  0%,3.31% { opacity:0; max-height:0; transform:translateY(6px); }
  5.51%,92.05% { opacity:1; max-height:200px; transform:none; }
  99.5% { opacity:0; max-height:200px; }
  100% { opacity:0; max-height:0; } }
.c-sim-m[style*="--i:1;"] { animation-name:c-sim-in1; }
@keyframes c-sim-in1 {
  0%,9.93% { opacity:0; max-height:0; transform:translateY(6px); }
  12.13%,92.05% { opacity:1; max-height:200px; transform:none; }
  99.5% { opacity:0; max-height:200px; }
  100% { opacity:0; max-height:0; } }
.c-sim-m[style*="--i:2;"] { animation-name:c-sim-in2; }
@keyframes c-sim-in2 {
  0%,22.52% { opacity:0; max-height:0; transform:translateY(6px); }
  24.72%,92.05% { opacity:1; max-height:200px; transform:none; }
  99.5% { opacity:0; max-height:200px; }
  100% { opacity:0; max-height:0; } }
.c-sim-m[style*="--i:3;"] { animation-name:c-sim-in3; }
@keyframes c-sim-in3 {
  0%,29.14% { opacity:0; max-height:0; transform:translateY(6px); }
  31.34%,92.05% { opacity:1; max-height:200px; transform:none; }
  99.5% { opacity:0; max-height:200px; }
  100% { opacity:0; max-height:0; } }
.c-sim-m[style*="--i:4;"] { animation-name:c-sim-in4; }
@keyframes c-sim-in4 {
  0%,41.72% { opacity:0; max-height:0; transform:translateY(6px); }
  43.92%,92.05% { opacity:1; max-height:200px; transform:none; }
  99.5% { opacity:0; max-height:200px; }
  100% { opacity:0; max-height:0; } }
.c-sim-m[style*="--i:5;"] { animation-name:c-sim-in5; }
@keyframes c-sim-in5 {
  0%,48.34% { opacity:0; max-height:0; transform:translateY(6px); }
  50.54%,92.05% { opacity:1; max-height:200px; transform:none; }
  99.5% { opacity:0; max-height:200px; }
  100% { opacity:0; max-height:0; } }
.c-sim-m[style*="--i:6;"] { animation-name:c-sim-in6; }
@keyframes c-sim-in6 {
  0%,60.93% { opacity:0; max-height:0; transform:translateY(6px); }
  63.13%,92.05% { opacity:1; max-height:200px; transform:none; }
  99.5% { opacity:0; max-height:200px; }
  100% { opacity:0; max-height:0; } }
.c-sim-m[style*="--i:7;"] { animation-name:c-sim-in7; }
@keyframes c-sim-in7 {
  0%,67.55% { opacity:0; max-height:0; transform:translateY(6px); }
  69.75%,92.05% { opacity:1; max-height:200px; transform:none; }
  99.5% { opacity:0; max-height:200px; }
  100% { opacity:0; max-height:0; } }
.c-sim-m[style*="--i:8;"] { animation-name:c-sim-in8; }
@keyframes c-sim-in8 {
  0%,80.13% { opacity:0; max-height:0; transform:translateY(6px); }
  82.33%,92.05% { opacity:1; max-height:200px; transform:none; }
  99.5% { opacity:0; max-height:200px; }
  100% { opacity:0; max-height:0; } }
.c-sim-typing[style*="--i:2;"] { animation-name:c-sim-typ2; }
@keyframes c-sim-typ2 {
  0%,16.56% { opacity:0; max-height:0; }
  17.96%,22.52% { opacity:1; max-height:44px; }
  23.72%,100% { opacity:0; max-height:0; } }
.c-sim-typing[style*="--i:4;"] { animation-name:c-sim-typ4; }
@keyframes c-sim-typ4 {
  0%,35.76% { opacity:0; max-height:0; }
  37.16%,41.72% { opacity:1; max-height:44px; }
  42.92%,100% { opacity:0; max-height:0; } }
.c-sim-typing[style*="--i:6;"] { animation-name:c-sim-typ6; }
@keyframes c-sim-typ6 {
  0%,54.97% { opacity:0; max-height:0; }
  56.37%,60.93% { opacity:1; max-height:44px; }
  62.13%,100% { opacity:0; max-height:0; } }
.c-sim-typing[style*="--i:8;"] { animation-name:c-sim-typ8; }
@keyframes c-sim-typ8 {
  0%,74.17% { opacity:0; max-height:0; }
  75.57%,80.13% { opacity:1; max-height:44px; }
  81.33%,100% { opacity:0; max-height:0; } }
/* ── 10 FAQ ──────────────────────────────────────────── */
.h-fq-b { display:flex; flex-wrap:wrap; gap:8px; margin-bottom:18px; }
/* ── ON A PHONE THE TABS ARE A RAIL ──
   Eight category tabs at 44px each, wrapping: 200px of tab strip before a
   reader reaches a single question, which is a quarter of the screen spent
   on navigation for a section that is mostly answers. In a row it is 44px
   and the swipe is the same gesture the four rails above it use.
   Written AFTER the base rule and scoped .h-fq .h-fq-b, because a media
   query adds no specificity and this file has lost that fight before. */
@media (max-width:640px) {
  .h-fq .h-fq-b { flex-wrap:nowrap; overflow-x:auto; scrollbar-width:none;
                  margin-inline:-16px; padding-inline:16px;
                  scroll-padding-inline:16px; scroll-snap-type:x proximity;
                  margin-bottom:14px; }
  .h-fq .h-fq-b::-webkit-scrollbar { display:none; }
  .h-fq .h-fq-t { flex:0 0 auto; scroll-snap-align:start; }
}
.h-fq-t { display:inline-flex; align-items:center; gap:9px; min-height:44px;
          padding:0 16px; cursor:pointer; font-size:14px; font-weight:650;
          color:var(--ink-2); border:1px solid var(--line);
          border-radius:var(--r-pill); background:var(--surface); }
.h-fq-t:hover { border-color:var(--gold-lt); color:var(--gold-dk); }
/* The count is part of the label, not decoration: it is how you know
   Getting started has five and Your kundli has five before you open either. */
.h-fq-t i { font-style:normal; font-family:var(--font-mono); font-size:11px;
            min-width:19px; height:19px; display:grid; place-items:center;
            border-radius:var(--r-pill); background:var(--rail);
            color:var(--ink-3); }
.h-fq-p { display:none; }
.h-fq-p .c-acc:last-child { margin-bottom:0; }#faq-start:checked ~ * .h-fq-p-start { display:block; }
#faq-start:focus-visible ~ * label[for="faq-start"] { outline:2px solid var(--gold); outline-offset:2px; }
#faq-start:checked ~ * label[for="faq-start"] { background:var(--gold-solid); border-color:var(--gold-solid); color:var(--gold-solid-text); }
#faq-start:checked ~ * label[for="faq-start"] i { background:var(--gold-solid-text); color:var(--gold-solid); }
#faq-tarot:checked ~ * .h-fq-p-tarot { display:block; }
#faq-tarot:focus-visible ~ * label[for="faq-tarot"] { outline:2px solid var(--gold); outline-offset:2px; }
#faq-tarot:checked ~ * label[for="faq-tarot"] { background:var(--gold-solid); border-color:var(--gold-solid); color:var(--gold-solid-text); }
#faq-tarot:checked ~ * label[for="faq-tarot"] i { background:var(--gold-solid-text); color:var(--gold-solid); }
#faq-muhurat:checked ~ * .h-fq-p-muhurat { display:block; }
#faq-muhurat:focus-visible ~ * label[for="faq-muhurat"] { outline:2px solid var(--gold); outline-offset:2px; }
#faq-muhurat:checked ~ * label[for="faq-muhurat"] { background:var(--gold-solid); border-color:var(--gold-solid); color:var(--gold-solid-text); }
#faq-muhurat:checked ~ * label[for="faq-muhurat"] i { background:var(--gold-solid-text); color:var(--gold-solid); }
#faq-kundli:checked ~ * .h-fq-p-kundli { display:block; }
#faq-kundli:focus-visible ~ * label[for="faq-kundli"] { outline:2px solid var(--gold); outline-offset:2px; }
#faq-kundli:checked ~ * label[for="faq-kundli"] { background:var(--gold-solid); border-color:var(--gold-solid); color:var(--gold-solid-text); }
#faq-kundli:checked ~ * label[for="faq-kundli"] i { background:var(--gold-solid-text); color:var(--gold-solid); }
#faq-astro:checked ~ * .h-fq-p-astro { display:block; }
#faq-astro:focus-visible ~ * label[for="faq-astro"] { outline:2px solid var(--gold); outline-offset:2px; }
#faq-astro:checked ~ * label[for="faq-astro"] { background:var(--gold-solid); border-color:var(--gold-solid); color:var(--gold-solid-text); }
#faq-astro:checked ~ * label[for="faq-astro"] i { background:var(--gold-solid-text); color:var(--gold-solid); }
#faq-pay:checked ~ * .h-fq-p-pay { display:block; }
#faq-pay:focus-visible ~ * label[for="faq-pay"] { outline:2px solid var(--gold); outline-offset:2px; }
#faq-pay:checked ~ * label[for="faq-pay"] { background:var(--gold-solid); border-color:var(--gold-solid); color:var(--gold-solid-text); }
#faq-pay:checked ~ * label[for="faq-pay"] i { background:var(--gold-solid-text); color:var(--gold-solid); }
#faq-data:checked ~ * .h-fq-p-data { display:block; }
#faq-data:focus-visible ~ * label[for="faq-data"] { outline:2px solid var(--gold); outline-offset:2px; }
#faq-data:checked ~ * label[for="faq-data"] { background:var(--gold-solid); border-color:var(--gold-solid); color:var(--gold-solid-text); }
#faq-data:checked ~ * label[for="faq-data"] i { background:var(--gold-solid-text); color:var(--gold-solid); }
  .h-f { position:relative; }
  .h-f-strip { display:flex; gap:8px; overflow-x:auto; padding:2px 2px 10px;
               scrollbar-width:thin; }
  .h-f-tile { flex:0 0 auto; display:flex; flex-direction:column;
              align-items:center; gap:2px; min-width:84px; padding:10px 12px;
              border:1px solid var(--line); border-radius:var(--r-card);
              background:transparent; color:var(--ink-2); cursor:pointer;
              text-decoration:none;
              transition:border-color .2s, background .2s; }
  .h-f-tile:focus-visible { outline:2px solid var(--gold); outline-offset:2px; }
  .h-f-tile:hover { border-color:var(--gold); color:var(--ink); }
  .h-f-tile b { font-size:13px; font-weight:600; }
  .h-f-tile i { font-style:normal; font-size:10.5px; color:var(--ink-3); }
  /* .h-f-hint and .h-f-l moved to ui.CSS — the Chinese page and the Lo Shu
     page both use them and neither includes this stylesheet, so both were
     rendering the labels as plain 16px body text. */
  .h-f-hint-m { color:var(--gold-dk); }

  .h-f-panes { display:grid; }
  .h-f-pane { grid-area:1/1; min-width:0; opacity:0; visibility:hidden; }
  .h-f-pane:first-child { opacity:1; visibility:visible; }

  /* ONE RASHI, ON ITS OWN PAGE. The twelve-pane cycle is the hub's whole
     mechanic and it is wrong here: /horoscope/taurus/ holds one pane, and
     the animation would hide it for eleven twelfths of every cycle — a page
     that is blank most of the time, which is also what a crawler would find
     if it rendered.

     Specificity does the work, not source order: .h-f-solo .h-f-pane is
     (0,2,0) against the (0,1,0) that sets the animation, and that rule is
     inside a media query, which adds no specificity at all. */
  .h-f-solo .h-f-pane { animation:none; opacity:1; visibility:visible; }
  .h-f-solo .h-f-tile { animation:none; }
  /* AND THE BAR CHART, which is the one that is easy to miss. "Across all
     rashis" is twelve bars and the cycle walks a gold ring along them in step
     with the panes. On the hub that is the page agreeing with itself; on a
     rashi's own page it is a ring hopping between twelve bars beside a
     reading about one of them, for ever, on a page where nothing else moves.
     Caught by checks/hsign-check.mjs counting running animations, because
     nothing about the markup looks wrong. */
  .h-f-solo .h-f-b { animation:none; }
  /* Marked by class, not by :target — see solo_strip(). border-color:var(--gold); background:var(--gold-bg); color:var(--ink); is the
     same declaration the hash rule uses, injected from Python so the two
     cannot drift into two different golds. */
  .h-f-tile.h-f-on { border-color:var(--gold); background:var(--gold-bg); color:var(--ink); }

  /* The reading on the left, the five areas as a pentagon on the right. */
  .h-f-card { border:1px solid var(--line); border-radius:var(--r-card);
              background:var(--surface); padding:24px 26px;
              margin-bottom:34px; display:grid; gap:20px 30px;
              grid-template-columns:1fr; align-items:center; }
  @media (min-width:900px) {
    .h-f-card { grid-template-columns:minmax(0,1fr) 268px; }
    .h-radar { border-left:1px solid var(--line); padding-left:26px; }
  }
  .h-f-main { min-width:0; }

  /* RENAMED FROM .h-rd. That name is the kundli readout grid on the home
     page — .h-rd { display:grid; grid-template-columns:repeat(3,...) } —
     and FEAT_CSS is imported there now, so horoscope's flex-column radar
     was landing on those cards and stacking them into one narrow column
     with a dead strip beside it. Two unrelated things cannot share a
     class once the stylesheet is shared. */
  .h-radar { margin:0; display:flex; flex-direction:column; align-items:center;
          gap:6px; }
  .h-radar svg { width:100%; max-width:268px; height:auto; overflow:visible; }
  .h-radar-g { fill:none; stroke:var(--line); stroke-width:1; }
  /* Translucent, not var(--gold-bg): an opaque fill painted over the 25/50/75
     rings and the chart lost its scale — it read as a lone pentagon. */
  .h-radar-s { fill:var(--gold); fill-opacity:.16; stroke:var(--gold);
            stroke-width:1.6; stroke-linejoin:round; }
  .h-radar-d { fill:var(--gold); }
  .h-radar-l { font-family:var(--font-mono); font-size:8.5px; letter-spacing:.09em;
            text-transform:uppercase; fill:var(--ink-3); }
  .h-radar-v { font-size:12px; letter-spacing:0; fill:var(--ink);
            font-weight:600; }
  .h-radar figcaption { display:flex; align-items:baseline; gap:8px; }
  .h-radar figcaption b { font-size:22px; font-weight:650;
                       font-variant-numeric:tabular-nums; }
  .h-f-eyebrow .c-sym-g { font-size:1.32em; }
  .h-f-eyebrow { font-family:var(--font-mono); font-size:10.5px;
                 letter-spacing:.12em; text-transform:uppercase;
                 color:var(--gold-dk); }
  /* flex-wrap, and it is why /horoscope/weekly/ scrolled the whole page
     sideways by 29px at 320px. Three things in this row — the quality word
     at 27px, five stars, and a DESCENDING pill — come to 349px on the
     narrowest phone, and a flex row that cannot wrap pushes the overflow
     out of the document rather than onto a second line. The daily pages
     have no trend pill, so only the four period pages ever overflowed. */
  .h-f-rate { display:flex; flex-wrap:wrap; align-items:center; gap:8px 12px;
              margin:8px 0 2px; }
  .h-f-rate b { font-family:var(--font-display); font-size:27px;
                font-weight:600; line-height:1.1; }
  .h-f-sum { font-size:16px; line-height:1.6; color:var(--ink);
             max-width:62ch; margin:6px 0 10px; }
  .h-f-over { font-size:14px; line-height:1.65; color:var(--ink-2);
              max-width:66ch; margin:0 0 4px; }
  /* inline-flex with a real height: as an inline-block it was a 23px tap
     target, which shell-check counts as a failure at every width. */
  .h-f-more { display:inline-flex; align-items:center; min-height:44px;
              margin-top:6px; font-size:13.5px; color:var(--gold-dk);
              text-decoration:none; }
  .h-f-more span { border-bottom:1px solid var(--gold-lt); }
  .h-f-more:hover span { border-bottom-color:var(--gold); }

  /* Period pages: the trend, and the named peak of the week/month/year. */
  .h-trend { font-family:var(--font-mono); font-size:10px; letter-spacing:.11em;
             text-transform:uppercase; padding:4px 9px; border-radius:999px;
             border:1px solid var(--line); color:var(--ink-2); }
  .h-trend-rising { color:var(--good); border-color:var(--good); }
  .h-trend-falling { color:var(--bad); border-color:var(--bad); }
  .h-shape { margin-bottom:34px; }
  .h-rem-wide { grid-column:1/-1; }
  .h-rem-p { font-weight:400 !important; font-size:13.5px !important;
             line-height:1.6; color:var(--ink-2); max-width:78ch; }

  .h-f-areas { display:grid; gap:12px; grid-template-columns:1fr;
               margin-bottom:34px; }
  @media (min-width:720px) { .h-f-areas { grid-template-columns:repeat(2,1fr); } }
  @media (min-width:1100px) { .h-f-areas { grid-template-columns:repeat(3,1fr); } }
  .h-f-area { min-width:0; padding:16px 18px; border:1px solid var(--line);
              border-radius:var(--r-card); background:var(--surface); }
  .h-f-area-h { display:flex; align-items:baseline; justify-content:space-between;
                gap:10px; margin-bottom:8px; }
  .h-f-area-h b { font-size:20px; font-weight:650;
                  font-variant-numeric:tabular-nums; }
  .h-f-area p { font-size:13.5px; line-height:1.6; color:var(--ink-2); margin:0; }

  .h-f-luck { display:grid; gap:14px 20px; grid-template-columns:repeat(2,1fr);
              border-top:1px solid var(--line); margin-top:18px;
              padding-top:16px; }
  @media (min-width:480px) { .h-f-luck { grid-template-columns:repeat(4,1fr); } }
  .h-f-luck-t { grid-column:1/-1; font-family:var(--font-mono); font-size:9.5px;
                letter-spacing:.12em; text-transform:uppercase;
                color:var(--gold-dk); }
  .h-f-luck-c { display:flex; flex-direction:column; gap:2px; min-width:0; }
  .h-f-luck-c b { font-size:16px; font-weight:650; line-height:1.35; }
  .h-f-note { font-size:13.5px; line-height:1.6; color:var(--ink-3);
              margin:14px 0 0; max-width:70ch; }
  .h-f-rems { border:1px solid var(--line); border-radius:var(--r-card);
              background:var(--surface); padding:18px 20px;
              display:grid; gap:16px 24px; grid-template-columns:1fr; }
  @media (min-width:620px) { .h-f-rems { grid-template-columns:repeat(2,1fr); } }
  @media (min-width:1100px) { .h-f-rems { grid-template-columns:repeat(4,1fr); } }
  .h-f-rem b { display:block; font-size:14.5px; font-weight:600; margin:3px 0 2px; }
  .h-f-rem i { font-style:normal; font-size:12px; line-height:1.45;
               color:var(--ink-3); }

  /* The four elements, each with how far through it the day is. */
  .h-dls { display:grid; gap:12px; grid-template-columns:1fr;
           margin-bottom:20px; }
  @media (min-width:560px) { .h-dls { grid-template-columns:repeat(2,1fr); } }
  @media (min-width:1000px) { .h-dls { grid-template-columns:repeat(4,1fr); } }
  .h-dl { display:flex; align-items:center; gap:14px; min-width:0;
          padding:14px 16px; border:1px solid var(--line);
          border-radius:var(--r-card); background:var(--surface); }
  .h-dl-r { flex:0 0 auto; width:52px; height:52px; transform:rotate(-90deg); }
  .h-dl-r circle { fill:none; stroke:var(--line); stroke-width:4; }
  .h-dl-r .h-dl-p { stroke:var(--gold); stroke-linecap:round; }
  .h-dl-r text { transform:rotate(90deg); transform-origin:26px 26px;
                 text-anchor:middle; dominant-baseline:central;
                 font-family:var(--font-mono); font-size:14px; fill:var(--ink-2);
                 font-variant-numeric:tabular-nums; }
  .h-dl-r .h-dl-pc { font-size:9px; fill:var(--ink-3); }
  .h-dl-t { min-width:0; }
  .h-dl-t b { display:block; font-size:15px; font-weight:650; line-height:1.3;
              margin:2px 0 1px; }
  .h-dl-t i { font-style:normal; font-size:11.5px; color:var(--ink-3); }
  .h-dl-t u { display:block; text-decoration:none; font-family:var(--font-mono);
              font-size:11px; color:var(--gold-dk); margin-top:2px; }

  /* What the rashi is, as against what today is. */
  .h-tr { position:relative; overflow:hidden; isolation:isolate;
          border:1px solid var(--line); border-radius:var(--r-card);
          background:var(--surface); padding:24px 26px 20px;
          margin-bottom:34px; }
  /* A hairline of the sign's element across the top. The only place on the
     page where colour means something other than good/bad. */
  .h-tr::before { content:''; position:absolute; inset:0 0 auto; height:2px;
                  background:var(--el, var(--gold)); opacity:.75; }
  .h-tr-e-fire  { --el:#C2542A; } .h-tr-e-earth { --el:#5E7443; }
  .h-tr-e-air   { --el:#4E7C93; } .h-tr-e-water { --el:#4A5E9E; }
  /* The rashi's own glyph, oversized and half out of frame. */
  /* A ::after, not a <span>: a 5%-opacity watermark is decoration, and as a
     real text node the contrast pass counted it as content and failed it at
     2.72:1. A fixed box with the glyph centred in it, rather than a corner
     offset, because the twelve glyphs sit at different heights inside their
     em box and a shared top/right cropped some into an unreadable band. */
  /* Anchored to the BOTTOM right, not the middle: the six-fact band has an
     opaque gold ground and sits across the vertical centre, so a centred
     watermark disappeared behind it. Down here it has only the chip rows to
     compete with, and those leave the right-hand side clear. */
  .h-tr::after { content:var(--mark); position:absolute; right:-34px;
               top:44%; z-index:-1;
               width:250px; height:250px; display:grid; place-items:center;
               font-size:200px; line-height:1; color:var(--gold);
               opacity:.055; pointer-events:none; user-select:none;
               font-family:"Apple Symbols","Segoe UI Symbol",
                           "Noto Sans Symbols 2","Noto Sans Symbols",serif; }
  @media (max-width:720px) { .h-tr::after { display:none; } }
  .h-tr-p { font-size:15px; line-height:1.65; color:var(--ink-2);
            max-width:64ch; margin:0 0 20px; }
  .h-tr-p::first-letter { font-family:var(--font-display); font-size:1.15em;
                          color:var(--ink); }
  .h-tr-fs { display:grid; gap:16px 20px; grid-template-columns:repeat(2,1fr);
             padding:16px 18px; margin-bottom:8px; border-radius:12px;
             background:var(--gold-bg); }
  @media (min-width:620px) { .h-tr-fs { grid-template-columns:repeat(3,1fr); } }
  @media (min-width:980px) { .h-tr-fs { grid-template-columns:repeat(6,1fr); } }
  .h-tr-f { display:flex; flex-direction:column; gap:3px; min-width:0; }
  .h-tr-f b { display:flex; align-items:center; gap:6px; font-size:14.5px;
              font-weight:650; line-height:1.3; }
  .h-el { flex:none; width:8px; height:8px; border-radius:50%;
          background:var(--el, var(--gold)); }
  .h-el-fire { --el:#C2542A; } .h-el-earth { --el:#5E7443; }
  .h-el-air  { --el:#4E7C93; } .h-el-water { --el:#4A5E9E; }

  .h-tr-r { display:grid; gap:8px 16px; grid-template-columns:1fr;
            padding:14px 0; border-bottom:1px solid var(--line); }
  .h-tr-r:last-child { border-bottom:0; padding-bottom:2px; }
  @media (min-width:620px) { .h-tr-r { grid-template-columns:112px 1fr;
                                       align-items:center; } }
  .h-tr-r > div { display:flex; flex-wrap:wrap; gap:7px; }
  .h-ch { border-radius:999px; padding:6px 13px; font-size:13px;
          line-height:1.35; }
  .h-ch-up { border-color:var(--gold); background:var(--gold-bg);
             color:var(--ink); font-weight:600; }
  .h-ch-dn { border-style:dashed; color:var(--ink-2); background:transparent; }
  .h-ch-do { background:var(--surface-2, transparent); }
  .h-ch-go { display:inline-flex; align-items:center; gap:7px; min-height:44px;
             padding:6px 15px; text-decoration:none; color:var(--ink); }
  .h-ch-go .c-sym-g { font-size:15px; color:var(--gold-dk); }
  .h-ch-go:hover { border-color:var(--gold); background:var(--gold-bg); }

  .h-wingg { display:grid; gap:14px; grid-template-columns:1fr;
             margin:20px 0 34px; }
  @media (min-width:720px) { .h-wingg { grid-template-columns:repeat(2,1fr); } }
  .h-wing { min-width:0; }
  .h-wins { display:flex; flex-wrap:wrap; gap:8px; margin-top:8px; }
  .h-win { display:flex; flex-direction:column; gap:1px; padding:8px 13px;
           border:1px solid var(--line); border-radius:999px;
           background:var(--surface); }
  .h-win b { font-size:12.5px; font-weight:600; color:var(--ink); }
  .h-win i { font-style:normal; font-family:var(--font-mono); font-size:11px;
             font-variant-numeric:tabular-nums; }
  .h-win.c-t-good { border-color:var(--good); }
  .h-win.c-t-bad  { border-color:var(--bad); }

  .h-f-chart { border:1px solid var(--line); border-radius:var(--r-card);
               background:var(--surface); padding:20px 18px 14px;
               margin-bottom:16px; }
  .h-f-bars { display:flex; align-items:flex-end; gap:5px; height:190px; }
  .h-f-b { flex:1 1 0; min-width:0; display:flex; flex-direction:column;
           align-items:center; justify-content:flex-end; height:100%; gap:5px;
           text-decoration:none; border-radius:6px; padding:3px 2px;
           outline:2px solid transparent; outline-offset:1px; }
  /* Scored from 35, not 0. Every rashi lands between 55 and 95 on a normal
     day, so bars drawn from zero are twelve near-identical columns and the
     comparison the chart exists to make is invisible.

     The height is a fraction of what is LEFT after the value above and the
     name below, not of the whole column -- as a percentage of the column the
     three together came to more than 100% and the names were clipped off the
     bottom edge of the card. */
  .h-f-b > em { display:block; width:100%; border-radius:5px 5px 3px 3px;
              flex:0 0 auto;
              height:max(6px, calc((100% - 42px) * var(--f))); }
  .h-f-b u { font-family:var(--font-mono); font-size:10.5px; color:var(--ink-2);
             text-decoration:none; font-variant-numeric:tabular-nums; }
  /* The full name where twelve of them fit, the three-letter form where they
     do not. "Sag" is not a rashi anybody calls their own. */
  .h-f-bn { flex:0 0 auto; font-family:var(--font-mono); font-size:10px;
                line-height:1.35; color:var(--ink-3); max-width:100%; }
  .h-f-bl, .h-f-bs { font-style:normal; display:block; white-space:nowrap;
                overflow:hidden; text-overflow:ellipsis; }
  /* "Ari" needs 20px at the 11px phone floor and the tile gave it 18. Two
     pixels, taken off the tile's own padding rather than off the type — twelve
     rashi abbreviations reading "Ar…" is a worse trade than a slightly
     tighter tile. */
  @media (max-width:640px) {
    .h-f-b { padding-inline:0; }
  }
  /* Below about 360 the twelve tiles have 24px each and "Ari" needs 20 plus
     the gap, so the codes came back as "Ar…". The chart scrolls instead: a
     rashi picker where four of the twelve are unreadable is worse than one
     that needs a swipe, and the glyph alone does not name the sign to anybody
     who has not learned the glyphs. */
  @media (max-width:379px) {
    .h-f-bars { overflow-x:auto; scrollbar-width:none;
                margin-inline:-18px; padding-inline:18px;
                scroll-padding-inline:18px; }
    .h-f-bars::-webkit-scrollbar { display:none; }
    .h-f-b { flex:0 0 30px; }
  }
  .h-f-bl { display:none; }
  @media (min-width:920px) {
    .h-f-bl { display:block; }
    .h-f-bs { display:none; }
  }
  .h-f-b:hover .h-f-bn, .h-f-b:hover u { color:var(--ink); }
  .h-f-ends { display:grid; gap:12px; grid-template-columns:1fr;
              margin-bottom:34px; }
  @media (min-width:720px) { .h-f-ends { grid-template-columns:repeat(2,1fr); } }
  .h-f-end { display:block; min-width:0; padding:16px 18px; text-decoration:none;
             color:var(--ink); border:1px solid var(--line);
             border-radius:var(--r-card); background:var(--surface); }
  .h-f-end:hover { border-color:var(--gold); }
  .h-f-end b { display:block; font-size:16px; font-weight:650; margin:2px 0 5px; }
  .h-f-end b em { font-style:normal; color:var(--ink-3); font-size:13px; }
  .h-f-end p { font-size:13px; line-height:1.55; color:var(--ink-3); margin:0; }
  /* The glyph is inline by default so it sits on the text baseline in a run
     of prose. Here it heads its own line, so it has to be blockified back. */
  .h-f-end svg, .h-f-end .c-sym-g { display:block; margin-bottom:6px;
                                    line-height:1.1; }

  .c-bg-good { background:var(--good); } .c-bg-mid { background:var(--mid); }
  .c-bg-bad  { background:var(--bad); }  .c-bg-gold { background:var(--gold-lt); }

  /* The cycle. Only under no-preference: somebody who has asked for less
     motion gets the first rashi and the strip, and picks their own. */
  @media (prefers-reduced-motion: no-preference) {
    .h-f-pane { animation:h-f-show 96s linear calc(var(--i) * 8s) infinite; }
    .h-f-tile { animation:h-f-mark 96s linear calc(var(--i) * 8s) infinite; }
    .h-f-b    { animation:h-f-ring 96s linear calc(var(--i) * 8s) infinite; }
    .h-f:hover .h-f-pane, .h-f:hover .h-f-tile, .h-f:hover .h-f-b,
    .h-f:focus-within .h-f-pane, .h-f:focus-within .h-f-tile,
    .h-f:focus-within .h-f-b { animation-play-state:paused; }
  }
  /* ...and any hash stops it dead across the block. */
  .h-f-a:target ~ .h-f-panes .h-f-pane,
  .h-f-a:target ~ .h-f-strip .h-f-tile,
  .h-f-a:target ~ * .h-f-b { animation:none; }
  .h-f-a:target ~ .h-f-panes .h-f-pane { opacity:0; visibility:hidden; }
  /* No reset for the tiles. With the animation off a tile's own rule already
     leaves it unmarked, so a reset here only creates a fight with the
     #<rashi>:target rule that marks one -- and it won that fight for
     background and border while losing it for colour, which left every tile
     plain and one of them mysteriously brighter. */
  /* The anchors are the scroll destination, so they sit at the top of the
     block rather than wherever the twelve spans happen to fall. */
  .h-f-a { position:absolute; top:-90px; width:1px; height:1px; }
@keyframes h-f-show { 0%{opacity:0;visibility:visible} 0.4%{opacity:1;visibility:visible} 7.933%{opacity:1;visibility:visible} 8.333%{opacity:0;visibility:hidden} 100%{opacity:0;visibility:hidden} }
@keyframes h-f-mark { 0%,8.333% { border-color:var(--gold); background:var(--gold-bg); } 8.334%,100% { border-color:var(--line); background:transparent; } }
@keyframes h-f-ring { 0%,8.333% { outline-color:var(--gold); } 8.334%,100% { outline-color:transparent; } }
#aries:target ~ .h-f-panes .h-f-p-aries { opacity:1; visibility:visible; }
#aries:target ~ .h-f-strip .h-f-t-aries { border-color:var(--gold); background:var(--gold-bg); color:var(--ink); }
#aries:target ~ * .h-f-b-aries { outline-color:var(--gold); }
#taurus:target ~ .h-f-panes .h-f-p-taurus { opacity:1; visibility:visible; }
#taurus:target ~ .h-f-strip .h-f-t-taurus { border-color:var(--gold); background:var(--gold-bg); color:var(--ink); }
#taurus:target ~ * .h-f-b-taurus { outline-color:var(--gold); }
#gemini:target ~ .h-f-panes .h-f-p-gemini { opacity:1; visibility:visible; }
#gemini:target ~ .h-f-strip .h-f-t-gemini { border-color:var(--gold); background:var(--gold-bg); color:var(--ink); }
#gemini:target ~ * .h-f-b-gemini { outline-color:var(--gold); }
#cancer:target ~ .h-f-panes .h-f-p-cancer { opacity:1; visibility:visible; }
#cancer:target ~ .h-f-strip .h-f-t-cancer { border-color:var(--gold); background:var(--gold-bg); color:var(--ink); }
#cancer:target ~ * .h-f-b-cancer { outline-color:var(--gold); }
#leo:target ~ .h-f-panes .h-f-p-leo { opacity:1; visibility:visible; }
#leo:target ~ .h-f-strip .h-f-t-leo { border-color:var(--gold); background:var(--gold-bg); color:var(--ink); }
#leo:target ~ * .h-f-b-leo { outline-color:var(--gold); }
#virgo:target ~ .h-f-panes .h-f-p-virgo { opacity:1; visibility:visible; }
#virgo:target ~ .h-f-strip .h-f-t-virgo { border-color:var(--gold); background:var(--gold-bg); color:var(--ink); }
#virgo:target ~ * .h-f-b-virgo { outline-color:var(--gold); }
#libra:target ~ .h-f-panes .h-f-p-libra { opacity:1; visibility:visible; }
#libra:target ~ .h-f-strip .h-f-t-libra { border-color:var(--gold); background:var(--gold-bg); color:var(--ink); }
#libra:target ~ * .h-f-b-libra { outline-color:var(--gold); }
#scorpio:target ~ .h-f-panes .h-f-p-scorpio { opacity:1; visibility:visible; }
#scorpio:target ~ .h-f-strip .h-f-t-scorpio { border-color:var(--gold); background:var(--gold-bg); color:var(--ink); }
#scorpio:target ~ * .h-f-b-scorpio { outline-color:var(--gold); }
#sagittarius:target ~ .h-f-panes .h-f-p-sagittarius { opacity:1; visibility:visible; }
#sagittarius:target ~ .h-f-strip .h-f-t-sagittarius { border-color:var(--gold); background:var(--gold-bg); color:var(--ink); }
#sagittarius:target ~ * .h-f-b-sagittarius { outline-color:var(--gold); }
#capricorn:target ~ .h-f-panes .h-f-p-capricorn { opacity:1; visibility:visible; }
#capricorn:target ~ .h-f-strip .h-f-t-capricorn { border-color:var(--gold); background:var(--gold-bg); color:var(--ink); }
#capricorn:target ~ * .h-f-b-capricorn { outline-color:var(--gold); }
#aquarius:target ~ .h-f-panes .h-f-p-aquarius { opacity:1; visibility:visible; }
#aquarius:target ~ .h-f-strip .h-f-t-aquarius { border-color:var(--gold); background:var(--gold-bg); color:var(--ink); }
#aquarius:target ~ * .h-f-b-aquarius { outline-color:var(--gold); }
#pisces:target ~ .h-f-panes .h-f-p-pisces { opacity:1; visibility:visible; }
#pisces:target ~ .h-f-strip .h-f-t-pisces { border-color:var(--gold); background:var(--gold-bg); color:var(--ink); }
#pisces:target ~ * .h-f-b-pisces { outline-color:var(--gold); }