* { 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 welcome gift ── */
  .d-bon { position:fixed; inset:0; z-index:60; display:flex;
           align-items:center; justify-content:center; padding:20px; }
  .d-bon[hidden] { display:none; }
  .d-bon-x { position:absolute; inset:0; background:rgba(0,0,0,.5); }
  .d-bon-c { position:relative; width:100%; max-width:390px; text-align:center;
             padding:26px 26px 20px; border-radius:18px;
             border:1px solid var(--line); background:var(--surface);
             box-shadow:0 18px 50px rgba(0,0,0,.22);
             max-height:calc(100dvh - 40px); overflow-y:auto; }
  .d-bon-g { display:inline-flex; align-items:center; justify-content:center;
             width:62px; height:62px; border-radius:50%;
             background:var(--gold-bg); color:var(--gold-dk);
             margin-bottom:13px; }
  .d-bon-c h2 { font-family:var(--font-serif); font-size:23px; font-weight:600;
                margin:0; color:var(--ink); letter-spacing:-.01em; }
  .d-bon-s { margin:5px 0 16px; font-size:13.5px; color:var(--ink-2); }
  .d-bon-amt { padding:15px; border-radius:var(--r-card);
               background:var(--gold-bg); margin-bottom:16px; }
  .d-bon-amt span { display:block; font-family:var(--font-mono);
                    font-size:10px; letter-spacing:.14em; color:var(--ink-3);
                    text-transform:uppercase; }
  .d-bon-amt b { display:block; margin:5px 0 4px; font-family:var(--font-serif);
                 font-size:38px; font-weight:600; line-height:1;
                 color:var(--gold-dk); }
  .d-bon-amt i { font-style:normal; font-size:12px; color:var(--ink-2); }
  .d-bon-l { list-style:none; margin:0 0 18px; padding:0; display:grid;
             gap:8px; text-align:left; }
  .d-bon-l li { position:relative; padding-left:20px; font-size:13px;
                color:var(--ink-2); }
  .d-bon-l li::before { content:''; position:absolute; left:4px; top:.5em;
                width:6px; height:6px; border-radius:50%;
                background:var(--gold-dk); }
  .d-bon-go { position:relative; width:100%; }
  .d-bon-go .d-bon-lb { transition:opacity .12s linear; }
  .d-bon-go[aria-busy="true"] .d-bon-lb { opacity:0; }
  .d-bon-go[aria-busy="true"] { pointer-events:none; }
  .d-bon-sp { position:absolute; top:50%; left:50%; width:20px; height:20px;
              margin:-10px 0 0 -10px; opacity:0; pointer-events:none; }
  .d-bon-go[aria-busy="true"] .d-bon-sp { opacity:1; }
  .d-bon-no { display:block; width:100%; margin-top:9px; font:inherit;
              font-size:12.5px; padding:7px; border:0; background:none;
              color:var(--ink-3); cursor:pointer; }
  .d-bon-no:hover { color:var(--ink-2); text-decoration:underline; }
  .d-bon-e { margin:9px 0 0; font-size:12.5px; color:var(--bad); }
  .d-bon-e[hidden] { display:none; }

  /* The row for whoever closed it. Money nobody has taken should not be
     invisible because a modal was dismissed once. */
  .d-bonr { display:flex; align-items:center; gap:13px; flex-wrap:wrap;
            padding:13px 16px; margin:0 0 18px;
            border:1px solid var(--gold); border-radius:var(--r-card);
            background:var(--gold-bg); }
  .d-bonr[hidden] { display:none; }
  .d-bonr-g { flex:none; color:var(--gold-dk); display:flex; }
  .d-bonr-t { flex:1 1 210px; min-width:0; font-size:13.5px; color:var(--ink); }
  .d-bonr-t b { font-weight:650; }
  .d-bonr-x { flex:none; font:inherit; font-size:12.5px; border:0;
              background:none; color:var(--ink-3); cursor:pointer;
              padding:6px 8px; }
  .d-bonr-x:hover { color:var(--ink-2); text-decoration:underline; }

  /* ── shell ── */
  .d-shell { display:grid; grid-template-columns:248px minmax(0,1fr);
             min-height:100vh; background:var(--cream); }
  .d-col2 { min-width:0; }
  .d-rail { background:var(--rail); border-right:1px solid var(--line);
            padding:16px 12px 12px; display:flex; flex-direction:column;
            gap:3px; position:sticky; top:0; height:100vh; overflow-y:auto; }
  .d-brand { display:flex; align-items:center; gap:10px; padding:4px 8px 16px;
             color:inherit; text-decoration:none;
             font-family:var(--font-serif); font-size:16px; font-weight:600; }
  .d-grp { margin-top:14px; padding:0 8px 6px; }
  .d-grp b { display:block; font-family:var(--font-mono); font-size:9.5px;
             letter-spacing:.14em; text-transform:uppercase; font-weight:600;
             color:var(--ink-3); }
  .d-grp i { display:block; font-family:var(--font-serif); font-style:italic;
             font-size:11.5px; color:var(--ink-3); }
  .d-nav { display:flex; align-items:center; gap:10px; padding:9px 10px;
           border-radius:var(--r-in); font-size:13.5px; font-weight:500;
           color:var(--ink-2); text-decoration:none; min-height:40px; }
  .d-nav:hover { background:var(--surface); color:var(--ink); }
  .d-nav .c-ico { width:18px; height:18px; flex:none; }
  .d-nl { flex:1; min-width:0; }
  .d-on { background:var(--pill-ink); color:var(--pill-text); font-weight:650; }
  .d-tail { font-family:var(--font-mono); font-size:10px; padding:1px 5px;
            border-radius:5px; background:var(--gold-bg); color:var(--gold-dk); }
  .d-on .d-tail { background:var(--surface); color:var(--ink); }
  .d-acct { position:relative; margin-top:auto; padding-top:12px;
            border-top:1px solid var(--line); }
  .d-acct-c { display:flex; align-items:center; gap:9px; padding:9px;
              border:1px solid var(--line); border-radius:var(--r-in);
              background:var(--surface); text-decoration:none;
              cursor:pointer; }
  .d-acct-c:hover { border-color:var(--gold-lt); }
  .d-acct-c .c-ico { flex:none; color:var(--ink-3);
                     transition:transform .16s; }
  #d-ac-o:checked ~ .d-acct-c .c-ico { transform:rotate(180deg); }
  /* UPWARD. It is the last thing in the rail with the viewport floor under
     it, so a menu hanging below it would open off the bottom of the screen.
     Same checkbox the profile switcher uses rather than the prototype's
     :hover, which on a touch screen is a menu that opens and will not close. */
  .d-ac-m { display:none; position:absolute; left:0; right:0;
            bottom:calc(100% + 7px); z-index:40; padding:6px;
            border-radius:var(--r-card); background:var(--surface);
            border:1px solid var(--line);
            box-shadow:0 18px 44px -18px rgba(0,0,0,.5); }
  #d-ac-o:checked ~ .d-ac-m { display:block; }
  .d-ac-x { display:none; }
  #d-ac-o:checked ~ .d-ac-x { display:block; position:fixed; inset:0;
                              z-index:35; }
  .d-ac-i { display:flex; align-items:center; gap:11px; width:100%;
            padding:9px 10px; border:0; border-radius:var(--r-in);
            background:none; cursor:pointer; text-align:left; font:inherit;
            font-size:13px; color:var(--ink); text-decoration:none; }
  .d-ac-i:hover { background:var(--surface-2); }
  .d-ac-i .c-ico { flex:none; color:var(--ink-3); }
  .d-ac-sep { height:1px; background:var(--line); margin:5px 8px; }
  /* No icon, and the only red thing in the rail: it is the one row here that
     does something rather than going somewhere. */
  .d-ac-out { padding-left:37px; color:var(--bad); font-weight:600; }
  @media (prefers-reduced-motion:reduce) {
    .d-acct-c .c-ico { transition:none; }
  }
  .d-av { width:30px; height:30px; border-radius:50%; flex:none;
          display:grid; place-items:center; font-size:12px; font-weight:700;
          background:var(--gold-solid); color:var(--gold-solid-text); }
  .d-who { min-width:0; flex:1; }
  .d-who b { display:block; font-size:13px; color:var(--ink); }
  .d-who i { display:block; font-style:normal; font-size:11.5px;
             color:var(--ink-3); }

  /* ── top bar ── */
  .d-top { display:flex; align-items:center; gap:12px; padding:11px 22px;
           border-bottom:1px solid var(--line); background:var(--cream);
           position:sticky; top:0; z-index:5; }
  .d-crumb { font-size:13px; color:var(--ink-3); min-width:0; }
  .d-crumb b { color:var(--ink); font-weight:600; }
  .d-tb { margin-left:auto; display:flex; align-items:center; gap:8px; }
  .d-chip { display:flex; align-items:center; gap:6px; font-size:12.5px;
            padding:6px 11px; border:1px solid var(--line);
            border-radius:var(--r-pill); background:var(--surface); }
  .d-chip i { font-style:normal; font-family:var(--font-mono); font-size:9.5px;
              letter-spacing:.05em; padding:1px 5px; border-radius:4px;
              background:var(--gold-bg); color:var(--gold-dk); }
  .d-wallet { display:flex; align-items:center; gap:7px; font-size:13px;
              font-weight:700; padding:6px 7px 6px 12px; text-decoration:none;
              border-radius:var(--r-pill); border:1px solid var(--gold);
              background:var(--gold-bg); color:var(--gold-dk); }
  .d-plus { display:grid; place-items:center; width:18px; height:18px;
            border-radius:50%; background:var(--gold-solid);
            color:var(--gold-solid-text); font-size:12px; line-height:1; }
  .d-burger { display:none; }
  .d-scrim { display:none; }

  /* ── main ── */
  .d-main { padding:26px 22px 56px; max-width:var(--wrap); }
  .d-h1 { font-family:var(--font-serif); font-size:clamp(27px,3.2vw,42px);
          line-height:1.08; letter-spacing:-.015em; font-weight:600;
          margin:0 0 9px; text-wrap:balance; }
  .d-h1 em { font-style:italic; color:var(--gold-dk); }
  .d-sub { display:flex; align-items:baseline; gap:8px; margin:0;
           color:var(--ink-2); font-size:14.5px; line-height:1.6;
           max-width:640px; }
  .d-sub b { color:var(--ink); font-weight:650; }
  /* NOT .d-dot. This CSS used to live inside /home/ where a page owned its
     own class names; moving it into lib/ made every name here global, and
     pages/views/biorhythm.py has been drawing its chart's data points with
     a .d-dot for months. The shell is the newcomer, so the shell renames. */
  /* Prose links. Scoped to <p> on purpose: every signed-in page puts the
     odd link in a caption or an empty-state sentence, and without this they
     render browser-default blue in the middle of a gold page. Anchors that
     are structure rather than prose — rail items, rashi tiles, roster cards,
     the profile menu — are never inside a paragraph, so they keep their own
     styling and this cannot reach them. */
  .d-main p a { color:var(--gold-dk); text-underline-offset:2px; }
  .d-main p a:hover { color:var(--gold); }

  .d-live { width:7px; height:7px; border-radius:50%; background:var(--good);
           flex:none; }
  .d-mk { display:flex; align-items:baseline; gap:10px; margin:32px 0 13px; }
  .d-mk0 { margin:0 0 13px; }
  .d-mkn { font-family:var(--font-mono); font-size:12px; color:var(--gold-dk); }
  /* An h2/h3 now, so the browser's own heading margin and 1.5em size have
     to go — the row is a flex baseline and a UA margin would shove it. */
  .d-mkt { font-family:var(--font-mono); font-size:12px; letter-spacing:.13em;
           text-transform:uppercase; font-weight:600; margin:0;
           color:inherit; }
  .d-mkd { font-family:var(--font-serif); font-style:italic; font-size:13px;
           color:var(--ink-3); }
  .d-card { background:var(--surface); border:1px solid var(--line);
            border-radius:var(--r-card); padding:20px; }
  .d-row { display:grid; gap:15px; }
  /* THE LEFT CARD SETS THE HEIGHT AND BEST HOURS FITS ITSELF INTO IT.
     Stretching the pair to their tallest is not the same thing: the tallest
     is whichever has more to say, so the void simply moves to the other
     column — which is exactly what happened when Best hours grew from three
     rows to seven. The slot is an empty positioned box, so it contributes
     nothing to the row; the card fills the slot absolutely and gives up
     rows to its scroller instead of giving up its shape.

     min-height so the pair cannot collapse when the left card is in one of
     its short states — no birth details, or a chart that would not load. */
  @media (min-width:980px) {
    .d-2 { grid-template-columns:1.5fr 1fr; }
    .d-hslot { position:relative; min-height:280px; }
    .d-hslot > .d-hrs { position:absolute; inset:0; }
  }
  /* On one column there is nothing to match, so the card is its own height
     and the whole list is simply there. */
  @media (max-width:979.98px) { .d-hslot { display:contents; } }
  .d-read { font-size:14.5px; line-height:1.65; color:var(--ink-2); margin:0; }
  .d-read b { color:var(--ink); font-weight:650; }

  /* ── profile switcher ── */
  .d-pf { position:relative; }
  .d-pf-t { display:flex; align-items:center; gap:9px; cursor:pointer;
            padding:5px 9px 5px 6px; border:1px solid var(--line);
            border-radius:var(--r-pill); background:var(--surface);
            max-width:230px; }
  .d-pf-t:hover { border-color:var(--gold-lt); }
  .d-pf-n { min-width:0; text-align:left; }
  .d-pf-n b { display:block; font-size:12.5px; font-weight:650; color:var(--ink);
              white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
  .d-pf-n i { display:block; font-style:normal; font-family:var(--font-mono);
              font-size:10px; color:var(--ink-3); }
  .d-pf-t .c-ico { flex:none; color:var(--ink-3); }
  .d-pf-m { display:none; position:absolute; top:calc(100% + 7px); left:0;
            z-index:40; min-width:250px; padding:6px; border-radius:var(--r-card);
            background:var(--surface); border:1px solid var(--line);
            box-shadow:0 18px 44px -18px rgba(0,0,0,.5); }
  /* The input sits INSIDE .d-top, so the menu and the catcher are its
     siblings there — not descendants of .d-shell, which is what the
     first version reached for and never matched. */
  #d-pf-o:checked ~ .d-pf .d-pf-m { display:block; }
  /* A full-screen catcher so the next click anywhere closes it — without one
     the menu stays open behind whatever you clicked next. */
  .d-pf-x { display:none; }
  #d-pf-o:checked ~ .d-pf-x { display:block; position:fixed;
            inset:0; z-index:35; }
  .d-pf-i { display:flex; align-items:center; gap:9px; width:100%;
            padding:8px 9px; border:0; border-radius:var(--r-in);
            background:none; cursor:pointer; text-align:left;
            text-decoration:none; font:inherit; }
  .d-pf-i:hover { background:var(--surface-2); }
  .d-pf-on { background:var(--gold-bg); }
  .d-pf-on .d-pf-n b { color:var(--gold-dk); }
  .d-pf-add { border-top:1px solid var(--line-soft); border-radius:0 0 9px 9px;
              margin-top:4px; padding-top:11px; }
  .d-pf-add .d-av { background:var(--surface-2); color:var(--ink-2); }
  /* max-width:150px used to sit here too and had never once applied: the
     phone block further down sets max-width:none at the same specificity and
     later in the file, so it won every time. The date of birth is what this
     rule is actually for. */
  @media (max-width:560px) { .d-pf-n i { display:none; } }

  /* ── waiting ── */
  /* A grey block the shape of the answer, not a spinner in the middle of an
     empty page: the layout is already correct, so nothing jumps when the real
     values land. */
  /* A SWEEP, NOT A PULSE. The old rule faded --line-soft in and out, and
     --line-soft sits 1.07:1 against the card it lies on in dark — so the bar
     was invisible at its brightest and more invisible at its dimmest, which
     reads as a page that has finished loading and has nothing to say. The
     band travelling left to right is the part that says "still coming"; the
     bar underneath it is what says "and it will be about this big". */
  .d-sk { display:block; min-height:1em; width:100%; border-radius:6px;
          /* The &nbsp; that gives the span its height must not be seen. */
          color:transparent; user-select:none;
          background-color:var(--sk);
          background-image:linear-gradient(100deg, rgba(0,0,0,0) 34%,
                           var(--sk-hi) 50%, rgba(0,0,0,0) 66%);
          background-size:280% 100%; background-repeat:no-repeat;
          animation:d-sheen 1.45s linear infinite; }
  .d-sk + .d-sk { margin-top:7px; }
  @keyframes d-sheen { from { background-position:170% 0; }
                       to { background-position:-70% 0; } }
  /* Stationary, not still-but-invisible: reduced motion keeps the bar and
     drops only the travel. */
  @media (prefers-reduced-motion:reduce) {
    .d-sk { animation:none; background-image:none; }
  }

  /* IN A FLEX PARENT A SKELETON COLLAPSES. .d-sub is a flex row, so a
     `<span class="d-sk">&nbsp;</span>` shrink-wrapped its one space and came
     out 3px wide — five screens opened with a crumb of grey under the
     headline where a line of type was about to appear. Width here, and a
     shorter one for the sub, because a full-column bar promises a paragraph
     the line will not deliver. */
  .d-sub .d-sk { flex:0 0 auto; width:min(26ch, 100%); }

  /* Seen only when a live reading could not be fetched and the page is
     showing what was built into it. It is a caveat on real data, not an
     error — amber, in the subtitle, not a banner across the page. It lives
     here because every signed-in page that reads a dated snapshot needs the
     same sentence, and three copies would drift. */
  .d-stale { color:var(--mid); font-size:13px; }
  .d-stale b { color:var(--mid); font-weight:650; }
  /* Same collapse, in the top bar. The profile chip and the wallet pill both
     size to their contents, so a width:100% child resolves against nothing —
     3px and 13px respectively. These are the widths a name and a balance
     actually take, so the chrome does not resize when they arrive. */
  .d-pf-n .d-sk { width:9ch; }
  .d-wallet .d-sk { width:4.5ch; }

  /* ── the rail becomes a drawer ── */
  @media (max-width:900px) {
    .d-shell { grid-template-columns:minmax(0,1fr); }
    .d-burger { display:grid; place-items:center; width:44px; height:44px;
                flex:none; cursor:pointer; border:1px solid var(--line);
                border-radius:10px; background:var(--surface);
                color:var(--ink-2); }
    .d-rail { position:fixed; top:0; left:0; bottom:0; width:264px; z-index:40;
              transform:translateX(-100%); transition:transform .2s ease; }
    #d-menu:checked ~ .d-shell .d-rail { transform:none; }
    #d-menu:checked ~ .d-shell .d-scrim { display:block; position:fixed;
              inset:0; z-index:30; background:rgba(0,0,0,.45); }
    .d-main { padding:20px 16px 48px; }
    .d-top { padding:10px 16px; }
  }
  /* ── ONE ROW ON A PHONE ──
     The bar holds a burger, the profile chip, a breadcrumb, a date, a wallet
     and the theme toggle: 473px of controls in 358px at 390. Letting it wrap
     kept everything on screen and made the header 116px of a 844px phone —
     two rows, the second one shoved to the right by margin-left:auto with
     124px of dead space beside it. It read as a header that had come apart,
     not one that had been designed.
     Two things go instead of wrapping. The breadcrumb, because it names the
     page a reader is looking at. And the date chip, because it is the only
     thing on the bar that is not a control — every page that turns on the
     date says so in its own heading, and what a phone needs up here is the
     way out (burger), who this is cast for (profile), and the money.
     What is left is 191px of fixed controls, so the profile takes the rest
     and truncates. That is why .d-pf gets min-width:0: it is a flex item, its
     min-width defaults to its content, and without this the name would push
     the wallet off the edge rather than ellipsing — the same trap that gave
     the roster card a 326px floor. */
  @media (max-width:620px) {
    .d-top { flex-wrap:nowrap; gap:8px; }
    .d-crumb { display:none; }
    .d-chip { display:none; }
    .d-tb { margin-left:auto; flex:none; gap:8px; }
    /* FITS ITS NAME, and shrinks only when the row runs out. flex defaults to
       0 1 auto, so the chip is as wide as its contents and no wider; the
       max-width is the ceiling a long name truncates at, and min-width:0 is
       what lets it give way at 320 rather than widening the page.
       It used to be flex:1 1 auto with width:100%, which stretched it across
       whatever the bar had spare — a chip holding "Rohit Singh" sat 167px
       wide with the name floating in the left third of it. */
    .d-pf { min-width:0; }
    .d-pf-t { max-width:190px; }
  }
  @media (prefers-reduced-motion:reduce) { .d-rail { transition:none; } }
  /* ── 11px IS THE FLOOR ON A PHONE, EVERYWHERE INSIDE THE SHELL ──
     Thirty-six rules across four files set text between 8.5px and 10.5px on
     these pages: axis labels, table headings, row labels, the segment names
     inside the dasha bars, date pills, the notification-time caption. Each was
     a fair call at 1280px, where the same component has half again the room.
     On a phone they are collectively most of the words on the screen, and
     8.5px is not a size anybody reads on a bus.
     ONE BLOCK, NOT THIRTY-SIX EDITS, because scattering the same override
     through four files is how the thirty-seventh gets written at 9px and
     nobody notices. .d-main prefixes every selector because page CSS is
     emitted AFTER the shell's, so this needs specificity rather than position
     to win — and from here it wins wherever the base rule lives.
     Anything that genuinely cannot hold 11px gets room made for it instead of
     being allowed back under the floor.
     THREE OF THESE WERE INVISIBLE LOCALLY. .d-fx (the dashboard's tithi /
     nakshatra / yoga / karana row) and .c-tl-now (the "now" marker on the day
     timeline) only render when there is live panchang data, and a local build
     runs with COSMIQE_STALE_OK=1. They were found by running the check
     against production after deploying, which is now the only way to see
     them — worth remembering before trusting a local pass on these pages. */
  @media (max-width:640px) {
    .d-main .c-lb-i i,
              .d-main .c-pf-l,
              .d-main .c-scl-l,
              .d-main .c-scl-t,
              .d-main .c-scl-tag,
              .d-main .c-scl-v,
              .d-main .c-table th,
              .d-main .c-tl-c b,
              .d-main .c-tl-lbl,
              .d-main .c-tl-night i,
              .d-main .c-tl-now i,
              .d-main .d-fx s,
              .d-main .d-fx i,
              .d-main .c-tl-t i,
              .d-main .d-flc s,
              .d-main .d-lk s,
              .d-main .d-ovl,
              .d-main .d-rate,
              .d-main .d-scl,
              .d-main .dl-lab i,
              .d-main .dl-lab s,
              .d-main .dl-life-t,
              .d-main .dl-ls b,
              .d-main .dl-ls i,
              .d-main .dl-seg,
              .d-main .dl-sg-h s,
              .d-main .dl-sg-r s,
              /* .dl-tbl th was here. The dasha table stacks on a phone and
                 hides its heads, so there is no width at which this rendered
                 — see the block at the end of dasha_app.py. */
              .d-main .h-dl-r .h-dl-pc,
              .d-main .h-f-b u,
              .d-main .h-f-bn,
              .d-main .h-f-hint,
              .d-main .h-f-l,
              .d-main .h-f-luck-t,
              .d-main .h-f-tile i,
              .d-main .h-trend,
              /* ── THE THREE THAT MIX THEIR OWN TEXT WITH A CHILD ──
                 Missed for a reason in the checks rather than in the page:
                 shell-mobile.mjs only measured elements with no element
                 children at all, so anything shaped like
                 <text>Finance<tspan>87</tspan></text> or
                 <span><svg/>Tithi<i>…</i></span> was never looked at, on five
                 horoscope pages and panchang. The eyebrow is 10.5, the anga
                 heading 10, and the radar label 8.5 in an SVG that renders it
                 at 9.0 on a 320 screen. */
              .d-main .h-f-eyebrow,
              .d-main .h-radar-l,
              .d-main .p-anga-h,
              .d-main .p-ch-h,
              .d-main .p-per-h,
              .d-main .p-sum i,
              .d-main .st-pill-off i { font-size:11px; }
  }

  /* Everything on the kundli is namespaced j-. The shell owns c-, h-, l-, s-
     and sg-; restyling a bare class one of those owns is what checks/clash.py
     exists to catch, and it has caught it twice. */

  /* The example caption lives under the form in the hero — see the aside in
     pages/kundli.py. Nothing here styles it. */

  /* ── the tabs ───────────────────────────────────────────────── */
  .j-tabs { margin-top:24px; }
  /* Zero-height scroll anchors, one per tab, sitting immediately above the
     strip. :target lands HERE rather than on a panel — target a panel and the
     browser scrolls that panel's top edge to the top of the viewport, which
     throws the strip you just clicked off the screen every single time. The
     margin is the sticky site header plus a little air. */
  .j-tt { display:block; height:0; scroll-margin-top:82px; }
  /* ── z-index 4, AND THE 40 IT WAS IS WHY THE DRAWER LOST ──
     .d-rail is the phone drawer at z-index:40 and its scrim is 30. This
     strip was 40 as well, and equal z-index is settled by DOM order — the
     rail is written before the column that holds this — so the tabs painted
     straight over an open drawer.
     4, not 40: the only thing this has to sit above is the page scrolling
     under it, and it has to sit UNDER .d-top (5), which it tucks beneath at
     top:60px. Above 5 it would cover the site header on the way past. */
  .j-tn { position:sticky; top:60px; z-index:4; display:flex; gap:8px;
    margin:0 0 8px; padding:10px 0; overflow-x:auto; overflow-y:hidden;
    background:var(--cream); border-bottom:1px solid var(--line);
    scrollbar-width:none; }
  .j-tn::-webkit-scrollbar { display:none; }
  .j-tn a { flex:none; display:flex; flex-direction:column;
    justify-content:center; gap:1px; min-height:44px; padding:6px 15px;
    text-decoration:none; border:1px solid var(--line);
    border-radius:var(--r-pill); background:var(--surface); }
  .j-tn a > b { font-size:13.5px; font-weight:650; color:var(--ink-2);
    white-space:nowrap; }
  .j-tn a > i { font-style:normal; font-size:11px; color:var(--ink-3);
    white-space:nowrap; }
  .j-tn a:hover { border-color:var(--gold-lt); }
  /* Which tab is open by default, and which link is lit for it, are generated
     from DEFAULT_TAB — see tab_css(). Nothing here names a tab. */
  .j-tp { display:none; }
  /* The panel's own h2. The tab link above already names it and the panel
     opens with a visible section head of its own, so a third printing of the
     same words would be noise — but the heading has to EXIST for the document
     outline and for aria-labelledby to point at something. */
  .j-tp-h { position:absolute; width:1px; height:1px; margin:-1px;
    overflow:hidden; clip-path:inset(50%); white-space:nowrap; }
  .j-gap { height:8px; }
  @media (max-width:559px) {
    /* One line on a phone. The sub-label is a nicety and the strip has to
       stay under 44px of a 640px screen. */
    .j-tn a > i { display:none; }
    .j-tn a { padding:9px 14px; }
  }
  /* PRINTING. Five tabs would otherwise print as one, and a kundli somebody
     prints for their pandit ji with four fifths missing is worse than no print
     stylesheet at all. Every panel, and every one of the twenty-three vargas,
     because a printed janam kundli traditionally carries them. */
  @media print {
    .j-tn { display:none; }
    .j-tt { display:none; }
    .j-tp { display:block !important; }
    .j-cp { display:block !important; break-inside:avoid; }
    .j-ctabs { display:none; }
    .j-tabs { margin-top:0; }
  }
  /* An explainer, not body copy. At 14px/1.75 in --ink-2 over 68ch these read
     as the point of the section; they are the caption under the point, and the
     thing they caption is the table or the drawing below them. */
  .j-note { max-width:62ch; margin:-8px 0 18px; font-size:13px;
    line-height:1.7; color:var(--ink-3); }
  .j-note b { color:var(--ink-2); font-weight:650; }
  .j-sub { display:block; font-style:normal; font-size:11.5px;
    color:var(--ink-3); margin-top:2px; }

  /* ── the lagna band ─────────────────────────────────────────── */
  .j-lb { padding:22px 24px 18px; border:1px solid var(--gold-lt);
    border-radius:var(--r-card); background:var(--gold-bg); margin-bottom:20px; }
  .j-lb-top { display:grid; gap:20px 28px; grid-template-columns:1fr; }
  @media (min-width:880px) {
    /* The two that lead take more room than the two that follow. */
    /* start, not center. Centred, the shorter pair floats against the taller
       one and the four eyebrow labels sit on two different lines 7px apart —
       close enough to read as a mistake rather than as a decision. */
    .j-lb-top { grid-template-columns:minmax(0,1.15fr) minmax(0,1fr);
      align-items:start; }
  }
  .j-lb-lead, .j-lb-rest { display:grid; gap:18px 22px;
    grid-template-columns:repeat(2,minmax(0,1fr)); min-width:0; }
  .j-lb-l, .j-lb-s { min-width:0; }
  .j-lb-l > b { display:block; font-family:var(--font-serif); font-size:30px;
    font-weight:600; line-height:1.12; color:var(--gold-dk); margin:5px 0 3px; }
  /* Half the size and in the ink ramp, not in gold. Four values in 26px gold
     was four things shouting at the same volume. */
  .j-lb-s > b { display:block; font-family:var(--font-serif); font-size:19px;
    font-weight:600; line-height:1.2; color:var(--ink); margin:4px 0 2px; }
  .j-lb-l > i, .j-lb-s > i { display:block; font-style:normal; font-size:12.5px;
    color:var(--ink-2); }
  /* The settings, as four facts rather than one mono sentence. Not hidden:
     the section under this page argues that two sites disagree because they
     pick different ones. */
  .j-lb-f { display:flex; flex-wrap:wrap; gap:8px; margin-top:18px;
    padding-top:16px; border-top:1px solid var(--gold-lt); }
  .j-lb-f > span { display:flex; align-items:baseline; gap:6px;
    padding:5px 11px; border-radius:var(--r-pill);
    border:1px solid var(--gold-lt); background:var(--surface);
    font-size:12px; color:var(--ink); }
  .j-lb-f i { font-style:normal; font-family:var(--font-mono); font-size:9.5px;
    letter-spacing:.11em; text-transform:uppercase; color:var(--ink-3); }
  @media (max-width:520px) {
    /* TWO ACROSS, NOT ONE. This flattened both pairs to a single column, so
       the four facts a kundli opens with — lagna, rashi, nakshatra, surya —
       were four full-width rows and the section was a column of headings
       before the chart itself. They stay in their pairs: the two that lead
       above the two that follow, two on each line. The lead type comes down
       again to fit a half-width column, and the sub lines wrap rather than
       clip, since a nakshatra plus its pada and lord is longer than a sign
       name. */
    .j-lb-lead, .j-lb-rest { gap:14px 16px; }
    .j-lb-l > b { font-size:21px; }
    .j-lb-s > b { font-size:16px; }
    .j-lb-l > i, .j-lb-s > i { overflow-wrap:break-word; }
  }
  /* Below 360 there is not room for two 26-character sub lines side by side,
     and the pair goes back to one column — the same floor the report shelf
     uses, and for the same reason. */
  @media (max-width:359px) {
    .j-lb-lead, .j-lb-rest { grid-template-columns:1fr; }
  }

  /* ── the two main charts ────────────────────────────────────── */
  .j-ch-two { display:grid; gap:18px; grid-template-columns:1fr;
    align-items:stretch; }
  @media (min-width:820px) { .j-ch-two { grid-template-columns:1fr 1fr; } }
  .j-ch { min-width:0; margin:0; display:flex; flex-direction:column;
    gap:14px; padding:20px 22px 22px; border:1px solid var(--line);
    border-radius:var(--r-card); background:var(--surface); }
  .j-ch figcaption > b { display:block; font-family:var(--font-serif);
    font-size:21px; font-weight:600; color:var(--ink); margin:5px 0 2px; }
  .j-ch figcaption > i { display:block; font-style:normal; font-size:13px;
    color:var(--gold-dk); font-weight:600; }
  .j-ch .c-nc { max-width:none; align-self:center; }
  .j-ch > p { margin:auto 0 0; font-size:13px; line-height:1.65;
    color:var(--ink-2); }

  /* ── legend ─────────────────────────────────────────────────── */
  .j-leg { display:flex; flex-wrap:wrap; gap:8px 18px; align-items:center;
    margin-top:18px; padding:14px 16px; border:1px solid var(--line-soft);
    border-radius:var(--r-in); background:var(--surface-2); }
  .j-leg > span { display:flex; align-items:baseline; gap:6px;
    font-size:12.5px; color:var(--ink-2); }
  .j-leg > span > b { font-family:var(--font-mono); font-size:11px;
    font-weight:700; color:var(--ink); }
  .j-leg-n { flex-basis:100%; display:block; font-size:12.5px;
    line-height:1.7; color:var(--ink-3); }

  /* ── tables ─────────────────────────────────────────────────── */
  .j-tbl { border:1px solid var(--line); border-radius:var(--r-card);
    background:var(--surface); overflow:auto; }
  .j-tbl table { width:100%; border-collapse:collapse; font-size:13px;
    min-width:640px; }
  /* Eight columns carrying eleven fields need the room; below this the
     wrapper scrolls sideways, which is what it is for. */
  .j-tbl-pl table { min-width:900px; }
  /* The header row is NOT sticky, and the rule that claimed it was is gone.
     .j-tbl is overflow:auto for the sideways scroll a nine-column table needs
     on a phone, and an ancestor with overflow resolves sticky against ITSELF
     rather than the viewport — so `top:0` pinned the row to the top of a box
     that never scrolls vertically, which is to say it did nothing at all. It
     measured 406px above the fold. .q-tbl on the calculators gets away with
     the same rule because it also caps max-height, so its box really is a
     scrollport; these tables are nine and twelve rows and do not want to be a
     scrollbox inside a page. */
  .j-tbl thead th { background:var(--surface);
    text-align:left; font-family:var(--font-mono); font-size:9.5px;
    letter-spacing:.11em; text-transform:uppercase; color:var(--ink-3);
    font-weight:400; padding:12px 14px; border-bottom:1px solid var(--line);
    white-space:nowrap; }
  .j-tbl tbody th { text-align:left; font-weight:600; color:var(--ink);
    padding:11px 14px; border-bottom:1px solid var(--line-soft);
    white-space:nowrap; }
  .j-tbl tbody th > b { display:block; font-weight:650; }
  .j-tbl tbody th > i { display:block; font-style:normal; font-size:11.5px;
    font-weight:400; color:var(--ink-3); margin-top:1px; }
  .j-tbl td { padding:11px 14px; border-bottom:1px solid var(--line-soft);
    color:var(--ink-2); vertical-align:top; }
  .j-tbl tbody tr:last-child > * { border-bottom:0; }
  .j-num { font-family:var(--font-mono); font-variant-numeric:tabular-nums;
    white-space:nowrap; }
  .j-mean { color:var(--ink-3); font-size:12.5px; line-height:1.55;
    min-width:190px; }
  .j-tbl-sm table { min-width:260px; }
  /* The row that is yours — the first bhava, the running mahadasha. Gold
     ground, and the left rule so it survives a horizontal scroll that puts
     the tinted cells off-screen. */
  .j-mine > * { background:var(--gold-bg); }
  .j-mine > :first-child { box-shadow:inset 3px 0 0 var(--gold); }

  .j-g { display:inline-block; padding:2px 7px; margin:0 4px 4px 0;
    border-radius:var(--r-pill); border:1px solid var(--line);
    background:var(--surface-2); font-family:var(--font-mono); font-size:11px;
    color:var(--ink); }

  /* Dignity. The one place colour carries meaning on this page, and it is the
     product's own three semantic tokens rather than a fourth palette. Each
     pairs its own -bg, which is what makes them clear 4.5:1 in both themes. */
  .j-dig { display:inline-block; padding:2px 9px; border-radius:var(--r-pill);
    font-size:11.5px; font-weight:600; white-space:nowrap;
    background:var(--surface-2); color:var(--ink-2); }
  .j-dig-good { background:var(--good-bg); color:var(--good); }
  .j-dig-mid { background:var(--mid-bg); color:var(--mid); }
  .j-dig-bad { background:var(--bad-bg); color:var(--bad); }

  .j-st { display:inline-block; padding:2px 8px; border-radius:var(--r-pill);
    border:1px solid var(--line); background:var(--surface-2);
    font-size:11px; font-style:normal; color:var(--ink-2); white-space:nowrap; }
  .j-st-w { border-color:transparent; background:var(--mid-bg);
    color:var(--mid); }
  .j-st-good { border-color:transparent; background:var(--good-bg);
    color:var(--good); }
  .j-st-mid { border-color:transparent; background:var(--mid-bg);
    color:var(--mid); }
  .j-st-r { border-color:var(--gold); background:var(--gold-bg);
    color:var(--gold-dk); font-weight:600; }

  /* ── the graha table ────────────────────────────────────────── */
  /* The dignity spine. Six columns of flat text told you Venus was
     Moolatrikona and Jupiter was in an enemy rashi in the same weight as
     everything else; a 3px rule down the left of the row says it before you
     have read a word, and the chip in the last column says which. This is the
     only colour in the table and it is the product's own three semantic
     tokens, not a fourth palette. */
     Each tone rule is written at .j-tbl-pl depth on purpose: `.j-pl-good > th`
     alone is (0,1,1) against the base's (0,2,2), so the base won and all nine
     spines painted --line. The spine was invisible in the first build. */
  .j-tbl-pl tbody th { box-shadow:inset 3px 0 0 var(--line); }
  .j-tbl-pl .j-pl-good > th { box-shadow:inset 3px 0 0 var(--good); }
  .j-tbl-pl .j-pl-mid > th { box-shadow:inset 3px 0 0 var(--mid); }
  .j-tbl-pl .j-pl-bad > th { box-shadow:inset 3px 0 0 var(--bad); }
  .j-tbl-pl tbody tr:nth-child(even) > * { background:var(--surface-2); }
  .j-tbl-pl td > b { display:block; font-weight:600; color:var(--ink); }
  .j-tbl-pl td > b em { font-style:normal; font-weight:400; color:var(--ink-3); }
  /* The drawing and the name, side by side. iconset draws the nine rather
     than setting them in a font — see the note above GLYPH in lib/iconset.py
     for why the Unicode graha block is not trustworthy on Android. */
  .j-tbl-pl tbody th { display:flex; align-items:center; gap:9px; }
  .j-pl-i { display:grid; place-items:center; width:26px; height:26px;
    flex:none; border-radius:50%; border:1px solid var(--line);
    background:var(--surface-2); color:var(--ink-2); }
  /* The name and its Sanskrit, stacked. .j-tbl tbody th > b sets display:block
     but these are grandchildren of the th now that the drawing shares the
     cell, so the child combinator stopped matching and the two ran together
     as "SunSurya". */
  .j-pl-n { min-width:0; }
  .j-pl-n > b { display:block; font-weight:650; color:var(--ink); }
  .j-pl-n > i { display:block; font-style:normal; font-size:11.5px;
    font-weight:400; color:var(--ink-3); margin-top:1px; }
  /* The bhava is the answer to "where is my Saturn", so it is a disc rather
     than a digit in a column of digits. */
  .j-hn { display:grid; place-items:center; width:30px; height:30px;
    border-radius:50%; border:1px solid var(--gold-lt);
    background:var(--gold-bg); font-family:var(--font-mono); font-size:13px;
    font-weight:700; color:var(--gold-dk); }
  .j-key { display:flex; flex-wrap:wrap; gap:8px 18px; margin-top:12px; }
  .j-key > span { display:flex; align-items:center; gap:7px; font-size:12px;
    color:var(--ink-3); }
  .j-key i { width:14px; height:3px; border-radius:2px; flex:none; }
  .j-key-good { background:var(--good); }
  .j-key-mid { background:var(--mid); }
  .j-key-bad { background:var(--bad); }
  .j-key-na { background:var(--line); }

  /* ── the twelve bhavas ──────────────────────────────────────── */
  .j-bh-g12 { display:grid; gap:12px; grid-template-columns:1fr; }
  @media (min-width:560px) {
    .j-bh-g12 { grid-template-columns:repeat(2,minmax(0,1fr)); }
  }
  @media (min-width:900px) {
    .j-bh-g12 { grid-template-columns:repeat(3,minmax(0,1fr)); }
  }
  @media (min-width:1120px) {
    .j-bh-g12 { grid-template-columns:repeat(4,minmax(0,1fr)); }
  }
  .j-bh { position:relative; overflow:hidden; min-width:0; padding:16px 18px 15px;
    border:1px solid var(--line); border-radius:var(--r-card);
    background:var(--surface); }
  /* The bhava number, large and set back. It is the thing the eye lands on and
     it is also the one value on the card that never needs reading twice. */
  .j-bh-n { position:absolute; top:2px; right:12px; font-family:var(--font-serif);
    font-size:56px; font-weight:600; line-height:1; color:var(--line);
    pointer-events:none; }
  .j-bh > b { position:relative; display:block; font-family:var(--font-serif);
    font-size:20px; font-weight:600; color:var(--ink); margin:5px 0 1px; }
  .j-bh > i { position:relative; display:block; font-style:normal;
    font-size:12px; color:var(--ink-3); }
  .j-bh-g { position:relative; display:flex; flex-wrap:wrap; gap:5px;
    margin:12px 0 0; min-height:24px; }
  .j-bh-g em { font-style:normal; font-size:12px; color:var(--ink-3); }
  .j-bh > p { position:relative; margin:11px 0 0; padding-top:10px;
    border-top:1px solid var(--line-soft); font-size:12.5px; line-height:1.55;
    color:var(--ink-2); }
  /* The lagna. Everything is counted from it, so it is the one card that is
     not on --surface. */
  .j-bh-on { border-color:var(--gold-lt); background:var(--gold-bg); }
  .j-bh-on .j-bh-n { color:var(--gold-lt); }
  .j-bh-on > b { color:var(--gold-dk); }
  /* A bhava with nothing in it is not a defect, and it should not read as a
     card that failed to load — it recedes rather than showing an em dash. */
  .j-bh-mt { background:var(--surface-2); }

  /* ── the day you were born ──────────────────────────────────── */
  .j-dy { margin:0 0 20px; }
  .j-dy-b0 { position:relative; height:40px; border-radius:var(--r-sm);
    background:var(--surface-2); border:1px solid var(--line);
    overflow:visible; }
  /* --gold-lt, not --gold-bg. The first version drew daylight in --gold-bg on
     a --surface-2 track, which measures 1.02:1 against it — the band was
     geometrically correct and completely invisible, and all a reader could see
     were the two hairline borders. A band nobody can see is not a band. */
  .j-dy-day { position:absolute; top:0; bottom:0; background:var(--gold-lt); }
  /* Rahu kaal is hatched rather than filled: it is a window to avoid, not a
     value, and a solid band the same weight as daylight would read as another
     phase of the day. */
  .j-dy-rk { position:absolute; top:0; bottom:0;
    background:repeating-linear-gradient(135deg,
      var(--mid) 0 3px, transparent 3px 7px);
    border-left:1px solid var(--mid); border-right:1px solid var(--mid); }
  .j-dy-b { position:absolute; top:-5px; bottom:-5px; width:0; }
  .j-dy-b > b { position:absolute; top:0; bottom:0; left:-1px; width:2px;
    background:var(--ink); }
  .j-dy-b i { position:absolute; left:50%; top:100%; transform:translateX(-50%);
    margin-top:5px; white-space:nowrap; font-style:normal;
    font-family:var(--font-mono); font-size:11px; font-weight:700;
    color:var(--ink); }
  .j-dy-t { position:relative; height:16px; margin-top:22px; }
  .j-dy-t > span { position:absolute; transform:translateX(-50%);
    font-size:11px; color:var(--ink-3); white-space:nowrap; }
  .j-dy-k { display:flex; flex-wrap:wrap; gap:6px 16px; margin-top:10px; }
  .j-dy-k > span { display:flex; align-items:center; gap:6px; font-size:11.5px;
    color:var(--ink-3); }
  .j-dy-k i { width:14px; height:10px; border-radius:2px; flex:none;
    border:1px solid var(--line); }
  .j-dy-kd { background:var(--gold-lt); border-color:var(--gold-lt); }
  .j-dy-kr { border-color:var(--mid); background:repeating-linear-gradient(
      135deg, var(--mid) 0 3px, transparent 3px 7px); }
  .j-dy-kn { background:var(--surface-2); }

  /* ── panchang / avakhada ────────────────────────────────────── */
  .j-two { display:grid; gap:18px; grid-template-columns:1fr;
    align-items:stretch; }
  @media (min-width:880px) { .j-two { grid-template-columns:1fr 1fr; } }
  .j-card { min-width:0; padding:20px 22px; border:1px solid var(--line);
    border-radius:var(--r-card); background:var(--surface); }
  .j-card-h { margin-bottom:16px; padding-bottom:14px;
    border-bottom:1px solid var(--line-soft); }
  .j-card-h > b { display:block; font-family:var(--font-serif); font-size:19px;
    font-weight:600; color:var(--ink); }
  .j-card-h > i { display:block; font-style:normal; font-size:13px;
    line-height:1.6; color:var(--ink-3); margin-top:4px; }
  .j-kvs { display:grid; gap:14px 18px;
    grid-template-columns:repeat(auto-fit,minmax(118px,1fr)); }
  .j-kv { min-width:0; }
  .j-kv > b { display:block; font-size:14.5px; font-weight:600;
    color:var(--ink); margin-top:3px; }

  /* ── the chart gallery ──────────────────────────────────────── */
  .j-gal { display:grid; gap:20px; }
  .j-ctg + .j-ctg { margin-top:14px; }
  .j-cts { display:flex; flex-wrap:wrap; gap:8px; margin-top:8px; }
  .j-ct { display:flex; flex-direction:column; gap:1px; min-width:62px;
    padding:8px 11px; border:1px solid var(--line); border-radius:var(--r-in);
    background:var(--surface); cursor:pointer; }
  .j-ct > b { font-family:var(--font-mono); font-size:12px; font-weight:700;
    color:var(--ink); }
  .j-ct > i { font-style:normal; font-size:10.5px; color:var(--ink-3); }
  .j-ct:hover { border-color:var(--gold-lt); }
  /* The checked state is generated by ui.selectable_css — it sets the gold
     border and ground on label[for=...] for all twenty-three at once. */
  /* All twenty-three stacked in one grid cell, only the checked one shown —
     so the section's height does not jump as you page through them. */
  .j-cpanels { display:grid; }
  .j-cp { display:none; grid-area:1/1; }
  .j-cp-in { display:grid; gap:24px; align-items:center;
    grid-template-columns:1fr; padding:22px; border:1px solid var(--line);
    border-radius:var(--r-card); background:var(--surface); }
  @media (min-width:820px) {
    /* Chart first and fixed; the reading takes whatever is left. */
    .j-cp-in { grid-template-columns:minmax(0,360px) minmax(0,1fr);
      align-items:start; }
  }
  .j-cp-i > b { display:block; font-family:var(--font-serif); font-size:23px;
    font-weight:600; color:var(--ink); margin:5px 0 8px; }
  .j-cp-i > p { margin:0; font-size:14px; line-height:1.7; color:var(--ink-2);
    max-width:52ch; }
  .j-cp-d { margin:0; display:flex; flex-direction:column; gap:12px;
    align-items:center; }
  .j-cp-d .c-nc { max-width:360px; }
  .j-cp-d figcaption { display:flex; flex-wrap:wrap; justify-content:center;
    gap:6px 18px; font-size:12.5px; color:var(--ink-3); }
  .j-cp-d figcaption b { color:var(--gold-dk); font-weight:650; }
  /* Where the grahas landed in the chart on the right. Reading a varga off
     a diamond means counting bhavas round from the top, which is the work
     this saves — and on the D60 it is the only way the panel is usable. */
  /* No cap. It was 430px inside a 750px column, which put 320px of nothing
     between the table and the drawing — the cap was fixing sparseness caused
     by the column being too wide, and the column is the right width now. */
  .j-cp-t { margin-top:18px; border:1px solid var(--line-soft);
    border-radius:var(--r-in); overflow:auto; }
  .j-cp-t tbody tr:nth-child(even) > * { background:var(--surface-2); }
  .j-cp-t table { width:100%; border-collapse:collapse; font-size:12.5px;
    min-width:220px; }
  .j-cp-t thead th { text-align:left; font-family:var(--font-mono);
    font-size:9px; letter-spacing:.11em; text-transform:uppercase;
    color:var(--ink-3); font-weight:400; padding:8px 12px;
    border-bottom:1px solid var(--line-soft); }
  .j-cp-t tbody th { text-align:left; font-weight:600; color:var(--ink);
    padding:6px 12px; white-space:nowrap; }
  .j-cp-t td { padding:6px 12px; color:var(--ink-2); }
  /* A graha that moved. The arrow column is 1ch wide and does the work; the
     ink on the row does the rest, so the nine can be scanned rather than
     compared name by name. */
  .j-cp-x { width:1px; padding-left:0; color:var(--gold-dk);
    font-size:13px; }
  .j-cp-mv > th, .j-cp-mv > td { color:var(--ink); font-weight:600; }
  .j-cp-n { margin:10px 0 0; font-size:12px; color:var(--ink-3); }
  .j-cp-n b { color:var(--ink-2); font-weight:650; }

  /* ── doshas ─────────────────────────────────────────────────── */
  .j-v-g { display:grid; gap:16px; grid-template-columns:1fr;
    align-items:stretch; margin-bottom:26px; }
  @media (min-width:840px) {
    .j-v-g { grid-template-columns:repeat(3,1fr); }
  }
  .j-v { min-width:0; display:flex; flex-direction:column;
    padding:20px 22px; border:1px solid var(--line);
    border-radius:var(--r-card); background:var(--surface); }
  .j-v-h > b { display:block; font-family:var(--font-serif); font-size:30px;
    font-weight:600; line-height:1.1; color:var(--ink); margin:5px 0 4px; }
  .j-v-h > i { display:block; font-style:normal; font-size:12.5px;
    line-height:1.6; color:var(--ink-2); }
  /* ── the dosha instruments ──────────────────────────────────
     Each dosha is a rule about a countable thing and each rule draws
     differently: mangal is three reference points, kaal sarp is seven grahas
     inside an arc or not, sade sati is three phases of two and a half years.
     A shared label/value grid described all three and showed none of them. */
  .j-vz { margin-top:16px; padding-top:15px;
    border-top:1px solid var(--line-soft); }
  .j-vz-t { margin:0 0 12px; font-size:12.5px; line-height:1.5;
    color:var(--ink-3); }
  .j-vz-t b { color:var(--ink); font-weight:650; }
  .j-vz-n { margin:11px 0 0; font-size:12.5px; line-height:1.55;
    color:var(--ink-3); }
  .j-vz-n b { color:var(--ink); font-weight:700; }

  /* mangal — the three places Mars is counted from */
  .j-vz-g { display:grid; gap:7px; }
  .j-vz-r { display:flex; align-items:baseline; gap:9px; flex-wrap:wrap;
    padding:8px 11px; border-radius:var(--r-in);
    border:1px solid var(--line); background:var(--surface); }
  .j-vz-r > .h-f-l { flex:1; min-width:90px; }
  .j-vz-r > b { font-size:13px; font-weight:650; color:var(--ink); }
  .j-vz-r > i { font-style:normal; font-size:11px; color:var(--ink-3); }
  .j-vz-on { border-color:var(--mid); background:var(--mid-bg); }
  .j-vz-on > b, .j-vz-on > i { color:var(--mid); }
  .j-vz-sc { display:flex; align-items:center; gap:10px; flex-wrap:wrap;
    margin-top:12px; }
  .j-vz-sc > div { display:flex; gap:4px; }
  .j-vz-s { padding:3px 10px; border-radius:var(--r-pill);
    border:1px solid var(--line); background:var(--surface);
    font-size:11px; color:var(--ink-3); }
  .j-vz-s-on { border-color:var(--mid); background:var(--mid);
    color:var(--pill-text); font-weight:650; }

  /* kaal sarp — seven pips, filled where the graha is inside the arc */
  .j-vz-ps { display:flex; flex-wrap:wrap; gap:6px; }
  .j-vz-p { display:grid; place-items:center; width:34px; height:34px;
    border-radius:50%; border:1px dashed var(--line);
    background:var(--surface); font-family:var(--font-mono); font-size:11px;
    color:var(--ink-3); }
  .j-vz-p-on { border-style:solid; border-color:var(--gold);
    background:var(--gold-solid); color:var(--gold-solid-text);
    font-weight:700; }

  /* sade sati — the three phases, the running one lit */
  .j-vz-phs { display:grid; gap:6px; grid-template-columns:repeat(3,1fr); }
  .j-vz-ph { min-width:0; padding:9px 9px 10px; border-radius:var(--r-in);
    border:1px solid var(--line); background:var(--surface); }
  .j-vz-ph > b { display:block; font-size:12.5px; font-weight:650;
    color:var(--ink); margin:3px 0 2px; }
  .j-vz-ph > i { display:block; font-style:normal; font-family:var(--font-mono);
    font-size:10px; line-height:1.4; color:var(--ink-3); }
  .j-vz-ph-on { border-color:var(--gold); background:var(--gold-solid); }
  .j-vz-ph-on > b, .j-vz-ph-on > i, .j-vz-ph-on > .h-f-l {
    color:var(--gold-solid-text); }
  .j-v > p { margin:14px 0 0; padding-top:14px;
    border-top:1px solid var(--line-soft); font-size:13px; line-height:1.7;
    color:var(--ink-2); }
  /* Present, and absent. Not red and green: a dosha is a condition with
     remedies, not an error, and the site's --bad is reserved for things that
     have actually gone wrong. */
  .j-v-mid { border-color:var(--gold-lt); background:var(--gold-bg); }
  .j-v-mid .j-v-h > b { color:var(--gold-dk); }
  .j-v-good .j-v-h > b { color:var(--good); }

  /* ── yogas ──────────────────────────────────────────────────── */
  /* Columns, not a grid. Ten yogas in a three-track grid is 3+3+3+1, and the
     last row was one card beside two thirds of nothing; the cards are also all
     different lengths, so a grid row is as tall as its longest card and the
     other two carry the slack. Multi-column packs them and balances the
     heights. The reading order becomes column-wise, which is the right trade
     for an unordered set. */
  .j-y-g { columns:3 300px; column-gap:14px; }
  .j-y { break-inside:avoid; margin-bottom:14px; padding:16px 18px 18px;
    border:1px solid var(--line); border-left:3px solid var(--line);
    border-radius:var(--r-card); background:var(--surface); }
  /* Strength as a spine, the same encoding the graha table uses for dignity.
     Ten cards that differ only in a word are ten cards nobody ranks. */
  .j-y-good { border-left-color:var(--good); }
  .j-y-mid { border-left-color:var(--mid); }
  .j-y-raja { border-color:var(--gold-lt); background:var(--gold-bg); }
  .j-y-raja.j-y-good { border-left-color:var(--good); }
  .j-y-raja.j-y-mid { border-left-color:var(--mid); }
  .j-y-h { display:flex; align-items:baseline; gap:9px; flex-wrap:wrap; }
  .j-y-h > b { font-family:var(--font-serif); font-size:18px; font-weight:600;
    color:var(--ink); }
  .j-y-hi { font-size:13px; color:var(--ink-3); }
  .j-y-m { display:flex; align-items:center; gap:7px; flex-wrap:wrap;
    margin:10px 0 0; }
  .j-y-f { display:block; font-style:normal; font-family:var(--font-mono);
    font-size:11.5px; line-height:1.6; color:var(--ink-3); margin-top:10px; }
  .j-y > p { margin:11px 0 0; padding-top:11px;
    border-top:1px solid var(--line-soft); font-size:13px; line-height:1.7;
    color:var(--ink-2); }
  /* The two counts, as the headline they are rather than a clause. */
  .j-yc { display:grid; gap:12px; grid-template-columns:1fr;
    margin-bottom:16px; }
  @media (min-width:560px) {
    .j-yc { grid-template-columns:repeat(2,minmax(0,1fr)); }
  }
  .j-yc > div { display:flex; align-items:baseline; gap:10px; min-width:0;
    padding:14px 18px; border:1px solid var(--line);
    border-radius:var(--r-card); background:var(--surface); }
  .j-yc > div > b { font-family:var(--font-serif); font-size:32px;
    font-weight:600; line-height:1; color:var(--gold-dk); }
  .j-yc > div > span { font-size:13px; line-height:1.45; color:var(--ink-2); }
  .j-yc > div > span b { color:var(--ink); font-weight:650; }

  .j-rem-g { display:grid; gap:14px; grid-template-columns:1fr;
    margin-top:22px; }
  @media (min-width:720px) {
    .j-rem-g { grid-template-columns:repeat(auto-fit,minmax(260px,1fr)); }
  }
  .j-rem { min-width:0; padding:16px 18px; border:1px solid var(--line);
    border-radius:var(--r-card); background:var(--surface); }
  .j-rem ul { margin:8px 0 0; padding-left:17px; }
  .j-rem li { font-size:12.5px; line-height:1.75; color:var(--ink-2); }

  /* ── dasha ──────────────────────────────────────────────────── */
  .j-rb { margin-bottom:22px; }
  .j-rb-b { display:flex; height:46px; border:1px solid var(--line);
    border-radius:var(--r-in); overflow:hidden; background:var(--surface); }
  .j-rb-s { position:relative; display:flex; align-items:center;
    justify-content:center; min-width:0; background:var(--surface-2);
    border-right:1px solid var(--line); }
  .j-rb-s:last-child { border-right:0; }
  .j-rb-s > b { font-family:var(--font-mono); font-size:10.5px;
    font-weight:600; color:var(--ink-3); letter-spacing:.02em; }
  /* Alternating grounds so eighteen periods read as eighteen rather than as
     one bar with tick marks. Even ones sit a shade back. */
  .j-rb-s:nth-child(even) { background:var(--surface); }
  /* .j-rb-s.j-rb-on, NOT .j-rb-on. A bare class is one specificity point and
     :nth-child(even) above is two, so on every chart whose running mahadasha
     happened to land on an even segment the stripe won and the lit cell kept
     the unlit ground — while `> b` below, having nothing to compete with,
     still repainted the label to the ON colour. Dark text on the dark
     ground: the one period the reader is actually in was the only one they
     could not read. Odd-numbered charts looked perfect, which is why this
     survived the example. */
  .j-rb-s.j-rb-on { background:var(--gold-solid);
                    border-right-color:var(--gold-solid); }
  .j-rb-s.j-rb-on > b { color:var(--gold-solid-text); font-weight:700; }
  .j-rb-t { display:flex; justify-content:space-between; margin-top:6px;
    font-family:var(--font-mono); font-size:11px; color:var(--ink-3); }

  .j-now { padding:22px 24px; border:1px solid var(--gold-lt);
    border-radius:var(--r-card); background:var(--gold-bg);
    margin-bottom:20px; }
  .j-dls { display:grid; gap:16px; grid-template-columns:1fr; }
  @media (min-width:660px) {
    .j-dls { grid-template-columns:repeat(auto-fit,minmax(150px,1fr)); }
  }
  .j-dl { min-width:0; }
  .j-dl > b { display:block; font-family:var(--font-serif); font-size:25px;
    font-weight:600; line-height:1.15; color:var(--gold-dk); margin:4px 0 3px; }
  .j-dl > i { display:block; font-style:normal; font-family:var(--font-mono);
    font-size:11.5px; color:var(--ink-2); }
  .j-now-b { margin:18px 0 0; padding-top:16px;
    border-top:1px solid var(--gold-lt); font-size:13.5px; line-height:1.75;
    color:var(--ink-2); }
  .j-now-b b { color:var(--ink); font-weight:650; }
  .j-ds-g { display:grid; gap:14px; grid-template-columns:1fr;
    margin-top:18px; }
  @media (min-width:760px) {
    .j-ds-g { grid-template-columns:repeat(auto-fit,minmax(240px,1fr)); }
  }
  .j-ds { min-width:0; padding:14px 16px; border-radius:var(--r-in);
    background:var(--surface); }
  .j-ds > p { margin:6px 0 0; font-size:12.5px; line-height:1.7;
    color:var(--ink-2); }

  /* The three sub-levels, side by side. Nine rows and four columns each, so
     they line up and the drill from years to months to weeks reads across
     rather than down. */
  .j-d-three { display:grid; gap:16px; grid-template-columns:1fr;
    align-items:start; margin-top:4px; }
  @media (min-width:700px) {
    .j-d-three { grid-template-columns:repeat(2,minmax(0,1fr)); }
  }
  @media (min-width:1060px) {
    .j-d-three { grid-template-columns:repeat(3,minmax(0,1fr)); }
  }
  .j-d-three > * { min-width:0; }
  .j-tbl-sm table { table-layout:auto; }
  .j-tbl-sm thead th { padding:10px 11px; vertical-align:bottom; }
  .j-tbl-sm thead th i { display:block; font-style:normal; margin-top:2px; }
  .j-tbl-sm thead th b { font-weight:700; color:var(--gold-dk); }
  .j-tbl-sm td, .j-tbl-sm tbody th { padding:9px 11px; }
  .j-note-t { margin-top:18px; }
  /* The mahadasha and antardasha lords read together — same planet, friend,
     enemy — which the API works out and nothing printed. */
  .j-now-p { margin:16px 0 0; padding:12px 14px; border-radius:var(--r-in);
    background:var(--surface); font-size:13px; line-height:1.65;
    color:var(--ink-2); }
  .j-now-p b { color:var(--gold-dk); font-weight:650; }

  /* The form's status line. By id for the box, by j- class for the two
     states — .c-help is the shell's and restyling it from a page is what
     checks/clash.py exists to catch. */
  #j-msg { margin-top:10px; }
  #j-msg:empty { display:none; }
  .j-busy { color:var(--gold-dk); font-weight:600; }
  .j-err { color:var(--bad); }
