/* ============================================================
   panchang.css — components.

   Palette tokens live in theme.css and are taken from the Srinivas
   Panchang app. Nothing in this file hard-codes a colour; every rule
   reads a token, so retheming is one file, not a search-and-replace.
   ============================================================ */

/* ---- base -------------------------------------------------- */
* { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--ground);
  color: var(--ink);
  font-family: var(--font-ui);
  font-size: 16px;          /* R5 — never below 16px for data */
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;       /* R3 — the body never scrolls sideways */
  padding-bottom: env(safe-area-inset-bottom);
}

/* R5 — line-height is set PER SCRIPT, not globally. Telugu, Kannada,
   Gujarati and Devanagari need more room than Latin, and a conjunct that
   collides with the line above is a legibility bug. */
/* The UI face comes first: it has no Indic glyphs, so Indic text falls through
   to the script's own face while Latin labels, numbers and the chrome stay in
   the UI face instead of borrowing the Indic font's Latin. */
body.script-telugu    { font-family: "IBM Plex Sans", "Noto Serif Telugu", var(--font-indic), var(--font-ui); line-height: 1.75; }
body.script-kannada   { font-family: "IBM Plex Sans", "Noto Serif Kannada", var(--font-indic), var(--font-ui); line-height: 1.75; }
body.script-gujarati  { font-family: "IBM Plex Sans", "Noto Serif Gujarati", var(--font-indic), var(--font-ui); line-height: 1.7; }
body.script-devanagari{ font-family: "IBM Plex Sans", "Tiro Devanagari Sanskrit", var(--font-indic), var(--font-ui); line-height: 1.7; }

h1, h2, h3, h4 { margin: 0; font-weight: 600; text-wrap: balance; }
p { margin: 0; }
a { color: var(--accent); text-decoration-thickness: 1px; text-underline-offset: 2px; }
a:hover { color: var(--accent-deep); }

:focus-visible {
  outline: 2px solid var(--structure);
  outline-offset: 2px;
  border-radius: 3px;
}

.wrap { max-width: var(--maxw); margin: 0 auto; padding: 0 16px; }
@media (min-width: 768px) { .wrap { padding: 0 24px; } }

.num { font-family: var(--font-num); font-variant-numeric: tabular-nums; letter-spacing: -.01em; }

.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* R6 — Indic strings are never truncated. A clipped conjunct can change
   a word, so everything wraps instead. */
.no-clip { overflow-wrap: anywhere; white-space: normal; }

/* ---- chrome: top bar --------------------------------------- */
/* The brand band: a kumkuma gradient with white text, edged below by a
   pasupu stripe. It is the one place the gradient appears, because a
   gradient behind data is exactly what §9 says to avoid. The stripe is an
   outer shadow rather than a border so the bar keeps its height and the
   city band beneath it does not shift.
   Three tracks (layout v8): brand · sections centred on the BAR, not in
   whatever the brand leaves over · badges and hamburger. Columns are pinned
   because the section nav is display:none below 1180px, and an unplaced grid
   item would otherwise let the tools slide into the middle track. */
.topbar {
  position: sticky; top: 0; z-index: 60;
  background: var(--brand-band);
  color: var(--brand-ink);
  box-shadow: 0 3px 0 var(--pasupu);
}
.topbar-in {
  max-width: var(--maxw-wide); margin: 0 auto; padding: 0 16px;
  display: grid; grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
  align-items: center; gap: 12px; min-height: 54px;
}
@media (min-width: 768px) { .topbar-in { padding: 0 20px; } }
.brand {
  grid-column: 1; justify-self: start; min-width: 0;
  display: flex; align-items: center; gap: 9px;
  font-weight: 600; color: var(--brand-ink); text-decoration: none;
  font-size: 16px; letter-spacing: -.01em; white-space: nowrap;
}
.brand:hover { color: var(--brand-ink); }
.brand .mark {
  width: 27px; height: 27px; flex: 0 0 27px; border-radius: 50%;
  display: grid; place-items: center;
  background: rgba(255,255,255,.16); color: var(--pasupu);
  border: 1px solid rgba(255,255,255,.3);
  font-family: var(--font-display); font-size: 15px; line-height: 1;
}
/* .86, not lower: at 12px this needs 4.5:1, and .72 measured 4.1:1 on the band.
   Shown only where the bar has room for it beside seven sections and badges. */
.brand .brand-sub { color: rgba(255,255,255,.86); font-weight: 400; font-size: 12px; display: none; }
@media (min-width: 1480px) { .brand .brand-sub { display: inline; } }

.top-tools { grid-column: 3; justify-self: end; display: flex; align-items: center; gap: 8px; }
.icon-btn {
  min-width: 40px; height: 40px; padding: 0 10px;
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  background: transparent; border: 1px solid transparent; border-radius: var(--radius-sm);
  color: var(--brand-ink); font: inherit; font-size: 14px; font-weight: 600; cursor: pointer;
  text-decoration: none;
}
.icon-btn:hover { background: rgba(255,255,255,.14); border-color: rgba(255,255,255,.22); color: var(--brand-ink); }
.icon-btn svg { width: 18px; height: 18px; }
.topbar :focus-visible { outline-color: var(--pasupu); }

/* ---- app badges -------------------------------------------- */
/* In the bar from 768px up; on a phone they move to the footer. A text link
   stands in until the official Google/Apple artwork is placed in
   public/badges/ — recreating that artwork is not permitted. */