#jc-D1:checked ~ .j-cp-D1,
#jc-D1:checked ~ * .j-cp-D1 { display:block; }
#jc-D1:checked ~ label[for="jc-D1"],
#jc-D1:checked ~ * label[for="jc-D1"] { border-color:var(--gold); background:var(--gold-bg); }
#jc-D1:focus-visible ~ label[for="jc-D1"],
#jc-D1:focus-visible ~ * label[for="jc-D1"] { outline:2px solid var(--gold); outline-offset:2px; }
#jc-D9:checked ~ .j-cp-D9,
#jc-D9:checked ~ * .j-cp-D9 { display:block; }
#jc-D9:checked ~ label[for="jc-D9"],
#jc-D9:checked ~ * label[for="jc-D9"] { border-color:var(--gold); background:var(--gold-bg); }
#jc-D9:focus-visible ~ label[for="jc-D9"],
#jc-D9:focus-visible ~ * label[for="jc-D9"] { outline:2px solid var(--gold); outline-offset:2px; }
#jc-chalit:checked ~ .j-cp-chalit,
#jc-chalit:checked ~ * .j-cp-chalit { display:block; }
#jc-chalit:checked ~ label[for="jc-chalit"],
#jc-chalit:checked ~ * label[for="jc-chalit"] { border-color:var(--gold); background:var(--gold-bg); }
#jc-chalit:focus-visible ~ label[for="jc-chalit"],
#jc-chalit:focus-visible ~ * label[for="jc-chalit"] { outline:2px solid var(--gold); outline-offset:2px; }
#jc-sun_chart:checked ~ .j-cp-sun_chart,
#jc-sun_chart:checked ~ * .j-cp-sun_chart { display:block; }
#jc-sun_chart:checked ~ label[for="jc-sun_chart"],
#jc-sun_chart:checked ~ * label[for="jc-sun_chart"] { border-color:var(--gold); background:var(--gold-bg); }
#jc-sun_chart:focus-visible ~ label[for="jc-sun_chart"],
#jc-sun_chart:focus-visible ~ * label[for="jc-sun_chart"] { outline:2px solid var(--gold); outline-offset:2px; }
#jc-moon_chart:checked ~ .j-cp-moon_chart,
#jc-moon_chart:checked ~ * .j-cp-moon_chart { display:block; }
#jc-moon_chart:checked ~ label[for="jc-moon_chart"],
#jc-moon_chart:checked ~ * label[for="jc-moon_chart"] { border-color:var(--gold); background:var(--gold-bg); }
#jc-moon_chart:focus-visible ~ label[for="jc-moon_chart"],
#jc-moon_chart:focus-visible ~ * label[for="jc-moon_chart"] { outline:2px solid var(--gold); outline-offset:2px; }
#jc-D2:checked ~ .j-cp-D2,
#jc-D2:checked ~ * .j-cp-D2 { display:block; }
#jc-D2:checked ~ label[for="jc-D2"],
#jc-D2:checked ~ * label[for="jc-D2"] { border-color:var(--gold); background:var(--gold-bg); }
#jc-D2:focus-visible ~ label[for="jc-D2"],
#jc-D2:focus-visible ~ * label[for="jc-D2"] { outline:2px solid var(--gold); outline-offset:2px; }
#jc-D3:checked ~ .j-cp-D3,
#jc-D3:checked ~ * .j-cp-D3 { display:block; }
#jc-D3:checked ~ label[for="jc-D3"],
#jc-D3:checked ~ * label[for="jc-D3"] { border-color:var(--gold); background:var(--gold-bg); }
#jc-D3:focus-visible ~ label[for="jc-D3"],
#jc-D3:focus-visible ~ * label[for="jc-D3"] { outline:2px solid var(--gold); outline-offset:2px; }
#jc-D4:checked ~ .j-cp-D4,
#jc-D4:checked ~ * .j-cp-D4 { display:block; }
#jc-D4:checked ~ label[for="jc-D4"],
#jc-D4:checked ~ * label[for="jc-D4"] { border-color:var(--gold); background:var(--gold-bg); }
#jc-D4:focus-visible ~ label[for="jc-D4"],
#jc-D4:focus-visible ~ * label[for="jc-D4"] { outline:2px solid var(--gold); outline-offset:2px; }
#jc-D5:checked ~ .j-cp-D5,
#jc-D5:checked ~ * .j-cp-D5 { display:block; }
#jc-D5:checked ~ label[for="jc-D5"],
#jc-D5:checked ~ * label[for="jc-D5"] { border-color:var(--gold); background:var(--gold-bg); }
#jc-D5:focus-visible ~ label[for="jc-D5"],
#jc-D5:focus-visible ~ * label[for="jc-D5"] { outline:2px solid var(--gold); outline-offset:2px; }
#jc-D6:checked ~ .j-cp-D6,
#jc-D6:checked ~ * .j-cp-D6 { display:block; }
#jc-D6:checked ~ label[for="jc-D6"],
#jc-D6:checked ~ * label[for="jc-D6"] { border-color:var(--gold); background:var(--gold-bg); }
#jc-D6:focus-visible ~ label[for="jc-D6"],
#jc-D6:focus-visible ~ * label[for="jc-D6"] { outline:2px solid var(--gold); outline-offset:2px; }
#jc-D7:checked ~ .j-cp-D7,
#jc-D7:checked ~ * .j-cp-D7 { display:block; }
#jc-D7:checked ~ label[for="jc-D7"],
#jc-D7:checked ~ * label[for="jc-D7"] { border-color:var(--gold); background:var(--gold-bg); }
#jc-D7:focus-visible ~ label[for="jc-D7"],
#jc-D7:focus-visible ~ * label[for="jc-D7"] { outline:2px solid var(--gold); outline-offset:2px; }
#jc-D8:checked ~ .j-cp-D8,
#jc-D8:checked ~ * .j-cp-D8 { display:block; }
#jc-D8:checked ~ label[for="jc-D8"],
#jc-D8:checked ~ * label[for="jc-D8"] { border-color:var(--gold); background:var(--gold-bg); }
#jc-D8:focus-visible ~ label[for="jc-D8"],
#jc-D8:focus-visible ~ * label[for="jc-D8"] { outline:2px solid var(--gold); outline-offset:2px; }
#jc-D10:checked ~ .j-cp-D10,
#jc-D10:checked ~ * .j-cp-D10 { display:block; }
#jc-D10:checked ~ label[for="jc-D10"],
#jc-D10:checked ~ * label[for="jc-D10"] { border-color:var(--gold); background:var(--gold-bg); }
#jc-D10:focus-visible ~ label[for="jc-D10"],
#jc-D10:focus-visible ~ * label[for="jc-D10"] { outline:2px solid var(--gold); outline-offset:2px; }
#jc-D11:checked ~ .j-cp-D11,
#jc-D11:checked ~ * .j-cp-D11 { display:block; }
#jc-D11:checked ~ label[for="jc-D11"],
#jc-D11:checked ~ * label[for="jc-D11"] { border-color:var(--gold); background:var(--gold-bg); }
#jc-D11:focus-visible ~ label[for="jc-D11"],
#jc-D11:focus-visible ~ * label[for="jc-D11"] { outline:2px solid var(--gold); outline-offset:2px; }
#jc-D12:checked ~ .j-cp-D12,
#jc-D12:checked ~ * .j-cp-D12 { display:block; }
#jc-D12:checked ~ label[for="jc-D12"],
#jc-D12:checked ~ * label[for="jc-D12"] { border-color:var(--gold); background:var(--gold-bg); }
#jc-D12:focus-visible ~ label[for="jc-D12"],
#jc-D12:focus-visible ~ * label[for="jc-D12"] { outline:2px solid var(--gold); outline-offset:2px; }
#jc-D16:checked ~ .j-cp-D16,
#jc-D16:checked ~ * .j-cp-D16 { display:block; }
#jc-D16:checked ~ label[for="jc-D16"],
#jc-D16:checked ~ * label[for="jc-D16"] { border-color:var(--gold); background:var(--gold-bg); }
#jc-D16:focus-visible ~ label[for="jc-D16"],
#jc-D16:focus-visible ~ * label[for="jc-D16"] { outline:2px solid var(--gold); outline-offset:2px; }
#jc-D20:checked ~ .j-cp-D20,
#jc-D20:checked ~ * .j-cp-D20 { display:block; }
#jc-D20:checked ~ label[for="jc-D20"],
#jc-D20:checked ~ * label[for="jc-D20"] { border-color:var(--gold); background:var(--gold-bg); }
#jc-D20:focus-visible ~ label[for="jc-D20"],
#jc-D20:focus-visible ~ * label[for="jc-D20"] { outline:2px solid var(--gold); outline-offset:2px; }
#jc-D24:checked ~ .j-cp-D24,
#jc-D24:checked ~ * .j-cp-D24 { display:block; }
#jc-D24:checked ~ label[for="jc-D24"],
#jc-D24:checked ~ * label[for="jc-D24"] { border-color:var(--gold); background:var(--gold-bg); }
#jc-D24:focus-visible ~ label[for="jc-D24"],
#jc-D24:focus-visible ~ * label[for="jc-D24"] { outline:2px solid var(--gold); outline-offset:2px; }
#jc-D27:checked ~ .j-cp-D27,
#jc-D27:checked ~ * .j-cp-D27 { display:block; }
#jc-D27:checked ~ label[for="jc-D27"],
#jc-D27:checked ~ * label[for="jc-D27"] { border-color:var(--gold); background:var(--gold-bg); }
#jc-D27:focus-visible ~ label[for="jc-D27"],
#jc-D27:focus-visible ~ * label[for="jc-D27"] { outline:2px solid var(--gold); outline-offset:2px; }
#jc-D30:checked ~ .j-cp-D30,
#jc-D30:checked ~ * .j-cp-D30 { display:block; }
#jc-D30:checked ~ label[for="jc-D30"],
#jc-D30:checked ~ * label[for="jc-D30"] { border-color:var(--gold); background:var(--gold-bg); }
#jc-D30:focus-visible ~ label[for="jc-D30"],
#jc-D30:focus-visible ~ * label[for="jc-D30"] { outline:2px solid var(--gold); outline-offset:2px; }
#jc-D40:checked ~ .j-cp-D40,
#jc-D40:checked ~ * .j-cp-D40 { display:block; }
#jc-D40:checked ~ label[for="jc-D40"],
#jc-D40:checked ~ * label[for="jc-D40"] { border-color:var(--gold); background:var(--gold-bg); }
#jc-D40:focus-visible ~ label[for="jc-D40"],
#jc-D40:focus-visible ~ * label[for="jc-D40"] { outline:2px solid var(--gold); outline-offset:2px; }
#jc-D45:checked ~ .j-cp-D45,
#jc-D45:checked ~ * .j-cp-D45 { display:block; }
#jc-D45:checked ~ label[for="jc-D45"],
#jc-D45:checked ~ * label[for="jc-D45"] { border-color:var(--gold); background:var(--gold-bg); }
#jc-D45:focus-visible ~ label[for="jc-D45"],
#jc-D45:focus-visible ~ * label[for="jc-D45"] { outline:2px solid var(--gold); outline-offset:2px; }
#jc-D60:checked ~ .j-cp-D60,
#jc-D60:checked ~ * .j-cp-D60 { display:block; }
#jc-D60:checked ~ label[for="jc-D60"],
#jc-D60:checked ~ * label[for="jc-D60"] { border-color:var(--gold); background:var(--gold-bg); }
#jc-D60:focus-visible ~ label[for="jc-D60"],
#jc-D60:focus-visible ~ * label[for="jc-D60"] { outline:2px solid var(--gold); outline-offset:2px; }.j-tp-chart { display:block; }
.j-tn a[href="#j-t-chart"] { border-color:var(--gold); background:var(--gold-solid); }
.j-tn a[href="#j-t-chart"] > b,
.j-tn a[href="#j-t-chart"] > i { color:var(--gold-solid-text); }
#j-t-chart:target ~ .j-tps > .j-tp-chart,
#j-t-grahas:target ~ .j-tps > .j-tp-grahas,
#j-t-vargas:target ~ .j-tps > .j-tp-vargas,
#j-t-yogas:target ~ .j-tps > .j-tp-yogas,
#j-t-dasha:target ~ .j-tps > .j-tp-dasha { display:block; }
#j-t-grahas:target ~ .j-tps > .j-tp-chart,
#j-t-vargas:target ~ .j-tps > .j-tp-chart,
#j-t-yogas:target ~ .j-tps > .j-tp-chart,
#j-t-dasha:target ~ .j-tps > .j-tp-chart { display:none; }
#j-t-chart:target ~ .j-tn a[href="#j-t-chart"],
#j-t-grahas:target ~ .j-tn a[href="#j-t-grahas"],
#j-t-vargas:target ~ .j-tn a[href="#j-t-vargas"],
#j-t-yogas:target ~ .j-tn a[href="#j-t-yogas"],
#j-t-dasha:target ~ .j-tn a[href="#j-t-dasha"] { border-color:var(--gold); background:var(--gold-solid); }
#j-t-chart:target ~ .j-tn a[href="#j-t-chart"] b,
#j-t-chart:target ~ .j-tn a[href="#j-t-chart"] i,
#j-t-grahas:target ~ .j-tn a[href="#j-t-grahas"] b,
#j-t-grahas:target ~ .j-tn a[href="#j-t-grahas"] i,
#j-t-vargas:target ~ .j-tn a[href="#j-t-vargas"] b,
#j-t-vargas:target ~ .j-tn a[href="#j-t-vargas"] i,
#j-t-yogas:target ~ .j-tn a[href="#j-t-yogas"] b,
#j-t-yogas:target ~ .j-tn a[href="#j-t-yogas"] i,
#j-t-dasha:target ~ .j-tn a[href="#j-t-dasha"] b,
#j-t-dasha:target ~ .j-tn a[href="#j-t-dasha"] i { color:var(--gold-solid-text); }
#j-t-grahas:target ~ .j-tn a[href="#j-t-chart"],
#j-t-vargas:target ~ .j-tn a[href="#j-t-chart"],
#j-t-yogas:target ~ .j-tn a[href="#j-t-chart"],
#j-t-dasha:target ~ .j-tn a[href="#j-t-chart"] { border-color:var(--line); background:var(--surface); }
#j-t-grahas:target ~ .j-tn a[href="#j-t-chart"] b,
#j-t-vargas:target ~ .j-tn a[href="#j-t-chart"] b,
#j-t-yogas:target ~ .j-tn a[href="#j-t-chart"] b,
#j-t-dasha:target ~ .j-tn a[href="#j-t-chart"] b { color:var(--ink-2); }
#j-t-grahas:target ~ .j-tn a[href="#j-t-chart"] i,
#j-t-vargas:target ~ .j-tn a[href="#j-t-chart"] i,
#j-t-yogas:target ~ .j-tn a[href="#j-t-chart"] i,
#j-t-dasha:target ~ .j-tn a[href="#j-t-chart"] i { color:var(--ink-3); }

  /* Own prefix k-. Everything the kundli itself draws is j-, and owned by
     pages/kundliview.py — this page only positions it. */
  .k-veil { display:none; }
  .k-veil.k-on { display:block; }
  .k-wait { padding:16px 0 40px; }
  .k-wait p { margin:16px 0 0; font-size:14px; color:var(--ink-2); }
  .k-wait-band { display:grid; gap:22px; grid-template-columns:repeat(4,1fr);
                 padding:20px 22px; }
  @media (max-width:760px) {
    .k-wait-band { grid-template-columns:repeat(2,1fr); }
  }
  .k-wait-two { display:grid; gap:16px; margin-top:16px;
                grid-template-columns:1fr; }
  @media (min-width:860px) {
    .k-wait-two { grid-template-columns:1fr 1fr; }
  }
  .k-wait-two .d-card { padding:20px; }
  /* The band's three tiers at the heights they really are: the mono label,
     the serif answer under it, the caption under that. */
  .k-sk-lbl { width:62%; height:10px; min-height:10px; }
  .k-sk-big { width:88%; height:26px; min-height:26px; margin-top:10px; }
  .k-sk-sub { width:70%; height:11px; min-height:11px; margin-top:9px; }
  /* A diamond chart is square. */
  .k-sk-sq { aspect-ratio:1 / 1; width:100%; border-radius:10px; }
  .k-err { color:var(--bad); }

  /* kv's sections are built for the public column, which is wider and
     centres its heads. Scoped under .d-main, never bare — the public page
     owns these classes and checks/clash.py is why. */
  .d-main .j-tabs { margin-top:18px; }
  .d-main .c-sec-h { text-align:left; }