.badges { display: flex; align-items: center; gap: 8px; }
.badge {
  display: inline-flex; align-items: center; gap: 7px; min-height: 40px;
  padding: 4px 11px; border-radius: var(--radius-sm); white-space: nowrap;
  background: #000; color: #fff; border: 1px solid rgba(255,255,255,.34);
  text-decoration: none;
}
.badge:hover { color: #fff; border-color: var(--pasupu); }
.badge svg { width: 17px; height: 17px; flex: 0 0 17px; }
.badge .bt { display: flex; flex-direction: column; line-height: 1.15; }
.badge .bt .s { font-size: 10px; letter-spacing: .04em; opacity: .9; }
.badge .bt .l { font-size: 13px; font-weight: 600; }
.badge.official { padding: 0; background: none; border: 0; min-height: 0; }
.badge.official img { display: block; height: 40px; width: auto; }
.top-badges { display: none; }
@media (min-width: 768px) { .top-badges { display: flex; } }

/* ---- chrome: the city band (city · date · page actions) ------ */
/* City and date on the left, the page's own actions on the right. The city
   is always visible and one tap from changing — never a silent default.
   Sticky from 768px; on a phone it wraps to two rows and scrolls away, so it
   never costs the day head its place in the first viewport. */
.contextbar {
  background: var(--surface);
  border-bottom: 1px solid var(--hair);
}
@media (min-width: 768px) { .contextbar { position: sticky; top: 54px; z-index: 45; } }
.contextbar-in {
  max-width: var(--maxw-wide); margin: 0 auto; padding: 8px 16px;
  display: flex; align-items: center; flex-wrap: wrap; gap: 8px;
  /* row-gap is tighter than the column gap: when the language pills drop to
     their own line they should still read as one bar, not two. */
  row-gap: 6px;
}
@media (min-width: 768px) { .contextbar-in { padding: 8px 20px; } }

.chip {
  display: inline-flex; align-items: center; gap: 6px; flex: 0 1 auto; min-width: 0;
  min-height: 38px; padding: 5px 13px; white-space: nowrap;
  background: var(--surface-alt); border: 1px solid var(--hair-strong);
  border-radius: 999px; color: var(--ink); font: inherit; font-size: 14px; font-weight: 600;
  cursor: pointer; text-decoration: none;
}
.chip:hover { border-color: var(--brass); background: var(--brass-soft); color: var(--ink); }
.chip svg { width: 15px; height: 15px; flex: 0 0 15px; color: var(--accent); }
.chip .chip-label {
  color: var(--ink-muted); font-size: 11px; font-weight: 700;
  text-transform: uppercase; letter-spacing: .06em;
}
.chip .chip-value { overflow: hidden; text-overflow: ellipsis; }


/* ---- the two language controls in the city band -------------------
   "Calendar as per" sets the tradition, the script and the interface;
   "Translate to" only adds the small second line under each name.

   The pair behaves as ONE unit at every width: either both pills sit on
   the bar beside the date, or both drop together to a full-width row of
   their own. They never split one-up-one-down, and they never squeeze
   the date out — which is what happened while the bar could not wrap.
   Inside the unit each pill takes exactly half (flex: 1 1 0), so the two
   stay the same width whatever language is selected. */
.langbar {
  display: flex; align-items: center; gap: 6px;
  flex: 1 1 340px;            /* shares the bar; drops whole when cramped */
  max-width: 560px;           /* and never sprawls on a very wide screen */
  min-width: 0; flex-wrap: nowrap;
}
.langsel {
  display: inline-flex; align-items: center; gap: 6px;
  flex: 1 1 0; min-width: 0;  /* equal halves, both allowed to shrink */
  min-height: 38px; padding: 3px 4px 3px 11px;
  background: var(--surface-alt); border: 1px solid var(--hair-strong);
  border-radius: 999px; cursor: pointer;
}
.langsel:focus-within { border-color: var(--accent); box-shadow: 0 0 0 3px var(--focus, rgba(255,196,12,.55)); }
.langsel .ls-label {
  flex: 0 0 auto;
  font-size: 11px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase;
  color: var(--ink-muted); white-space: nowrap;
}
.langsel select {
  flex: 1 1 auto; width: 100%; min-width: 0;
  min-height: 30px; padding: 0 4px; border: 0; border-radius: 999px;
  background: transparent; color: var(--ink); font: inherit; font-size: 14px; font-weight: 600;
  cursor: pointer; text-overflow: ellipsis;
}
.langsel select:focus { outline: none; }

/* Below this the bar cannot hold city + date + both pills, so the pair
   takes a line of its own — as a pair, still side by side. */
@media (max-width: 900px) {
  .langbar { flex: 1 0 100%; order: 8; }
}
/* On a phone the label stacks above the value, so neither pill has to
   truncate the language name — the one word that actually matters. */
@media (max-width: 520px) {
  .langsel { flex-direction: column; align-items: stretch; gap: 0; padding: 2px 9px; min-height: 42px; }
  .langsel .ls-label { font-size: 9px; line-height: 1.35; }
  .langsel select { font-size: 13px; min-height: 22px; padding: 0; }
}

/* ---- the second language, under a label ----------------------------
   A reading aid, never a second heading: always smaller, lighter, muted,
   and never inheriting the uppercasing or letter-spacing of the label it
   sits under — those belong to the label, not to a translation of it. */
.gloss {
  display: block;
  font-family: var(--font-ui);
  font-size: .78em; font-weight: 400; font-style: normal;
  line-height: 1.35; letter-spacing: 0; text-transform: none;
  color: var(--ink-muted);
}
/* Where the label is already tiny, hold a floor so the gloss stays legible
   instead of shrinking with it. */
.dh-data .k .gloss, .row .k .gloss, .cal-week .dow .gloss, .date .m .gloss { font-size: 10px; }
.timing .name .gloss { font-size: 12px; }
.timing .name em .gloss { font-size: 11px; }
.nl-title .gloss, .nl-sub .gloss { font-size: 11px; }
.card-title .gloss, .page-title .gloss { font-size: .62em; font-weight: 500; }
.tag .gloss { display: inline; font-size: 1em; }
.tag .gloss::before { content: " · "; }
/* Printing is for a household to keep: one language is enough on paper. */
@media print { .gloss { display: none; } }

/* The second line is set in the SECOND language, which may be an Indic
   script the Latin UI stack cannot draw. body carries script2-* for it. */
body.script2-telugu     .roman, body.script2-telugu     .ro, body.script2-telugu     .gloss { font-family: "Noto Serif Telugu", var(--font-indic); }
body.script2-kannada    .roman, body.script2-kannada    .ro, body.script2-kannada    .gloss { font-family: "Noto Serif Kannada", var(--font-indic); }
body.script2-gujarati   .roman, body.script2-gujarati   .ro, body.script2-gujarati   .gloss { font-family: "Noto Serif Gujarati", var(--font-indic); }
body.script2-devanagari .roman, body.script2-devanagari .ro, body.script2-devanagari .gloss { font-family: "Tiro Devanagari Sanskrit", var(--font-indic); }

.datenav { display: flex; align-items: center; gap: 2px; flex: 0 1 auto; min-width: 0; }
.datenav .step {
  width: 32px; height: 38px; flex: 0 0 32px; display: grid; place-items: center;
  border: 1px solid transparent; border-radius: var(--radius-sm);
  color: var(--ink); font-size: 20px; text-decoration: none;
}
.datenav .step:hover { border-color: var(--hair-strong); background: var(--surface-sunk); color: var(--ink); }
.datenav .today-btn {
  min-height: 38px; padding: 0 12px; margin-left: 4px; display: inline-flex; align-items: center;
  border-radius: var(--radius-sm); border: 1px solid var(--accent); color: var(--accent);
  font-size: 13px; font-weight: 600; text-decoration: none;
}
.datenav .today-btn:hover { background: var(--accent-soft); }

.ctx-actions { margin-left: auto; display: flex; align-items: center; gap: 6px; flex: 0 0 auto; }
.cbtn {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  min-height: 36px; padding: 0 12px; border-radius: var(--radius-sm);
  border: 1px solid var(--hair-strong); background: var(--surface-alt);
  color: var(--ink); font: inherit; font-size: 13px; font-weight: 600;
  white-space: nowrap; cursor: pointer; text-decoration: none;
}
.cbtn svg { width: 16px; height: 16px; flex: 0 0 16px; color: var(--structure); }
.cbtn:hover { border-color: var(--brass); background: var(--brass-soft); color: var(--ink); }

/* Phone: city + date + three actions is ~420px against ~330px usable, so the
   band wraps — city and date first, the actions right-aligned beneath — and
   View month and Print collapse to 40px icons that keep their names for
   screen readers. Sankalpam keeps its word. */
@media (max-width: 767px) {
  .contextbar-in { flex-wrap: wrap; column-gap: 6px; row-gap: 6px; padding: 8px 12px; }
  .chip { padding: 5px 10px; font-size: 13px; min-height: 40px; }
  .chip .chip-label { display: none; }
  .contextbar-in > .chip { max-width: 42%; }
  .datenav { flex: 1 1 0; min-width: 0; justify-content: flex-end; }
  .datenav .step { width: 28px; flex-basis: 28px; height: 40px; }
  .datenav .today-btn { min-height: 40px; padding: 0 9px; }
  /* order 9 keeps the actions below the language pills (order 8) once
     everything has dropped to its own row. */
  .ctx-actions { flex: 1 0 100%; order: 9; justify-content: flex-end; }
  .cbtn { min-height: 40px; }
  .cbtn.ico { width: 40px; padding: 0; }
  .cbtn.ico .t { display: none; }
}
@media (max-width: 420px) {
  .chip svg { display: none; }
}

/* ---- chrome: bottom nav (mobile) --------------------------- */
/* R9 — bottom nav on mobile, top nav on desktop. Five items, no more. */
.bottomnav {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 45;
  display: grid; grid-template-columns: repeat(5, 1fr);
  background: var(--surface); border-top: 1px solid var(--hair);
  padding-bottom: env(safe-area-inset-bottom);
}
@media (min-width: 768px) { .bottomnav { display: none; } }
.bottomnav a {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 3px; min-height: 56px; text-decoration: none;
  color: var(--ink-muted); font-size: 11px; font-weight: 500;
}
.bottomnav a svg { width: 20px; height: 20px; }
.bottomnav a[aria-current="page"] { color: var(--accent); }


/* ---- page furniture ---------------------------------------- */
main { padding: 18px 0 40px; }

.page-head { margin-bottom: 18px; }
.eyebrow {
  font-size: 12px; text-transform: uppercase; letter-spacing: .1em;
  color: var(--brass); font-weight: 600;
}
.page-title { font-size: 24px; letter-spacing: -.01em; margin-top: 4px; }
@media (min-width: 768px) { .page-title { font-size: 30px; } }
.page-note { color: var(--ink-muted); font-size: 14px; margin-top: 6px; max-width: 62ch; }

.section-label {
  font-size: 12px; text-transform: uppercase; letter-spacing: .11em;
  color: var(--ink-muted); font-weight: 600; margin-bottom: 8px;
  display: flex; align-items: center; gap: 10px;
}
.section-label::after {
  content: ""; flex: 1; height: 1px;
  background: linear-gradient(90deg, var(--hair-strong), transparent);
}

.card {
  background: var(--card-bg); border: 1px solid var(--hair);
  border-radius: var(--radius); box-shadow: var(--shadow);
  padding: 14px;
}
@media (min-width: 768px) { .card { padding: 18px; } }
.card-head {
  display: flex; align-items: baseline; justify-content: space-between; gap: 10px;
  margin-bottom: 12px;
}
.card-title {
  margin: 0; line-height: 1.4;
  font-size: 12px; text-transform: uppercase; letter-spacing: .11em;
  color: var(--structure); font-weight: 700;
}

.grid { display: grid; gap: 14px; }
@media (min-width: 900px) {
  .grid-2 { grid-template-columns: 1fr 1fr; }
}

/* R10 — full-width sections on mobile, never cards inside cards */
@media (max-width: 599px) {
  .card { border-left: 0; border-right: 0; border-radius: 0; margin-left: -16px; margin-right: -16px; }
  /* Layout v8: the day's cards keep their edges inside the gutter. */
  .today .card { border: 1px solid var(--hair); border-radius: var(--radius); margin-left: 0; margin-right: 0; }
}

/* ---- the page body and the ad rail -------------------------- */
/* ≥1180px the rail (300px — the width of every desktop unit worth running)
   sits left of the body. It stretches to the body's height, which is what
   gives the sticky 300×600 room to travel; the 300×250 above it scrolls away,
   because a fully sticky rail (~900px) is taller than a laptop screen. The
   sticky offset clears the brand band and the city band. */
.page-layout { max-width: var(--maxw-wide); margin: 0 auto; }
.adrail { display: none; }
@media (min-width: 1180px) {
  .page-layout.has-rail {
    display: grid; grid-template-columns: 300px minmax(0, 1fr); gap: 24px;
    padding: 0 20px; align-items: start;
  }
  .page-layout.has-rail .adrail {
    display: flex; flex-direction: column; gap: 22px; align-self: stretch; padding-top: 18px;
  }
  .page-layout.has-rail .adrail .sticky { position: sticky; top: 128px; }
  .page-layout.has-rail .wrap { max-width: none; padding: 0; }
}
.content { display: block; min-width: 0; container-type: inline-size; container-name: content; }

/* ---- reserved ad slots ------------------------------------- */
/* Exact-size, so the page never shifts when a unit fills or fails to. */
.ad { display: flex; flex-direction: column; align-items: center; gap: 4px; }
.ad-label {
  align-self: stretch; text-align: center; font-size: 10px; font-weight: 700;
  text-transform: uppercase; letter-spacing: .1em; color: var(--ad-fg);
}
.ad-unit {
  flex: 0 0 auto; max-width: 100%;
  background: var(--ad-bg); border: 1px dashed var(--ad-border); color: var(--ad-fg);
  display: flex; align-items: center; justify-content: center; text-align: center;
}
.ad-unit .px { font-family: var(--font-num); font-size: 12px; }
.u-halfpage { width: 300px; height: 600px; }
.u-mrec     { width: 300px; height: 250px; }
.u-leader   { width: 728px; height: 90px; }
.u-mbanner  { width: 320px; height: 50px; }

/* ---- the day head ------------------------------------------ */
/* Identity (samvatsara → masa · paksha · tithi → era → tradition) beside the
   day's readings. The first thing under the city band at every width. */
.dayhead {
  display: grid; grid-template-columns: minmax(0, 1fr); gap: 14px;
  background: var(--ground-deep); border: 1px solid var(--hair); border-radius: var(--radius);
  padding: 14px; margin-bottom: 14px; align-items: start;
}
@container content (min-width: 600px) {
  .dayhead { grid-template-columns: minmax(0, 1fr) minmax(0, 1.3fr); gap: 16px 24px; padding: 16px 18px; }
}
.dh-id .sv { font-size: 21px; color: var(--accent); line-height: 1.45; }
.dh-id .roman {
  display: block; font-family: var(--font-ui); font-size: 12px; font-weight: 400;
  color: var(--ink-muted); margin-top: 2px; letter-spacing: 0;
}
.dh-id .ayana { color: var(--ink-muted); font-size: 13px; margin-top: 4px; }
.dh-id .masa { margin-top: 8px; font-size: 17px; font-weight: 600; color: var(--structure); line-height: 1.5; }
.dh-id .eras { font-size: 12px; color: var(--brass); font-weight: 600; margin-top: 6px; }
.dh-id .tradition { margin-top: 4px; font-size: 12px; color: var(--ink-muted); line-height: 1.5; }
.dh-id .tradition b { color: var(--ink-mid); font-weight: 600; }
.dh-id .tradition .unrev { color: var(--accent); font-weight: 600; }
.dh-id .tradition a { margin-left: 4px; font-weight: 600; white-space: nowrap; }

.dh-data { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 11px 10px; }
.dh-data > div { display: flex; flex-direction: column; min-width: 0; }
.dh-data .k {
  font-size: 11px; text-transform: uppercase; letter-spacing: .08em;
  color: var(--ink-muted); font-weight: 700;
}
.dh-data .v { font-weight: 600; font-size: 16px; margin-top: 1px; overflow-wrap: anywhere; }
.dh-data .now { grid-column: 1 / -1; padding-top: 10px; border-top: 1px solid var(--hair); }
.dh-data .now .v { font-family: var(--font-ui); font-size: 14px; line-height: 1.55; }
.dh-data .now .bad { color: var(--ashubha); }
.dh-data .now .good { color: var(--shubha); }
.dh-data .now .clear { color: var(--ink); }
.dh-data .now .until { color: var(--ink-muted); font-weight: 400; font-family: var(--font-num); font-size: 13px; }
.dh-polar { grid-column: 1 / -1; font-size: 13px; color: var(--ink-mid); }

/* ---- the card grid (today) --------------------------------- */
/* Placed by named areas per content width, so reading order and visual
   order agree everywhere: Panchanga → Timings → Hora → Next observance →
   Coming up. Hora needs a full row for its two columns, so beside Panchanga
   and Timings the right-hand column holds the two short festival cards. */
.cardgrid {
  display: grid; gap: 14px; align-items: start;
  grid-template-columns: minmax(0, 1fr);
}
/* Below three columns the cards simply flow in source order, and the full-
   width pieces span the row — so a slot that is hidden, or not rendered at
   all, leaves no empty row behind. */
.cardgrid .c-hora, .cardgrid .c-ad { grid-column: 1 / -1; }
.side { display: contents; }
.infeed-tablet { display: none; }
@container content (min-width: 740px) {
  .cardgrid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .infeed-phone { display: none; }
  .infeed-tablet { display: flex; }
}
@container content (min-width: 900px) {
  .cardgrid {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    grid-template-areas: "pan tim side" "hora hora hora";
  }
  .c-pan { grid-area: pan; } .c-tim { grid-area: tim; } .cardgrid .c-hora { grid-area: hora; }
  .side { grid-area: side; display: flex; flex-direction: column; gap: 14px; }
  .cardgrid .c-ad { display: none; }
}
/* The in-feed slot is for widths without the desktop rail. */
@media (min-width: 1180px) { .cardgrid .c-ad { display: none; } }
.card { min-width: 0; }
.card-note { font-size: 12px; color: var(--ink-muted); font-family: var(--font-num); }
.tagrow { display: flex; flex-wrap: wrap; gap: 6px; padding-top: 12px; }
a.tag { text-decoration: none; }
a.tag:hover { border-color: var(--brass); color: var(--ink); }

.rise-set {
  display: grid; grid-template-columns: repeat(2, 1fr); gap: 8px 14px;
  margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--hair);
  font-size: 14px;
}
@media (min-width: 480px) { .rise-set { grid-template-columns: repeat(4, 1fr); } }
.rise-set div { display: flex; flex-direction: column; gap: 1px; }
.rise-set .k { font-size: 12px; color: var(--ink-muted); text-transform: uppercase; letter-spacing: .06em; }
.rise-set .v { font-family: var(--font-num); font-weight: 600; font-size: 16px; }

/* ---- panchanga rows ---------------------------------------- */
.rows { display: flex; flex-direction: column; }
.row {
  /* minmax(0, 1fr), not a bare 1fr — a grid track's implicit minimum is its
     content's min-content, so an unbreakable Indic run in a narrow card would
     otherwise force the row wider than the card instead of wrapping. */
  display: grid; grid-template-columns: 92px minmax(0, 1fr) auto; gap: 10px;
  align-items: baseline; padding: 11px 0;
  border-bottom: 1px solid var(--hair); width: 100%;
  background: none; border-left: 0; border-right: 0; border-top: 0;
  font: inherit; color: inherit; text-align: left; cursor: pointer;
}
.row:last-child { border-bottom: 0; }
.row:hover { background: var(--surface-alt); }
.row .k {
  font-size: 12px; text-transform: uppercase; letter-spacing: .07em;
  color: var(--ink-muted); font-weight: 600; font-family: var(--font-ui);
}
.row .v { font-weight: 600; overflow-wrap: anywhere; }
.row .v .roman { display: block; font-size: 12px; font-weight: 400; color: var(--ink-muted); font-family: var(--font-ui); }
.row .t { font-family: var(--font-num); font-size: 14px; color: var(--ink-mid); white-space: nowrap; }
.row .t .spill { color: var(--accent); font-weight: 700; }
.row-detail {
  padding: 0 0 12px 0; font-size: 14px; color: var(--ink-mid);
  border-bottom: 1px solid var(--hair);
}
.row-detail dl { display: grid; grid-template-columns: auto 1fr; gap: 3px 14px; margin: 6px 0 0; }
.row-detail dt { color: var(--ink-muted); font-size: 13px; }
.row-detail dd { margin: 0; font-family: var(--font-num); font-size: 13px; }
.row-detail .why { margin-top: 8px; color: var(--ink-muted); max-width: 58ch; }

/* ---- timings ----------------------------------------------- */
.timing {
  display: grid; grid-template-columns: auto minmax(0, 1fr) auto; gap: 10px;
  align-items: center; padding: 10px 0; border-bottom: 1px solid var(--hair);
}
.timing:last-child { border-bottom: 0; }
/* R14 — colour is NEVER the only encoding. Every row carries a glyph. */
.timing .dot {
  width: 20px; text-align: center; font-size: 13px; font-weight: 700;
  font-family: var(--font-ui);
}
.timing.bad .dot  { color: var(--ashubha); }
.timing.good .dot { color: var(--shubha); }
.timing .name { font-weight: 500; overflow-wrap: anywhere; }
.timing .name em { font-style: normal; font-size: 12px; color: var(--ink-muted); display: block; }
.timing .when { font-family: var(--font-num); font-size: 14px; white-space: nowrap; }
.timing.bad .when  { color: var(--ashubha); }
.timing.good .when { color: var(--shubha); }
.timing .when .spill { font-weight: 700; }

.seg-toggle { display: inline-flex; border: 1px solid var(--hair-strong); border-radius: 999px; overflow: hidden; }
.seg-toggle button {
  min-height: 36px; padding: 0 14px; border: 0; background: var(--surface-alt);
  color: var(--ink-mid); font: inherit; font-size: 13px; font-weight: 600; cursor: pointer;
}
.seg-toggle button + button { border-left: 1px solid var(--hair-strong); }
.seg-toggle button[aria-pressed="true"] { background: var(--structure); color: var(--on-structure); }

/* A window running right now. */
.timing.running {
  background: var(--brass-soft); box-shadow: inset 3px 0 0 var(--brass);
  margin-left: -10px; padding-left: 10px; margin-right: -6px; padding-right: 6px;
}
.timing.running .name em { color: var(--brass-ink); font-weight: 700; }
/* Where a shubha and an ashubha window overlap, both rows say so. */
.timing .clash { display: block; font-size: 12px; color: var(--brass-ink); line-height: 1.4; margin-top: 2px; }
/* One heading, every window under it; glyph and name sit against the first time. */
.timing.group { align-items: start; }
.timing .when.multi { display: flex; flex-direction: column; align-items: flex-end; gap: 4px; }
.timing .when .w1 { font-size: 11px; color: var(--ink-muted); margin-right: 6px; }

/* ---- hora: a day column and a night column ----------------- */
/* Day horas are a twelfth of daylight and night horas a twelfth of the night,
   so each column states its own span and length. Narrow: the time drops
   under the planet and the English gloss goes. */
.hora-cols { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 12px; }
@container content (min-width: 600px) { .hora-cols { gap: 0 26px; } }
.hora-col h3 {
  margin: 0 0 4px; padding-bottom: 6px; border-bottom: 1px solid var(--hair-strong);
  font-size: 12px; text-transform: uppercase; letter-spacing: .08em; font-weight: 700; color: var(--ink);
}
.hora-col h3 span {
  display: block; margin-top: 2px; text-transform: none; letter-spacing: 0;
  font-size: 11px; font-weight: 500; color: var(--ink-muted);
}
.hr {
  display: grid; grid-template-columns: 12px 18px minmax(0, 1fr);
  grid-template-areas: "g n p" ". . w";
  gap: 0 6px; align-items: baseline; padding: 6px 0; border-bottom: 1px solid var(--hair);
}
.hr:last-child { border-bottom: 0; }
.hr .g { grid-area: g; font-size: 12px; text-align: center; }
.hr .n { grid-area: n; font-size: 11px; color: var(--ink-muted); text-align: right; }
.hr .p { grid-area: p; font-size: 14px; font-weight: 600; }
.hr .p .ro { display: none; font-family: var(--font-ui); font-size: 11px; font-weight: 400; color: var(--ink-muted); margin-left: 6px; }
.hr .w { grid-area: w; font-size: 12.5px; white-space: nowrap; }
.hr.good .g, .hr.good .w { color: var(--shubha); }
.hr.bad .g, .hr.bad .w { color: var(--ashubha); }
.hr.running { background: var(--brass-soft); box-shadow: inset 3px 0 0 var(--brass); margin-left: -8px; padding-left: 8px; }
.hr.running .n { color: var(--brass-ink); font-weight: 700; }
.hr.running .p .ro { display: inline; color: var(--brass-ink); font-weight: 700; }
@container content (min-width: 600px) {
  .hr { grid-template-columns: 14px 20px minmax(0, 1fr) auto; grid-template-areas: "g n p w"; }
  .hr .p .ro { display: inline; }
}
.hora-legend { margin-top: 10px; font-size: 12px; color: var(--ink-muted); }

/* ---- next observance & coming up --------------------------- */
.fest-name {
  display: block; font-size: 17px; font-weight: 600; color: var(--accent);
  line-height: 1.4; text-decoration: none;
}
.fest-name:hover { text-decoration: underline; }
.fest-art { font-family: var(--font-display); color: var(--brass); margin-right: 6px; }
.fest-when { color: var(--ink-muted); font-size: 13px; margin-top: 3px; }
.fest-desc { font-size: 14px; color: var(--ink-mid); margin-top: 8px; line-height: 1.5; }

.up-list { display: flex; flex-direction: column; }
.up {
  display: grid; grid-template-columns: 82px minmax(0, 1fr); gap: 10px; align-items: baseline;
  padding: 8px 0; border-bottom: 1px solid var(--hair); text-decoration: none; color: inherit;
}
.up:last-child { border-bottom: 0; }
.up:hover { color: inherit; }
.up:hover .what { text-decoration: underline; }
.up .when { font-size: 12px; color: var(--ink-muted); }
.up .what { font-size: 14px; font-weight: 600; color: var(--accent); line-height: 1.4; }
.up .rel { display: block; font-family: var(--font-ui); font-size: 12px; font-weight: 400; color: var(--ink-muted); }
.up.elsewhere .what { color: var(--ink-mid); }
.up-more { display: inline-block; margin-top: 10px; font-size: 13px; font-weight: 600; color: var(--structure); }

.tag {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 3px 9px; border-radius: 999px; font-size: 12px; font-weight: 600;
  background: var(--surface-sunk); color: var(--ink-mid); border: 1px solid var(--hair);
  white-space: nowrap;
}
.tag.major    { background: var(--accent-soft); color: var(--accent-deep); border-color: transparent; }
.tag.ekadashi { background: var(--structure-soft); color: var(--structure); border-color: transparent; }
.tag.fasting  { background: var(--brass-soft); color: var(--brass); border-color: transparent; }
.tag.women    { background: var(--shubha-soft); color: var(--shubha); border-color: transparent; }
.tag.elsewhere{ background: transparent; color: var(--ink-muted); border-style: dashed; }

/* ---- the regional-difference explainer (F1.9) -------------- */
.explainer {
  border: 1px solid var(--brass); border-left-width: 3px;
  background: var(--brass-soft); border-radius: var(--radius);
  padding: 14px 16px;
}
.explainer h3 {
  font-size: 12px; text-transform: uppercase; letter-spacing: .11em;
  color: var(--brass); margin-bottom: 8px;
}
.explainer dl { display: grid; gap: 4px 14px; margin: 0; }
@media (min-width: 600px) { .explainer dl { grid-template-columns: auto 1fr; } }
.explainer dt { color: var(--ink-mid); font-size: 14px; }
.explainer dd { margin: 0; font-weight: 600; font-size: 14px; }
.explainer .why { margin-top: 10px; font-size: 14px; color: var(--ink-mid); max-width: 66ch; }

/* ---- coming up --------------------------------------------- */
.upcoming { display: flex; gap: 10px; overflow-x: auto; padding-bottom: 4px; }
.upcoming::-webkit-scrollbar { height: 6px; }
.upcoming::-webkit-scrollbar-thumb { background: var(--hair-strong); border-radius: 3px; }
.up-card {
  flex: 0 0 auto; min-width: 190px; max-width: 260px;
  padding: 11px 13px; border: 1px solid var(--hair); border-radius: var(--radius);
  background: var(--card-bg); text-decoration: none; color: inherit;
}
.up-card:hover { border-color: var(--brass); box-shadow: var(--shadow); }
.up-card .when { font-size: 12px; color: var(--ink-muted); font-family: var(--font-num); }
.up-card .what { font-weight: 600; margin-top: 3px; color: var(--accent); line-height: 1.35; }
.up-card .rel { font-size: 12px; color: var(--ink-muted); margin-top: 4px; }

/* ---- action row -------------------------------------------- */
.actions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 20px; }
.btn {
  display: inline-flex; align-items: center; gap: 7px;
  min-height: 44px; padding: 0 16px; border-radius: var(--radius-sm);
  border: 1px solid var(--hair-strong); background: var(--surface);
  color: var(--ink); font: inherit; font-size: 14px; font-weight: 600;
  text-decoration: none; cursor: pointer;
}
.btn:hover { border-color: var(--brass); background: var(--brass-soft); color: var(--ink); }
.btn.primary { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
.btn.primary:hover { background: var(--accent-deep); border-color: var(--accent-deep); color: var(--on-accent); }
.btn.ghost { background: transparent; border-color: transparent; color: var(--structure); }
.btn.ghost:hover { background: var(--structure-soft); }

/* ---- month calendar ---------------------------------------- */
/* The toolbar above the frame. Stepping to another month lives in the
   masthead now (.am-nav), so what is left acts on the month being shown:
   the format switch, centred over the calendar the way the month plate
   below it is, and Print at the right edge. The three columns are what
   keeps the switch on the page's centre line and not on the centre of
   whatever is left over beside the button. */
.cal-head {
  display: grid; grid-template-columns: 1fr auto 1fr;
  align-items: center; gap: 10px; margin-bottom: 12px;
}
.cal-head .cal-view { grid-column: 2; justify-self: center; }
.cal-head .cal-print { grid-column: 3; justify-self: end; }

/* The sheet: masthead and grid inside ONE frame, the way a printed calendar
   is framed. On paper this box is the square (see the print rules) and the
   bands above and below it are the owner's. */
.calsheet {
  display: flex; flex-direction: column;
  border: 2px solid var(--kumkuma-deep); border-radius: 3px;
  background: var(--surface); overflow: hidden;
}

/* The ornamental frame around the sheet: a kolam chain — kumkuma lozenges
   and dots on pasupu, the pattern and the two colours of a threshold
   drawing — between two kumkuma rules. It is one repeating tile, symmetric
   on both axes, so it runs the same way down the sides as along the top
   and needs no corner pieces. Chrome only: it rings the calendar and never
   fills a cell (CLAUDE.md §0). */
.calframe {
  padding: 11px;
  border: 2px solid var(--kumkuma-deep); border-radius: 6px;
  background-color: var(--pasupu);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 16 16'%3E%3Crect width='16' height='16' fill='%23FFC40C'/%3E%3Cpath d='M8 2.2 13.8 8 8 13.8 2.2 8Z' fill='%23B31B1B'/%3E%3Ccircle cx='8' cy='8' r='1.7' fill='%23FFF1B8'/%3E%3Ccircle cx='0' cy='0' r='1.6' fill='%238C1515'/%3E%3Ccircle cx='16' cy='0' r='1.6' fill='%238C1515'/%3E%3Ccircle cx='0' cy='16' r='1.6' fill='%238C1515'/%3E%3Ccircle cx='16' cy='16' r='1.6' fill='%238C1515'/%3E%3C/svg%3E");
  background-size: 16px 16px; background-position: 1px 1px;
  -webkit-print-color-adjust: exact; print-color-adjust: exact;
}
@media (max-width: 599px) { .calframe { padding: 7px; background-size: 11px 11px; } }

/* The banner slot above the frame, the width of the calendar. */
.cal-ad { margin-bottom: 12px; }
.cal-ad:empty { display: none; }

/* ---- the format switch: links drawn as a segmented control ---- */
.seg-toggle a.seg {
  display: inline-flex; align-items: center; min-height: 36px; padding: 0 16px;
  background: var(--surface-alt); color: var(--ink-mid);
  font-size: 13px; font-weight: 600; text-decoration: none;
}
.seg-toggle a.seg + a.seg { border-left: 1px solid var(--hair-strong); }
.seg-toggle a.seg[aria-current] { background: var(--structure); color: var(--on-structure); }
.seg-toggle a.seg:focus-visible { outline: 3px solid var(--pasupu); outline-offset: -3px; }

/* Reserved page regions. They exist only on paper; the artwork and the
   footer line that go in them are the owner's to supply, and until they
   arrive these hold the proportions rather than pretending to content. */
.print-band { display: none; }

/* ---- the almanac masthead ---- */
/* The month heading — the banner — is shown at EVERY width; what changes is
   where the two information blocks go.
     laptop  (≥900px)  one row:  left block · banner · right block
     tablet  (600–899) banner across the top, the two blocks below it as a
                       pair of plain cards side by side
     phone   (<600px)  banner, then each block as its own card, one per row
   The banner is last in the markup's middle but first in reading order on
   a narrow screen, so the placement is by grid area, not by source order.
   Because the banner always names the month, the nav row's own title is
   never needed on these two pages and is hidden at every width. */
.cal-almanac {
  display: grid; gap: 8px 18px; grid-template-columns: 1fr;
  grid-template-areas: "mid" "left" "right";
  border-bottom: 2px solid var(--kumkuma-deep);
  background: var(--surface-alt); padding: 10px 14px;
  font-size: 13px; color: var(--ink-mid);
}
.cal-almanac .am-left { grid-area: left; }
.cal-almanac .am-mid { grid-area: mid; }
.cal-almanac .am-right { grid-area: right; }
@media (min-width: 900px) {
  .cal-almanac { grid-template-columns: 1fr auto 1fr; grid-template-areas: "left mid right"; align-items: center; }
  .cal-almanac .am-right { text-align: right; }
}
@media (max-width: 899px) {
  .cal-almanac { padding: 10px; font-size: 12.5px; gap: 8px; }
  .cal-almanac .am-sv { font-size: 13px; }
  .cal-almanac .am-left, .cal-almanac .am-right {
    background: var(--surface); border: 1px solid var(--hair-strong);
    border-radius: 8px; padding: 8px 10px;
  }
  .cal-almanac .am-year, .cal-almanac .am-month { font-size: 24px; }
}
@media (min-width: 600px) and (max-width: 899px) {
  .cal-almanac { grid-template-columns: 1fr 1fr; grid-template-areas: "mid mid" "left right"; }
}
.cal-almanac .am-line { line-height: 1.45; }
.cal-almanac .am-sv { font-weight: 700; font-size: 14px; color: var(--structure); }
.cal-almanac .am-masa { font-weight: 700; color: var(--brass-ink); }
.cal-almanac .am-mid { text-align: center; }
/* ---- the month step, in the masthead ---- */
/* One link on each side of the month plate: the commonest move on this page,
   put where the month it steps from is named. The chevron is the target and
   is set large — it is read across a room-lit phone held at arm's length,
   which the 14px caret in the old toolbar was not. The name beside it goes
   when the row gets narrow; the arrow and its aria-label still say which
   month it leads to. Green, the structure colour: kumkuma stays chrome. */
.cal-almanac .am-navrow {
  display: flex; align-items: center; justify-content: center; gap: 10px;
}
.cal-almanac .am-plate { min-width: 0; }
.cal-almanac .am-nav {
  display: inline-flex; align-items: center; gap: 4px;
  flex: 0 0 auto; min-height: 44px; padding: 0 8px; border-radius: 10px;
  color: var(--structure); font-size: 14px; font-weight: 600;
  text-decoration: none; white-space: nowrap;
}
.cal-almanac .am-nav:hover { background: var(--structure-soft); }
.cal-almanac .am-nav:focus-visible { outline: 3px solid var(--pasupu); outline-offset: 2px; }
.cal-almanac .am-arrow { width: 30px; height: 30px; flex: 0 0 auto; }
/* A masa with no neighbour on one side keeps that side's width, so the
   plate stays on the centre line rather than sliding across. */
.cal-almanac .am-nav-gap { display: inline-block; width: 44px; min-height: 44px; }
@media (max-width: 899px) {
  .cal-almanac .am-navrow { gap: 6px; }
  .cal-almanac .am-arrow { width: 26px; height: 26px; }
}
@media (max-width: 640px) { .cal-almanac .cal-navname { display: none; } }
/* The banner a printed calendar sets its month in: the year and the month
   on a kumkuma plate edged in pasupu, the English name beneath. White on
   kumkuma is 6.8:1, pasupu on kumkuma-deep 5.9:1. */
.cal-almanac .am-banner {
  display: inline-flex; align-items: baseline; gap: 12px;
  padding: 5px 18px 7px; border-radius: 10px;
  background: linear-gradient(135deg, var(--kumkuma-deep), var(--kumkuma));
  box-shadow: inset 0 0 0 2px var(--pasupu);
  -webkit-print-color-adjust: exact; print-color-adjust: exact;
}
.cal-almanac .am-year {
  font-size: 30px; font-weight: 700; line-height: 1.1; color: #FFFFFF;
}
.cal-almanac .am-month {
  font-size: 30px; font-weight: 700; line-height: 1.25; color: var(--pasupu);
}
.cal-almanac .am-en {
  margin-top: 4px; font-size: 14px; font-weight: 800; letter-spacing: .14em;
  text-transform: uppercase; color: var(--accent-deep);
}
/* On a masa page the line under the banner is the Gregorian span in the
   reader's own script. Tracking and uppercasing are Latin typography;
   letter-spaced Telugu pulls conjuncts apart, so this line has neither. */
.cal-almanac .am-en.am-sub { font-size: 13px; letter-spacing: 0; text-transform: none; }
/* Provenance, not a heading: the tradition and its review state sit at the
   foot of the masthead in the smallest size on the band, and the second
   language rides inline rather than breaking the line in two. */
.cal-almanac .am-trad { font-size: 11.5px; color: var(--ink-muted); margin-top: 2px; }
.cal-almanac .am-trad .gloss { display: inline; font-size: 1em; }
.cal-almanac .am-trad .gloss::before { content: " "; }
.cal-almanac .unrev { color: var(--accent); font-weight: 600; }

/* ---- the grid ---- */
/* Every cell is one size: the columns are equal fractions and the rows are
   one fixed height, so the grid reads as a printed table rather than as
   boxes that grew to their contents. `auto` is the upper bound rather than
   the rule — a row with an unusually long festival name grows instead of
   clipping an Indic word (R6). The traditional layout is wider than a phone,
   so it scrolls sideways with the weekday stub pinned; the week layout stays
   seven columns at every width and sheds detail instead. The scroll
   container, not the grid, carries the frame, so the sticky stub has a
   scroll parent to stick to. */
.cal-scroll {
  overflow-x: auto; overscroll-behavior-x: contain;
  background: var(--cal-line);
}
/* Every cell is ruled off from its neighbours by a light line — the grid's
   own background showing through a 1px gap. It has to be visible against
   every masa tint and against the moon cells' dark, or a festival name at
   the foot of one cell reads as belonging to the date at the head of the
   cell below. */
.cal, .cal-scroll { --cal-line: #C4BFA3; }
:root[data-theme="dark"] .cal, :root[data-theme="dark"] .cal-scroll { --cal-line: #4A5044; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .cal, :root:not([data-theme="light"]) .cal-scroll { --cal-line: #4A5044; }
}
.cal {
  --cellh: 116px;
  display: grid; gap: 1px; background: var(--cal-line);
  /* `1fr` in a grid of no fixed height resolves to the TALLEST row, so every
     row takes that height: a busy week makes the whole month a little
     taller rather than making one row taller than the rest. */
  grid-auto-rows: minmax(var(--cellh), 1fr);
}

.cal-week { grid-template-columns: repeat(7, minmax(0, 1fr)); grid-template-rows: auto; }
/* The stub is at least --stub wide and grows to the longest weekday name,
   so a name is never broken or spilled into the first week's cells. */
.cal-trad {
  --stub: 128px; --colmin: 132px;
  grid-template-columns: minmax(var(--stub), max-content) repeat(var(--weeks), minmax(var(--colmin), 1fr));
}

/* ---- the weekday stub (traditional) ---- */
.cal-trad .wd-stub {
  position: sticky; left: 0; z-index: 2;
  background: var(--surface-sunk); padding: 8px 10px;
  display: flex; flex-direction: column; gap: 4px; justify-content: center;
  box-shadow: 1px 0 0 var(--hair-strong);
}
/* A weekday name is one word, and a word is never broken (R6): "మంగళవారం"
   over two lines as "మంగళవా / రం" is a clipped conjunct by another route.
   The stub is sized to hold the longest name whole instead. */
.wd-name {
  font-weight: 700; font-size: 12.5px; color: var(--ink); line-height: 1.25;
  overflow-wrap: normal; word-break: keep-all; white-space: nowrap;
}
.wd-rahu { display: flex; flex-direction: column; font-size: 10px; line-height: 1.3; }
.wd-rahu .k {
  text-transform: uppercase; letter-spacing: .05em; font-weight: 700;
  font-size: 9px; color: var(--ink-muted);
}
.wd-rahu .num { font-family: var(--font-num); font-weight: 600; color: var(--ashubha-ink); }

/* ---- the weekday heading (week) ---- */
.cal-week .dow abbr { text-decoration: none; border: 0; cursor: inherit; }
.cal-week .dow {
  background: var(--surface-sunk); padding: 7px 4px; text-align: center;
  font-size: 11px; text-transform: uppercase; letter-spacing: .07em;
  color: var(--ink-muted); font-weight: 700;
}
.cal-week .dow .wd-rahu { align-items: center; text-transform: none; letter-spacing: 0; margin-top: 2px; }

/* ---- a day cell ---- */
/* The masa paints the cell. `--masa` is set inline per day; a cell with no
   day has none and falls back to the surface. The paint is a layer rather
   than a background so dark mode can drop it to a wash and keep the theme's
   own ink, instead of a light-mode pastel with light-mode text stranded on
   a dark page. */
.cal .cell {
  position: relative; isolation: isolate;
  background: var(--surface); padding: 6px 7px 9px;
  display: flex; flex-direction: column; gap: 2px; align-items: stretch;
  border: 0; font: inherit; color: var(--ink); text-align: left; cursor: pointer;
  text-decoration: none;   /* the whole cell is the link; underlining it is noise */
  overflow: hidden;
}
.cal .cell::before {
  content: ""; position: absolute; inset: 0; z-index: -1;
  background: var(--masa, transparent);
}
:root[data-theme="dark"] .cal .cell::before { opacity: .2; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .cal .cell::before { opacity: .2; }
}
.cal .cell:hover::before { filter: brightness(.96); }
.cal .cell.blank { background: var(--surface-sunk); cursor: default; }

.cal .cell .dline { display: flex; align-items: center; justify-content: space-between; gap: 4px; }
.cal .cell .d { font-family: var(--font-num); font-weight: 700; font-size: 16px; line-height: 1.1; }

/* The moon as it is lit that morning. Decorative — the tithi name beside it
   and the cell's aria-label both say it in words. */
/* Solid, not tinted: the whole point is the boundary between the lit and
   the unlit half, and at fourteen pixels that boundary only reads if both
   sides are opaque. The same two colours work on every masa tint and in
   either theme, so the moon is the one thing on the page that does not
   change with the ground under it. */
.moon { width: 14px; height: 14px; flex: none; display: block; }
.moon .m-dark { fill: #4A4A3D; }
.moon .m-lit { fill: #FFFFFF; }
.moon .m-ring { fill: none; stroke: #4A4A3D; stroke-width: 1; }
.cal-legend .legend-moon { display: inline-block; vertical-align: -2px; }

/* One reading: the name, then the time it ends. R6 — never clip; a long
   nakshatra wraps to a second line rather than becoming "Uttarabhadr…",
   which in an Indic script could change a word. */
.cal .cell .rd {
  display: block; font-size: 11px; line-height: 1.35; color: var(--ink-mid);
}
.cal .cell .rd .nm { font-weight: 600; color: var(--ink); }
/* A clock time is Latin numerals and reads as one token, so it never breaks
   across lines — "15:42–" over "17:07" is unreadable at this size. The Indic
   NAME beside it still wraps freely, which is the rule that matters (R6). */
.cal .cell .rd .num {
  font-family: var(--font-num); font-size: 10px; color: var(--ink-mid); margin-left: 4px;
  white-space: nowrap;
}
.cal .cell .rd .spill { font-weight: 700; }

/* Varjyam and durmuhurtam. The chip is the encoding — a letter in the
   reader's own script on its own ground — and the times beside it are plain
   ink. Red text directly on a masa tint is the one combination that cannot
   be made to clear AA on every colour in the palette, and the chip carries
   its own background, so it always can.
   Flex, not a text indent: the chip is an inline-flex box, and a negative
   text-indent drags its own glyph out of it. */
.cal .cell .rd.win {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 0 2px; color: var(--ink-mid);
}
.cal .cell .rd.win .num { color: var(--ink-mid); margin-left: 0; }
.cal .cell .rd.win .wsep { margin: 0 3px; color: var(--ink-muted); }
.cal .cell .rd.win .wa { flex: none; }
/* The abbreviation is a WORD in the reader's script — వ, ವ, व, વ — not a
   one-letter glyph in a fixed box. So the chip grows to the text and holds a
   script line-height; a squeezed conjunct is the same failure as a clipped
   one (R6). */
.wa {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 15px; padding: 0 3px; border-radius: 3px; margin-right: 4px;
  font-style: normal; font-size: 10px; font-weight: 700; line-height: 1.6;
  background: var(--ashubha-soft); color: var(--ashubha-ink); vertical-align: 1px;
  box-shadow: inset 0 0 0 1px var(--ashubha-ink);
}

/* A festival is named in ink and marked with a dot, not written in a colour:
   the tints under it run from a pale yellow to a strong coral, and no single
   red clears AA on all of them. */
.cal .cell .marks { margin-top: auto; padding-top: 3px; display: flex; flex-direction: column; gap: 2px; }
.cal .cell .fname, .cal-legend .fname {
  font-size: 10px; line-height: 1.25; color: var(--ink); font-weight: 700;
}
.cal .cell .fname::before, .cal-legend .fname::before {
  content: "●"; color: var(--accent); font-size: 7px; vertical-align: 2px; margin-right: 3px;
}
.cal-legend .fname { font-size: 12px; }

/* Today and the selected day are rings, not fills — a fill would argue with
   the masa the cell already carries. */
.cal .cell.today { box-shadow: inset 0 0 0 2px var(--accent); }
.cal .cell.sel { box-shadow: inset 0 0 0 2px var(--brass); }

/* ---- the printed-calendar look ---- */
/* Numerals as a printed Hindu calendar sets them: large, a deep indigo, and
   red on a Sunday or a day that carries an observance. The red is the
   theme's accent-deep, so it lightens in dark mode instead of sinking into
   the ground. Either colour only repeats what the cell already says. */
.cal { --num: #1F2A6B; }
:root[data-theme="dark"] .cal { --num: var(--ink); }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .cal { --num: var(--ink); } }
.cal .cell .d { font-size: 22px; line-height: 1; color: var(--num); }
.cal .cell.sun .d, .cal .cell.fest .d, .cal .cell.today .d { color: var(--accent-deep); }

/* The weekday stub is a tile: the name large and bold, Sunday in red, and
   rahu kalam set under it the way the printed stub carries it. */
.cal-trad .wd-stub { background: var(--pasupu-soft); border-left: 4px solid var(--kumkuma-deep); }
.cal-trad .wd-stub .wd-name { font-size: 14px; color: var(--num); }
.cal-trad .wd-stub.sun .wd-name, .cal-week .dow.sun abbr { color: var(--accent-deep); }
:root[data-theme="dark"] .cal-trad .wd-stub { background: var(--surface-sunk); }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .cal-trad .wd-stub { background: var(--surface-sunk); }
}

/* ---- the festival list in the empty cells ---- */
.cal .fest-cell {
  background: var(--surface-alt); cursor: default; padding: 6px 8px; gap: 3px;
  font-size: 10.5px; line-height: 1.3;
}
.cal .fest-cell .fl-title {
  font-size: 10px; font-weight: 800; letter-spacing: .06em; text-transform: uppercase;
  color: var(--accent-deep); margin-bottom: 2px;
}
.fest-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 2px; }
.fest-list li { break-inside: avoid; overflow-wrap: anywhere; }
.fest-list a { color: var(--ink); text-decoration: none; }
.fest-list a:hover { text-decoration: underline; }
.fest-list b { display: inline-block; min-width: 1.6em; color: var(--accent-deep); font-weight: 700; }
.fest-list .more a { color: var(--structure); font-weight: 600; }
/* In the week layout the run is one merged cell: the list flows down, then
   across, one column per grid column it spans. */
.cal .fest-cell.fest-wide .fest-list { display: block; columns: var(--fcols, 1); column-gap: 14px; }
.cal .fest-cell.fest-wide .fest-list li { margin-bottom: 2px; }

/* The masa's month mark beside the numeral: a masa straddles two Gregorian
   months, so its first day and the 1st of the next month name the month. */
.cal .cell .mmark {
  margin-left: 6px; margin-right: auto; align-self: center;
  font-size: 10.5px; font-weight: 700; letter-spacing: .02em; color: var(--ink-mid);
}

/* ---- Chandra Masam: the paksha is the ground ----
   Shukla paksha days are white with black text; Krishna paksha days are a
   slate grey with light text (7.5:1). The colours are absolute, not theme
   tokens — the page is a printed sheet and reads the same in either theme —
   so each ground re-points the ink tokens the cell rules already use, and
   every line, numeral, time and festival name follows without a rule of its
   own. The varjyam/durmuhurtam chip keeps its light-theme pair on both,
   because it carries its own ground. */
.moon-cell {
  --ashubha-soft: #FBDCDC; --ashubha-ink: #B71C1C;
  -webkit-print-color-adjust: exact; print-color-adjust: exact;
}
.moon-cell.wax {
  background: #FFFFFF;
  --ink: #111114; --ink-mid: #26262C; --ink-muted: #55555E;
  --num: #1F2A6B; --accent: #C62828; --accent-deep: #B71C1C;
}
.moon-cell.wane {
  background: #4E525C;
  --ink: #FAFAF5; --ink-mid: #ECECE4; --ink-muted: #CFCFC6;
  --num: #FFFFFF; --accent: #FF9C8F; --accent-deep: #FFBBB0;
}
.cal .moon-cell::before { display: none; }
/* The moon glyph's unlit half and rim are dark ink; on the grey ground they
   would vanish, so there the rim turns light and the unlit half deepens. */
.moon-cell.wane .moon .m-dark { fill: #25272D; }
.moon-cell.wane .moon .m-ring { stroke: #F0F0EA; }
.cal .moon-cell.today { box-shadow: inset 0 0 0 3px var(--accent); }

/* The legend's paksha key: one swatch of each ground. */
.mc-key {
  display: inline-block; width: 14px; height: 18px; flex: none;
  border: 1px solid var(--cal-line, #C4BFA3); border-radius: 2px;
}

.cal-legend {
  display: flex; flex-wrap: wrap; gap: 6px 16px; margin-top: 10px;
  font-size: 12px; color: var(--ink-muted);
}
.cal-legend span { display: inline-flex; align-items: center; gap: 5px; }
/* The legend's colour chips. Each one sits NEXT TO the word it stands for,
   so the colour is never carrying the meaning by itself. */
.cal-legend .swatch {
  display: inline-block; width: 12px; height: 12px; border-radius: 3px; flex: none;
}
/* The festival entry is the word itself, dotted the way a festival name is
   dotted in a cell — the sample IS the label, so there is nothing to
   mis-pair. Styling lives with the cell rule above. */

.day-peek {
  margin-top: 14px; border: 1px solid var(--brass); border-left-width: 3px;
  border-radius: var(--radius); background: var(--surface); padding: 14px;
}
.day-peek .pk-date { font-weight: 700; font-size: 16px; }
.day-peek .pk-line { font-size: 14px; color: var(--ink-mid); margin-top: 5px; font-family: var(--font-num); }

/* ---- festival list ----------------------------------------- */
.filters { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 14px; }
.filters button {
  min-height: 38px; padding: 0 13px; border-radius: 999px;
  border: 1px solid var(--hair-strong); background: var(--surface);
  color: var(--ink-mid); font: inherit; font-size: 13px; font-weight: 600; cursor: pointer;
}
.filters button[aria-pressed="true"] {
  background: var(--structure); border-color: var(--structure); color: var(--on-structure);
}

.fest {
  display: grid; grid-template-columns: 76px 1fr; gap: 12px;
  padding: 14px 0; border-bottom: 1px solid var(--hair);
}
@media (min-width: 600px) { .fest { grid-template-columns: 92px 1fr; gap: 16px; } }
.fest .date {
  text-align: center; padding: 6px 0; border-radius: var(--radius-sm);
  background: var(--surface-sunk); align-self: start;
}
.fest .date .m {
  font-size: 10px; text-transform: uppercase; letter-spacing: .04em; line-height: 1.25;
  color: var(--ink-muted); font-weight: 700; padding: 0 3px; overflow-wrap: anywhere;
}
.fest .date .d { font-family: var(--font-num); font-size: 21px; font-weight: 700; line-height: 1.15; }
.fest .date .w { font-size: 11px; color: var(--ink-muted); }
.fest .name { font-size: 17px; font-weight: 600; color: var(--accent); line-height: 1.35; }
.fest .name .roman { display: block; font-size: 12px; font-weight: 400; color: var(--ink-muted); font-family: var(--font-ui); }
.fest .sub { font-size: 13px; color: var(--ink-mid); margin-top: 3px; }
.fest .times { font-size: 13px; color: var(--ink-muted); font-family: var(--font-num); margin-top: 4px; }
.fest .tags { display: flex; flex-wrap: wrap; gap: 5px; margin-top: 7px; }
.fest.elsewhere { opacity: .62; }
.fest.elsewhere .name { color: var(--ink-mid); }
.fest.elsewhere .date { background: transparent; border: 1px dashed var(--hair-strong); }

/* ---- form fields: settings sheet, settings page, sankalpam ------- */
.range { display: flex; flex-wrap: wrap; gap: 10px; align-items: flex-end; margin-top: 14px; }
.field { display: flex; flex-direction: column; gap: 4px; }
.field label { font-size: 12px; text-transform: uppercase; letter-spacing: .07em; color: var(--ink-muted); font-weight: 600; }
.field input, .field select {
  min-height: 44px; padding: 0 11px; border-radius: var(--radius-sm);
  border: 1px solid var(--hair-strong); background: var(--surface);
  color: var(--ink); font: inherit; font-size: 15px;
}

/* ---- sankalpam --------------------------------------------- */
.sankalpam-text {
  font-family: var(--font-display); font-size: 20px; line-height: 2;
  padding: 18px; border-radius: var(--radius);
  background: var(--surface-alt); border: 1px solid var(--brass);
}
body.script-telugu   .sankalpam-text { font-family: "Noto Serif Telugu", var(--font-indic); }
body.script-kannada  .sankalpam-text { font-family: "Noto Serif Kannada", var(--font-indic); }
body.script-gujarati .sankalpam-text { font-family: "Noto Serif Gujarati", var(--font-indic); }
.sankalpam-text .line { display: block; }
/* The terms in colour are the ones that change every day. */
.sankalpam-text .val { color: var(--accent); font-weight: 600; }
.sankalpam-text .blank {
  display: inline-block; min-width: 5em; border-bottom: 2px dotted var(--brass);
}
.sk-size-1 .sankalpam-text { font-size: 20px; }
.sk-size-2 .sankalpam-text { font-size: 26px; line-height: 1.95; }
.sk-size-3 .sankalpam-text { font-size: 33px; line-height: 1.9; }

/* ---- modal / sheet ----------------------------------------- */
.scrim {
  position: fixed; inset: 0; z-index: 60; background: rgba(20,16,12,.5);
  display: grid; place-items: end center; padding: 0;
}
@media (min-width: 768px) { .scrim { place-items: center; padding: 24px; } }
.scrim[hidden] { display: none; }
.sheet {
  width: 100%; max-width: 720px; max-height: 88vh; overflow: auto;
  background: var(--surface); border: 1px solid var(--hair-strong);
  border-radius: 14px 14px 0 0; box-shadow: var(--shadow-lift);
}
@media (min-width: 768px) { .sheet { border-radius: 14px; max-height: 84vh; } }
.sheet-head {
  position: sticky; top: 0; background: var(--surface); z-index: 1;
  display: flex; align-items: center; justify-content: space-between;
  gap: 10px; padding: 14px 16px; border-bottom: 1px solid var(--hair);
}
.sheet-head h2 { font-size: 17px; }
.sheet-body { padding: 14px 16px; }
.sheet-foot {
  position: sticky; bottom: 0; background: var(--surface-alt);
  border-top: 1px solid var(--hair); padding: 12px 16px;
}

.two-pane { display: grid; gap: 18px; }
@media (min-width: 640px) { .two-pane { grid-template-columns: 1fr 1fr; gap: 22px; } }
.pane-label {
  font-size: 11px; text-transform: uppercase; letter-spacing: .11em;
  color: var(--ink-muted); font-weight: 700; margin-bottom: 8px;
}
.opt {
  display: flex; align-items: flex-start; gap: 10px; width: 100%;
  padding: 10px; border-radius: var(--radius-sm); border: 1px solid transparent;
  background: none; font: inherit; color: inherit; text-align: left; cursor: pointer;
  min-height: 44px;
}
.opt:hover { background: var(--surface-alt); }
.opt[aria-pressed="true"] { border-color: var(--accent); background: var(--accent-soft); }
.opt .radio {
  width: 17px; height: 17px; flex: 0 0 17px; margin-top: 3px; border-radius: 50%;
  border: 2px solid var(--hair-strong);
}
.opt[aria-pressed="true"] .radio { border-color: var(--accent); background: var(--accent); box-shadow: inset 0 0 0 3px var(--surface); }
.opt .t { font-weight: 600; }
.opt .s { font-size: 12px; color: var(--ink-muted); display: block; }
.opt.disabled { opacity: .48; cursor: not-allowed; }

.search-input {
  width: 100%; min-height: 44px; padding: 0 12px; border-radius: var(--radius-sm);
  border: 1px solid var(--hair-strong); background: var(--surface);
  color: var(--ink); font: inherit; font-size: 16px;
}
.results { margin-top: 8px; display: flex; flex-direction: column; }
.results button {
  display: block; width: 100%; text-align: left; padding: 11px 10px; min-height: 44px;
  background: none; border: 0; border-bottom: 1px solid var(--hair);
  font: inherit; color: inherit; cursor: pointer;
}
.results button:hover { background: var(--surface-alt); }
.results .r-name { font-weight: 600; }
.results .r-sub { font-size: 12px; color: var(--ink-muted); }

/* The consequence panel: what this preset actually gives you. It is what
   turns an opaque setting into an informed choice. */
.consequence { font-size: 13px; color: var(--ink-mid); line-height: 1.6; }
.consequence strong { color: var(--ink); }
.consequence .unreviewed {
  display: block; margin-top: 8px; padding: 8px 10px; border-radius: var(--radius-sm);
  background: var(--accent-soft); color: var(--accent); font-weight: 600; font-size: 12px;
}

/* ---- tables (methodology, regions) ------------------------- */
.table-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }
table.data { border-collapse: collapse; width: 100%; min-width: 560px; font-size: 14px; }
table.data th, table.data td {
  text-align: left; padding: 9px 12px; border-bottom: 1px solid var(--hair);
  vertical-align: top;
}
table.data th {
  font-size: 11px; text-transform: uppercase; letter-spacing: .08em;
  color: var(--ink-muted); font-weight: 700; background: var(--surface-sunk);
}
table.data tr:last-child td { border-bottom: 0; }

.prose { max-width: 68ch; }
.prose h2 { font-size: 20px; margin: 28px 0 8px; color: var(--structure); }
.prose h3 { font-size: 16px; margin: 20px 0 6px; }
.prose p { margin: 0 0 12px; color: var(--ink-mid); }
.prose ul { margin: 0 0 14px; padding-left: 20px; color: var(--ink-mid); }
.prose li { margin-bottom: 5px; }

.note {
  border-left: 3px solid var(--brass); background: var(--brass-soft);
  padding: 12px 14px; border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
  font-size: 14px; color: var(--ink-mid); margin: 14px 0;
}
.note strong { color: var(--ink); }

/* ---- footer ------------------------------------------------ */
.site-foot {
  border-top: 1px solid var(--hair); margin-top: 40px;
  padding: 22px 0 30px; background: var(--ground-deep);
}
.appfoot {
  display: flex; flex-direction: column; align-items: center; gap: 10px;
  padding: 0 16px 18px; margin-bottom: 18px; border-bottom: 1px solid var(--hair);
}
@media (min-width: 768px) { .appfoot { display: none; } }
.appfoot .ftitle {
  font-size: 11px; text-transform: uppercase; letter-spacing: .09em; color: var(--ink-muted); font-weight: 700;
}
.site-foot .links { display: flex; flex-wrap: wrap; gap: 8px 20px; font-size: 14px; }
.site-foot .links a { color: var(--structure); text-decoration: none; }
.site-foot .links a:hover { text-decoration: underline; }
.site-foot .provenance {
  margin-top: 12px; font-size: 12px; color: var(--ink-muted); max-width: 70ch; line-height: 1.6;
}

.empty { padding: 26px 0; color: var(--ink-muted); font-size: 15px; }

/* ---- print (R12) ------------------------------------------- */
/* Portrait, with a margin wide enough that no printer's unprintable edge
   eats the calendar's frame. Orientation only — the paper size is the
   reader's, and the sheet below is sized as a fraction of it rather than
   assuming A4. */
@page { size: portrait; margin: 10mm; }

@media print {
  :root { --ground: #fff; --surface: #fff; --card-bg: #fff; --ink: #000; --ink-mid: #222; --ink-muted: #555; }
  body { background: #fff; color: #000; font-size: 11pt; padding: 0; }
  .topbar, .contextbar, .bottomnav, .actions, .filters, .seg-toggle,
  .icon-btn, .datenav, .scrim, .site-foot .links, .appfoot,
  .ad, .adrail, .menusheet { display: none !important; }
  .page-layout.has-rail { display: block; padding: 0; }
  .cardgrid { grid-template-columns: 1fr 1fr !important; grid-template-areas: none !important; }
  .cardgrid > * { grid-area: auto !important; }
  .cardgrid .c-hora { grid-column: 1 / -1 !important; }
  .side { display: contents !important; }
  .timing.running, .hr.running { background: none; box-shadow: none; }
  main { padding: 0; }
  .card { box-shadow: none; border: 1px solid #999; break-inside: avoid; page-break-inside: avoid; }
  /* ---- the month sheet on paper ----
     One portrait page: a band for the masthead artwork, the calendar as a
     SQUARE, and a band under it. Both bands are the owner's to fill; their
     depths are placeholders and will be set to the artwork when it arrives.
     They are given in mm and kept modest so the three together fit US Letter
     (259mm of content height) as well as A4 (277mm) — on A4 the slack falls
     below the bottom band rather than stretching anything.

     There is no scrolling and no viewport here, so the grid prints whole:
     the sideways scroll is released, the pinned weekday stub stops being
     sticky, and the row height becomes an equal fraction of the square
     instead of a pixel floor. A month is the unit that must not break
     across pages. */
  .cal-month, .cal-legend, .page-note, .upcoming, .section-label { display: none !important; }
  .print-band { display: block !important; }
  .band-top { height: 34mm; }
  .band-bottom { height: 18mm; }

  .cal-ad { display: none !important; }
  /* The square is the frame, ornament included; the sheet fills it. */
  .calframe {
    width: 100%; aspect-ratio: 1 / 1; display: flex; padding: 3mm;
    background-size: 3.4mm 3.4mm; break-inside: avoid; page-break-inside: avoid;
  }
  .calsheet {
    flex: 1 1 auto; min-width: 0; min-height: 0;
    border: 1.2pt solid #8C1515; border-radius: 0;
  }
  .calsheet .cal-scroll { overflow: visible !important; flex: 1 1 auto; min-height: 0; background: #999; }
  .calsheet .cal { height: 100%; background: #999; }
  .cal-trad {
    --stub: 23mm; --colmin: 0 !important;
    grid-template-rows: repeat(7, 1fr); grid-auto-rows: 1fr;
  }
  .cal-week { grid-template-rows: auto repeat(var(--weeks), 1fr); grid-auto-rows: 1fr; }
  .cal-trad .wd-stub { position: static; box-shadow: none; padding: 2mm 1.5mm; }
  .cal-trad .wd-stub .wd-name, .wd-name { font-size: 8pt; }
  .wd-rahu { font-size: 6pt; }
  .wd-rahu .k { font-size: 5.5pt; }
  .cal .cell { padding: 1.2mm 1.4mm; overflow: hidden; }
  .cal .cell .d { font-size: 13pt; }
  .cal .fest-cell { font-size: 6.2pt; padding: 1.2mm 1.4mm; }
  .cal .fest-cell .fl-title { font-size: 6pt; }
  .cal-almanac .am-nav { display: none !important; }
  .cal-almanac .am-banner { padding: 1mm 4mm 1.4mm; }
  .cal-almanac .am-year, .cal-almanac .am-month { font-size: 18pt; }
  .cal-almanac .am-en { font-size: 8pt; margin-top: 1mm; }
  .cal-trad .wd-stub { border-left-width: 2pt; }
  .cal .cell .rd { font-size: 6.6pt; line-height: 1.3; }
  .cal .cell .rd .num { font-size: 6.2pt; }
  .cal .cell .fname { font-size: 6pt; }
  .moon { width: 10px; height: 10px; }
  .wa { font-size: 6pt; min-width: 9px; line-height: 1.5; }
  .cal-almanac {
    border-color: #8C1515; border-bottom-width: 1.2pt; background: none;
    break-inside: avoid; padding: 2mm 3mm; font-size: 7.5pt;
  }
  .cal-almanac .am-sv { font-size: 8pt; }
  /* A printed page is ~720px wide, which the screen rules would read as a
     tablet. Paper always gets the one-row masthead, without the cards. */
  .cal-almanac { grid-template-columns: 1fr auto 1fr !important; grid-template-areas: "left mid right" !important; align-items: center; }
  .cal-almanac .am-right { text-align: right; }
  .cal-almanac .am-left, .cal-almanac .am-right { background: none; border: 0; padding: 0; }
  .cal-almanac .am-year, .cal-almanac .am-month { font-size: 18pt; }
  /* Print keeps the masa tints: they are the point of the page, and every
     browser's "background graphics" switch is the reader's to set. */
  .cal .cell::before { -webkit-print-color-adjust: exact; print-color-adjust: exact; }
  .grid-2 { grid-template-columns: 1fr 1fr !important; }
  a { color: #000; text-decoration: none; }
  .print-only { display: block !important; }
}
.print-only { display: none; }

/* ---- reduced motion ---------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  * { animation: none !important; transition: none !important; }
}

/* ---- content protection ------------------------------------ */
/* A deterrent layer, not protection — see public/js/protect.js.
   It must never cost keyboard navigation, focus rings, screen
   readers, or our own Copy / Share / Print buttons. */
body.protected {
  -webkit-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
}
/* Anything the reader is meant to interact with stays selectable.
   The sankalpam is the clearest case: it exists to be recited and
   passed on, so it carries data-allow-copy and opts back in. */
body.protected input,
body.protected textarea,
body.protected select,
body.protected [contenteditable="true"],
body.protected [data-allow-copy],
body.protected [data-allow-copy] * {
  -webkit-user-select: text;
  user-select: text;
}
body.protected img,
body.protected .dayhead { -webkit-user-drag: none; user-drag: none; pointer-events: auto; }

/* The devtools heuristic blurs content rather than blocking the page:
   the check is wrong often enough (zoom, sidebars, narrow windows)
   that a false positive must cost a glance, not the visit. */
body.sp-shielded main,
body.sp-shielded .dayhead {
  filter: blur(9px);
  transition: filter .12s linear;
  pointer-events: none;
}
body.sp-shielded::after {
  content: "Content hidden while developer tools are open.";
  position: fixed; inset: auto 0 50% 0; z-index: 70; text-align: center;
  font: 600 15px/1.5 var(--font-ui); color: var(--ink-muted);
  padding: 0 24px;
}
@media print { body.sp-shielded main { filter: none; } }

/* ---- calendar header on small screens ---------------------- */
@media (max-width: 767px) {
  .cal-head { gap: 8px; }
}
/* Narrow enough that the switch and the button cannot share a line: the
   switch takes the row, still centred, and Print sits under it at the
   right. */
@media (max-width: 400px) {
  .cal-head { grid-template-columns: 1fr; }
  .cal-head .cal-view { grid-column: 1; }
  .cal-head .cal-print { grid-column: 1; }
}

/* ---- the two layouts at narrow widths ---------------------- */
/* The traditional layout keeps every reading and scrolls sideways instead of
   dropping one: on a tablet or a phone the weekday stub stays pinned to the
   left edge so a column is never orphaned from the weekday it belongs to.
   Below a laptop the stub and the columns tighten, they do not shrink to
   nothing — an Indic nakshatra name has a width it cannot go under. */
@media (max-width: 1023px) {
  .cal-trad { --stub: 112px; --colmin: 126px; }
}
@media (max-width: 767px) {
  .cal-trad { --stub: 96px; --colmin: 122px; }
  .cal-trad .wd-stub { padding: 8px 7px; }
  .wd-name { font-size: 12px; }
}

/* The week layout is the opposite trade: seven columns at EVERY width, never
   a scroll, so the shape of the month is readable at a glance. A 48px column
   cannot hold four timed readings, so below a tablet it sheds them from the
   least load-bearing upward — the two windows first, then the nakshatra.
   Nothing is lost: the full day is one tap away, the cell's aria-label still
   carries every reading for a screen reader, and a reader who wants all of
   it on a phone switches to the traditional layout, which keeps it. */
@media (max-width: 767px) {
  .cal-week .cell .rd.win { display: none; }
  .cal-week .cell .rd .num { display: block; margin-left: 0; }
  .cal-week .dow .wd-rahu { display: none; }
  .cal-week { --cellh: 96px; }
}
@media (max-width: 599px) {
  .cal-week .cell .rd-n { display: none; }
  .cal-week .cell { padding: 6px 4px; }
  .cal-week .cell .fname { font-size: 9px; }
  .cal-week { --cellh: 80px; }
}

/* ---- display options in the settings sheet ----------------- */
.display-opts { display: grid; gap: 10px; grid-template-columns: 1fr; }
@media (min-width: 560px) { .display-opts { grid-template-columns: 1fr 1fr; } }
.display-opts .field select { width: 100%; }

/* ---- lunar masa grid --------------------------------------- */
/* Laid out by tithi rather than by weekday column: a masa is 29 or 30
   tithis and does not align with a week, so a Sun–Sat grid would draw a
   Gregorian idea over a lunar one. The weekday is printed on each cell. */
.paksha-label {
  display: flex; align-items: center; gap: 8px;
  margin: 18px 0 8px; font-size: 14px; font-weight: 700; color: var(--structure);
}
.paksha-label .glyph { font-size: 17px; color: var(--brass); }

.mgrid {
  display: grid; gap: 1px; background: var(--hair);
  grid-template-columns: repeat(2, minmax(0, 1fr));
  border: 1px solid var(--hair-strong); border-radius: var(--radius); overflow: hidden;
}
@media (min-width: 560px)  { .mgrid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (min-width: 860px)  { .mgrid { grid-template-columns: repeat(5, minmax(0, 1fr)); } }
.mcell {
  background: var(--surface); padding: 9px 10px; min-height: 76px;
  display: flex; flex-direction: column; gap: 3px;
  text-decoration: none; color: inherit;
}
.mcell:hover { background: var(--surface-alt); }
.mcell .mt { font-weight: 700; font-size: 13px; line-height: 1.35; }
.mcell .mg { font-size: 11px; color: var(--ink-muted); }
.mcell .mf { font-size: 11px; color: var(--accent); font-weight: 600; line-height: 1.35; margin-top: auto; }
.mcell.today   { box-shadow: inset 0 0 0 2px var(--accent); }
.mcell.today .mt { color: var(--accent); }
.mcell.purnima  { background: var(--brass-soft); }
.mcell.amavasya { background: var(--night); }
.mcell.ekadashi .mt { color: var(--structure); }

/* ---- observance lists -------------------------------------- */
.obs-list { display: flex; flex-direction: column; }
.obs {
  display: grid; grid-template-columns: 76px 1fr; gap: 12px;
  padding: 14px 0; border-bottom: 1px solid var(--hair);
}
@media (min-width: 600px) { .obs { grid-template-columns: 92px 1fr; gap: 16px; } }
.obs:last-child { border-bottom: 0; }
/* A day already gone stays in the list — the year view is a reference, not
   a feed — but it steps back so the next one is what you land on. */
.obs.past { opacity: .55; }
.obs .date {
  text-align: center; padding: 6px 0; border-radius: var(--radius-sm);
  background: var(--surface-sunk); align-self: start;
  text-decoration: none; color: inherit; display: block;
}
.obs .date .m {
  display: block; font-size: 10px; text-transform: uppercase; letter-spacing: .04em; line-height: 1.25;
  color: var(--ink-muted); font-weight: 700; padding: 0 3px; overflow-wrap: anywhere;
}
.obs .date .d { display: block; font-family: var(--font-num); font-size: 21px; font-weight: 700; line-height: 1.15; }
.obs .date .w { display: block; font-size: 11px; color: var(--ink-muted); }
.obs .name { font-size: 17px; font-weight: 600; color: var(--accent); line-height: 1.35; }
.obs .name .roman { display: block; font-size: 12px; font-weight: 400; color: var(--ink-muted); font-family: var(--font-ui); }
.obs .name .moon-glyph { color: var(--brass); margin-right: 5px; }
.obs .sub { font-size: 13px; color: var(--ink-mid); margin-top: 3px; }
.obs .times { font-size: 13px; color: var(--ink-mid); margin-top: 5px; }
.obs .times .num { font-family: var(--font-num); font-weight: 600; }
.obs .tags { display: flex; flex-wrap: wrap; gap: 5px; margin-top: 7px; }

.obs-ul { margin: 8px 0 0; padding-left: 20px; color: var(--ink-mid); font-size: 14px; }
.obs-ul li { margin-bottom: 4px; }

/* ---- balam tables ------------------------------------------ */
.balam-grid {
  display: grid; gap: 8px;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
}
.balam-cell {
  padding: 10px 11px; border-radius: var(--radius-sm);
  border: 1px solid var(--hair); background: var(--surface);
  display: flex; flex-direction: column; gap: 2px;
}
/* R14 — the verdict is a word and a glyph, never colour alone. */
.balam-cell.good { background: var(--shubha-soft); border-color: var(--shubha); }
.balam-cell.bad  { background: var(--ashubha-soft); border-color: var(--ashubha); }
.balam-cell .bl-name { font-weight: 700; font-size: 14px; }
.balam-cell .bl-note { font-size: 11px; color: var(--ink-muted); }
.balam-cell .bl-verdict { font-size: 12px; font-weight: 700; margin-top: 2px; }
.balam-cell.good .bl-verdict { color: var(--shubha-ink); }
.balam-cell.bad  .bl-verdict { color: var(--ashubha-ink); }


/* ---- settings page ----------------------------------------- */
.opt input[type="radio"] { width: 17px; height: 17px; accent-color: var(--accent); flex: 0 0 17px; }
details summary::-webkit-details-marker { color: var(--brass); }

/* The release this page came from — what a reader quotes in a bug report. */
.site-foot .version { margin-top: 10px; font-size: 12px; color: var(--ink-muted); text-align: center; letter-spacing: .02em; }
