/* ============================================================
   Pragati365 — soothing, mobile-first stylesheet
   ============================================================ */
:root {
  --bg: #f6f8fb;
  --surface: #ffffff;
  --surface-2: #f0f4f8;
  --ink: #1f2933;
  --muted: #6b7787;
  --primary: #4f7cac;
  --primary-600: #3d6691;
  --accent: #2f9e93;
  --accent-soft: #e6f4f2;
  --border: #e6eaef;
  /* Reading canvas for the post page. Warm off-white rather than pure white:
     it lowers the contrast of a long list of dense text without dimming it, and
     it is the same paper under all three readability skins — the skin changes
     the type, not the sheet it is printed on. Print resets it to #fff. */
  --paper: #fffdf7;
  /* The tint used *on* that paper (one-liner hover, the line being spoken).
     --surface-2 is a cool blue-grey and reads as a stray UI panel on cream. */
  --paper-2: #f6f1e4;
  --ring: rgba(79, 124, 172, 0.25);
  --radius: 14px;
  --radius-sm: 9px;
  --shadow: 0 1px 2px rgba(31, 41, 51, .04), 0 6px 20px rgba(31, 41, 51, .06);
  --shadow-sm: 0 1px 3px rgba(31, 41, 51, .07);
  --maxw: 1080px;
  /* Poppins for Latin/UI. The system fallbacks matter: with `display=swap` the
     first paint uses them, so the stack has to look deliberate on its own. */
  --font: 'Poppins', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
  /* Hindi chrome under a non-default skin, and print: a text-optimised
     Devanagari face rather than a display cut. */
  --font-hi: 'Noto Sans Devanagari', 'Poppins', 'Nirmala UI', 'Mangal', system-ui, sans-serif;

  /* ---- One reading face per post-page skin, each covering BOTH scripts ----
     The one-liners are the product, and a skin that used one family for English
     and a different one for Hindi read as two half-choices rather than a look:
     the two halves of the same fact disagreed on weight, x-height and mood.
     These families all ship Latin *and* Devanagari, so a skin is a single
     typographic decision applied to both languages.
     Every fallback here also has Devanagari coverage, because the same variable
     now sets the Hindi line: dropping to 'Segoe Script' or a generic `cursive`
     would leave Devanagari to whatever the OS picks. */
  /* Handwritten — Kalam: a genuine handwriting face in both scripts, and legible
     past a headline, which matters when it carries thirty full sentences. */
  --font-hand: 'Kalam', 'Noto Sans Devanagari', 'Segoe Script', cursive;
  /* Newspaper (the default skin) — Anek Devanagari: a modern Devanagari-first
     family whose matching Latin is designed to sit beside Devanagari, so the
     two halves of a fact share one voice. Comfortable at reading sizes on
     phones and desktops alike. */
  --font-news: 'Anek Devanagari', 'Noto Sans Devanagari', 'Nirmala UI', system-ui, sans-serif;
}

* {
  box-sizing: border-box;
}

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}

body {
  margin: 0;
  font-family: var(--font);
  color: var(--ink);
  background: var(--bg);
  line-height: 1.6;
  font-size: 16px;
  -webkit-font-smoothing: antialiased;
  /* Sticky footer: main grows to fill the viewport, so a short page (e.g. an
     empty archive) still pushes the footer to the bottom instead of leaving it
     floating mid-screen. */
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}

body>main {
  flex: 1 0 auto;
}

img {
  max-width: 100%;
  height: auto;
}

a {
  color: var(--primary-600);
  text-decoration: none;
}

a:hover {
  text-decoration: underline;
}

h1,
h2,
h3 {
  line-height: 1.25;
  color: var(--ink);
  margin: 0 0 .5em;
}

.container {
  width: 100%;
  max-width: var(--maxw);
  margin: 0 auto;
  padding: 0 18px;
}

.muted {
  color: var(--muted);
}

.accent {
  color: var(--accent);
}

.skip-link {
  position: absolute;
  left: -9999px;
}

.skip-link:focus {
  left: 12px;
  top: 12px;
  background: #fff;
  padding: 8px 14px;
  border-radius: 8px;
  z-index: 100;
  box-shadow: var(--shadow);
}

/* ---------- Header / nav ---------- */
.site-header {
  position: sticky;
  top: 0;
  z-index: 50;
  background: rgba(255, 255, 255, .9);
  backdrop-filter: saturate(150%) blur(8px);
  border-bottom: 1px solid var(--border);
}

.header-inner {
  display: flex;
  align-items: center;
  gap: 14px;
  height: 62px;
}

.brand {
  display: flex;
  align-items: center;
  gap: 10px;
  font-weight: 700;
  color: var(--ink);
}

.brand:hover {
  text-decoration: none;
}

/* Logo mark. The SVG carries its own badge + gradient, so no background here. */
.brand-logo {
  display: block;
  width: 34px;
  height: 34px;
  flex: none;
}

.brand-name {
  font-size: 1.15rem;
  letter-spacing: -.01em;
}

.site-nav {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 4px;
}

.site-nav a {
  padding: 8px 12px;
  border-radius: 8px;
  color: var(--ink);
  font-weight: 500;
  font-size: .95rem;
}

.site-nav a:hover {
  background: var(--surface-2);
  text-decoration: none;
}

.site-nav a.active {
  color: var(--primary-600);
  background: var(--accent-soft);
}

/* Menu button — shared by the public header and the admin topbar, so both show
   the identical icon. The glyphs are Font Awesome (fa-bars / fa-xmark, loaded
   from the CDN in partials/head.ejs); the button keeps a fixed 44px box so the
   layout can't shift while the icon font loads. */
.nav-burger,
.admin-burger {
  display: none;
  place-items: center;
  width: 44px;
  height: 44px;
  cursor: pointer;
  color: var(--ink);
  font-size: 1.35rem;
  line-height: 1;
}

.nav-burger {
  margin-left: auto;
}

.nav-burger .icon-open,
.nav-burger .icon-close,
.admin-burger .icon-open,
.admin-burger .icon-close {
  grid-area: 1 / 1;
  transition: opacity .2s ease;
}

.nav-burger .icon-close,
.admin-burger .icon-close {
  opacity: 0;
}

/* Swap to the cross while the menu is open. The admin toggle is not a sibling
   of its button, hence :has() there. */
.nav-toggle:checked~.nav-burger .icon-open,
body:has(.admin-nav-toggle:checked) .admin-burger .icon-open {
  opacity: 0;
}

.nav-toggle:checked~.nav-burger .icon-close,
body:has(.admin-nav-toggle:checked) .admin-burger .icon-close {
  opacity: 1;
}

/* ---------- Buttons / chips ---------- */
.btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 11px 18px;
  border-radius: 999px;
  font-weight: 600;
  font-size: .95rem;
  cursor: pointer;
  border: 1px solid transparent;
  transition: .15s;
}

.btn:hover {
  text-decoration: none;
  transform: translateY(-1px);
}

.btn-primary {
  background: var(--primary);
  color: #fff;
}

.btn-primary:hover {
  background: var(--primary-600);
  color: #fff;
}

.btn-ghost {
  background: transparent;
  border-color: var(--border);
  color: var(--ink);
}

.btn-ghost:hover {
  background: var(--surface-2);
}

.chip {
  display: inline-flex;
  align-items: center;
  padding: 4px 11px;
  border-radius: 999px;
  font-size: .8rem;
  font-weight: 600;
  background: var(--accent-soft);
  color: var(--accent);
  border: 1px solid transparent;
}

.chip:hover {
  text-decoration: none;
  border-color: var(--accent);
}

/* ---------- Sections / cards ---------- */
.section {
  margin: 25px 0;
}

.section-title {
  font-size: 1.25rem;
  margin-bottom: 16px;
  position: relative;
  padding-left: 14px;
}

.section-title::before {
  content: '';
  position: absolute;
  left: 0;
  top: .15em;
  bottom: .15em;
  width: 4px;
  border-radius: 4px;
  background: linear-gradient(var(--primary), var(--accent));
}

.grid {
  display: grid;
  gap: 18px;
}

.cards {
  grid-template-columns: 1fr;
}

.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 20px;
  box-shadow: var(--shadow-sm);
  transition: .18s;
}

.card:hover {
  box-shadow: var(--shadow);
  transform: translateY(-2px);
}

.card-meta {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: .82rem;
  color: var(--muted);
  margin-bottom: 10px;
}

.card-title {
  font-size: 1.1rem;
  margin: 0 0 8px;
}

.card-excerpt {
  font-size: .92rem;
  margin: 0 0 12px;
}

.card-link {
  font-weight: 600;
  font-size: .9rem;
}

/* ---------- Breadcrumb / page head ---------- */
.breadcrumb {
  font-size: .85rem;
  color: var(--muted);
  margin: 20px 0 8px;
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
}

.breadcrumb span {
  color: var(--muted);
}

.page-head {
  margin: 8px 0 24px;
}

.page-head h1 {
  font-size: clamp(1.5rem, 4vw, 2rem);
}

/* ---------- Post ---------- */
/* The article canvas is frosted glass: semi-transparent warm paper over the
   page background with a backdrop blur. The border stays hairline-light so
   the edges read as glass, not a box. Browsers without backdrop-filter get a
   nearly-opaque paper so text keeps full contrast. Print resets it to solid
   white (see the print block). */
.post {
  position: relative;
  z-index: 1;
  background: rgba(255, 253, 247, 0.55);
  -webkit-backdrop-filter: blur(18px) saturate(140%);
  backdrop-filter: blur(18px) saturate(140%);
  border: 1px solid rgba(230, 234, 239, 0.75);
  border-radius: var(--radius);
  padding: 28px 24px;
  box-shadow: var(--shadow-sm);
  margin-bottom: 30px;
}

@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .post {
    background: rgba(255, 253, 247, 0.94);
  }
}

.post-title {
  font-size: clamp(1.5rem, 4vw, 2.1rem);
  letter-spacing: -.02em;
  margin-top: 8px;
}

.post-body {
  font-size: clamp(1.1rem, 0.95rem + 0.8vw, 1.3rem);
}

.post-body h2 {
  font-size: 1.3rem;
  margin: 1.4em 0 .6em;
}

.post-foot {
  margin-top: 24px;
  padding-top: 18px;
  border-top: 1px solid var(--border);
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 14px;
}

/* Header action cluster: the eye (read count) + the t-shirt (readability skin).
   Grouped so both sit as one flex:none unit and never get pushed out of the
   corner by a long, wrapping title (see .post-head-top below). */
.post-head-actions {
  display: flex;
  align-items: center;
  gap: 8px;
  flex: none;
  margin-top: 14px;
}

.skin-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  padding: 0;
  border-radius: 999px;
  border: 1px solid var(--border);
  background: var(--surface-2);
  color: var(--muted);
  cursor: pointer;
  transition: .15s;
}

.skin-btn:hover {
  color: var(--primary-600);
  border-color: var(--primary);
  background: var(--surface);
}

.skin-btn[aria-expanded="true"] {
  color: #fff;
  background: var(--primary);
  border-color: var(--primary);
}

/* Sources accordion */
.sources-accordion {
  flex: 1 1 100%;
  margin-top: 6px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--surface);
}

.sources-accordion summary {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 13px 16px;
  cursor: pointer;
  list-style: none;
  font-weight: 600;
  font-size: .92rem;
  background: var(--surface-2);
  user-select: none;
}

.sources-accordion summary::-webkit-details-marker {
  display: none;
}

.sources-summary-label {
  color: var(--ink);
}

.sources-count {
  background: var(--accent);
  color: #fff;
  border-radius: 999px;
  font-size: .72rem;
  font-weight: 700;
  padding: 2px 9px;
}

.sources-accordion .chevron {
  margin-left: auto;
  color: var(--muted);
  transition: transform .2s;
}

.sources-accordion[open] .chevron {
  transform: rotate(180deg);
}

.sources-body {
  padding: 8px 16px 16px;
  display: grid;
  gap: 16px;
}

.source-group-title {
  font-size: .8rem;
  text-transform: uppercase;
  letter-spacing: .05em;
  color: var(--accent);
  margin: 10px 0 8px;
  display: flex;
  align-items: center;
  gap: 8px;
}

.source-group-title .src-n {
  color: var(--muted);
  background: var(--surface-2);
  border-radius: 999px;
  padding: 1px 8px;
  font-size: .72rem;
  letter-spacing: 0;
}

.source-group ul {
  margin: 0;
  padding-left: 18px;
  display: grid;
  gap: 5px;
}

.source-group li {
  overflow-wrap: anywhere;
  word-break: break-word;
}

.source-group a {
  color: var(--primary-600);
  font-size: .88rem;
  overflow-wrap: anywhere;
  word-break: break-word;
}

/* bilingual current-affairs list (markup from services/postBuilder.js) */
.ca-list {
  padding-left: 22px;
  margin: 0;
  display: grid;
  gap: 10px;
}

.ca-item {
  line-height: 1.6;
}

/* Hindi lines: the Devanagari face, a hair larger and looser. Devanagari has a
   smaller apparent x-height than Latin at the same px size, and its matras need
   vertical room — matching Latin's metrics exactly makes it look cramped. */
.ca-hi {
  font-size: 1rem;
  font-family: var(--font-hi);
  line-height: 1.75;
}

[lang="hi"] {
  font-family: var(--font-hi);
}

/* A Hindi post page sets lang="hi" on the body wrapper, so its headings, buttons
   and labels all follow — while an English page is untouched. */
[lang="hi"] .ca-hi {
  font-size: 1.5rem;
}

/* Tap-to-mark: a personal "I've read this" highlight, available under every
   readability skin. Padding + a negative margin keeps the enlarged hit target
   from shifting the list's left edge or the gap between lines. Cursor + focus
   ring signal it is interactive without looking like a button. */
.ca-item {
  cursor: pointer;
  border-radius: var(--radius-sm);
  padding: 5px 10px;
  margin: -5px -10px;
  transition: background-color .15s, color .15s;
}

.ca-item:hover {
  background: var(--paper-2);
}

.ca-item:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px var(--ring);
}

/* ── monthly round-up: a date separator between each day's block ────────────
   A list item rather than a heading outside the <ol>, so it carries .ca-en /
   .ca-hi and postI18n.bodyForLang() gives /hi/ the Hindi date instead of an
   English one sitting in the middle of Hindi text. `list-style: none` keeps it
   out of the numbering, so the visible count still counts facts only. */
.ca-monthly {
  gap: 12px;
}

.ca-day {
  list-style: none;
  /* The negative left margin cancels .ca-list's padding so the rule spans the
     full column instead of starting at the numbers. */
  margin: 24px 0 6px -22px;
  padding: 0 0 8px;
  border-bottom: 2px solid var(--paper-2);
  font-weight: 700;
  /* Poppins, not the reading face: this is chrome inside the article and has to
     stay distinct from the facts under it under every readability skin. */
  font-family: var(--font);
  font-size: 1.05rem;
  color: var(--accent);
  cursor: default;
}

.ca-day:first-child {
  margin-top: 0;
}

.ca-day:hover {
  background: none;
}

/* The separator's Hindi line is chrome too, so it does not take the enlarged body
   size a Hindi page gives .ca-hi. */
.ca-day .ca-hi,
[lang="hi"] .ca-day .ca-hi {
  font-size: 1.05rem;
  font-weight: 700;
  line-height: 1.6;
}

/* Marked = read: a font-colour change only, no background/border — a quiet
   personal tick. Both lines of a marked one-liner switch to the accent green. */
.ca-item.is-marked .ca-en,
.ca-item.is-marked .ca-hi {
  color: var(--accent);
}

/* Currently-spoken line during audio playback — a left accent bar, distinct
   from the marked state's plain colour change so a listener can tell "this is
   playing now" apart from "I tapped this earlier" at a glance. */
.ca-item.is-speaking {
  box-shadow: inset 3px 0 0 var(--primary);
  background: var(--paper-2);
}

/* Post meta row */
.post-meta-row {
  display: flex;
  align-items: center;
  gap: 14px;
  color: var(--muted);
  font-size: .9rem;
  margin: 12px 0 20px;
}

/* ---------- Prose (about / contact / privacy) ---------- */
.prose {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 28px 24px;
  box-shadow: var(--shadow-sm);
  max-width: 70ch;
}

.prose h2 {
  margin-top: 1.6em;
  font-size: 1.2rem;
  scroll-margin-top: 20px;
}

.prose h3 {
  margin-top: 1.2em;
  margin-bottom: .3em;
  font-size: 1rem;
  color: var(--ink);
}

.prose p {
  margin: 0 0 .9em;
}

.prose a {
  text-decoration: underline;
  text-underline-offset: 2px;
}

/* Static-page header block: title + lede. The rule is scoped to .prose so
   listing pages (which reuse .page-head) don't inherit the separator. */
.page-head h1 {
  margin: 0 0 .35em;
  font-size: 1.6rem;
  line-height: 1.25;
}

.prose .page-head {
  border-bottom: 1px solid var(--border);
  padding-bottom: 16px;
  margin-bottom: 4px;
}

.page-lede {
  font-size: 1.02rem;
  color: var(--muted);
  margin: 0;
}

.page-meta {
  font-size: .85rem;
  margin: 0 0 .6em;
}

/* Bulleted fact lists — tighter and more scannable than default <ul> */
.fact-list {
  margin: 0 0 1em;
  padding-left: 1.1em;
}

.fact-list li {
  margin-bottom: .45em;
}

/* Callout: highlighted block for the disclaimer and contact details */
.callout {
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-left: 4px solid var(--primary);
  border-radius: var(--radius-sm);
  padding: 16px 18px;
  margin: 0 0 1.2em;
}

.callout> :last-child {
  margin-bottom: 0;
}

.callout-warn {
  border-left-color: #d99b2b;
  background: #fdf6e9;
}

.contact-email {
  font-size: 1.08rem;
  font-weight: 600;
  margin-bottom: .3em !important;
  word-break: break-all;
}

/* ---------- Search / pagination / empty / error ---------- */
.search-form {
  display: flex;
  gap: 10px;
  margin-top: 12px;
}

.search-form input {
  flex: 1;
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 11px 18px;
  font: inherit;
  outline: none;
}

.search-form input:focus {
  border-color: var(--primary);
  box-shadow: 0 0 0 3px var(--ring);
}

.pagination {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 14px;
  margin: 30px 0;
}

.page-btn {
  padding: 9px 16px;
  border-radius: 999px;
  border: 1px solid var(--border);
  background: var(--surface);
  font-weight: 600;
  font-size: .9rem;
}

.page-btn.disabled {
  opacity: .45;
  pointer-events: none;
}

.page-info {
  color: var(--muted);
  font-size: .9rem;
}

.empty {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-sm);
  padding: 56px 32px;
  text-align: center;
  color: var(--muted);
}

.empty p {
  margin: 0;
}

/* Date + publish-time metadata */
.post-dates {
  display: flex;
  align-items: baseline;
  gap: 10px;
  flex-wrap: wrap;
}

.post-stamp {
  font-size: .88rem;
  color: var(--muted);
}

/* Total point count — a quiet pill beside the published time. Faded on purpose
   (same grey treatment as the "#N" chip): the number is a reference, not
   something that should compete with the one-liners. */
.post-total {
  font-size: .74rem;
  font-weight: 600;
  color: var(--muted);
  background: rgba(230, 234, 239, 0.45);
  border: 1px solid rgba(230, 234, 239, 0.7);
  border-radius: 999px;
  padding: 2px 9px;
  white-space: nowrap;
}

/* Read counter (eye icon). Server-counted on every render, so it works with JS
   off and is not suppressed by ad blockers. Tabular digits keep the badge from
   twitching in width as the number ticks up.

   It appears on the post page only — pinned to the top right of the article
   header, beside the title. */
.post-head-top {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 14px;
}

.post-head-top .post-title {
  flex: 1 1 auto;
  min-width: 0;
}

.post-head-top .view-count {
  flex: none;
  padding: 3px 10px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--surface-2);
}

.view-count {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: .82rem;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.view-count-icon {
  flex: none;
  opacity: .8;
}

.view-count-n {
  font-weight: 600;
}

@media (max-width: 480px) {

  /* Narrow phones: a clamped title needs the full width, so let the whole
     action cluster (eye badge + skin button) drop onto its own line together,
     still right-aligned and still side by side with each other. */
  .post-head-top {
    flex-wrap: wrap;
  }

  .post-head-actions {
    margin: 0 0 0 auto;
    order: -1;
  }
}

/* Post footer actions */
.post-actions {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin-bottom: 18px;
}

.post-actions .btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  min-width: 0;
  min-height: 44px;
  /* A long label (Hindi runs wider than English here) wraps inside the pill
     instead of pushing the button past the post's edge. */
  white-space: normal;
  overflow-wrap: break-word;
  text-align: center;
}

@media (max-width: 480px) {

  /* Narrow phones: give the reading column its width back. 24px of padding each
     side on a 320px screen spends 15% of the line on nothing, which matters more
     here than anywhere else on the site — this page is thirty dense lines. */
  .post {
    padding: 20px 14px;
  }

  /* Two equal columns: both actions get the same footprint and the same 44px
     tap height, and neither can overflow the container. */
  .post-actions {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 8px;
  }

  .post-actions .btn {
    padding: 10px 12px;
    font-size: .88rem;
  }
}

/* Print sheet wrapper — a layout-only table. On screen it is fully neutralised
   to blocks, so it has no effect; in print its <thead> becomes a running header. */
.print-sheet,
.print-sheet>thead,
.print-sheet>tbody,
.print-sheet>tbody>tr,
.print-sheet>tbody>tr>td {
  display: block;
  width: auto;
}

.print-sheet>thead {
  display: none;
}

.print-watermark {
  display: none;
}

/* ---------- Print / Save as PDF ----------
   Strips site chrome so the saved PDF is a clean one-liner revision sheet. */
@media print {

  /* Small top margin: the running header sits at the top of this content area,
     so this value is effectively the watermark's distance from the paper edge.
     Chrome clips anything outside the page area, so 0 is not usable. */
  @page {
    margin: 7mm 11mm 12mm;
  }

  :root {
    --shadow: none;
    --shadow-sm: none;
  }

  body {
    background: #fff;
    display: block;
    min-height: 0;
    font-size: 12pt;
  }

  .site-header,
  .site-footer,
  .breadcrumb,
  .skip-link,
  .post-actions,
  .lang-switch,
  .sources-accordion,
  .view-count,
  .skin-btn,
  .skin-overlay,
  .skin-modal,
  .share-block,
  .audio-player,
  .adsbygoogle,
  ins.adsbygoogle {
    display: none !important;
  }

  main.container {
    max-width: none;
    padding: 0;
  }

  .post {
    border: none;
    box-shadow: none;
    padding: 0;
    background: #fff !important;
  }

  .post-title {
    font-size: 18pt;
    margin: 0 0 6pt;
  }

  .post-stamp {
    font-size: 10pt;
    color: #444;
  }

  .ca-list {
    padding-left: 18pt;
  }

  .ca-item {
    break-inside: avoid;
    page-break-inside: avoid;
    margin-bottom: 8pt;
  }

  a {
    color: inherit;
    text-decoration: none;
  }

  /* A revision sheet must print identically no matter which readability skin
     was active on screen — the PDF is the exam-prep artefact, not the skin.
     (The glass canvas is already forced to #fff on `.post` above, for every
     skin; the title, dates and chrome were never skin-scoped to begin with.)
     The on-screen card list is flattened back to a plain numbered list: the
     "#N" chips are hidden (the browser's decimal ::marker takes over) and
     every card border/fill/shadow is stripped. */
  .ca-list,
  [data-skin] .ca-list {
    list-style: decimal !important;
    padding-left: 18pt !important;
    border: none !important;
    background: none !important;
    display: block !important;
  }

  .ca-item,
  [data-skin] .ca-item {
    border: none !important;
    border-bottom: none !important;
    background: none !important;
    box-shadow: none !important;
    border-radius: 0 !important;
    padding: 0 !important;
    margin: 0 0 8pt !important;
  }

  .ca-item::before {
    display: none !important;
  }

  [data-skin] .ca-en,
  [data-skin] .ca-hi {
    font-family: inherit !important;
    font-size: inherit !important;
    color: inherit !important;
    font-weight: inherit !important;
  }

  .ca-item.is-marked {
    background: none !important;
    box-shadow: none !important;
  }

  .ca-item.is-marked .ca-en,
  .ca-item.is-marked .ca-hi {
    color: inherit !important;
  }

  /* Restore real table semantics so thead repeats and reserves space per page. */
  .print-sheet {
    display: table;
    width: 100%;
    border-collapse: collapse;
  }

  .print-sheet>thead {
    display: table-header-group;
  }

  .print-sheet>tbody {
    display: table-row-group;
  }

  .print-sheet>thead>tr,
  .print-sheet>tbody>tr {
    display: table-row;
  }

  .print-sheet>thead>tr>td,
  .print-sheet>tbody>tr>td {
    display: table-cell;
    padding: 0;
  }

  .print-sheet-head {
    text-align: right;
    padding-bottom: 3mm !important;
  }

  .print-watermark {
    display: inline-block;
    font-size: 8.5pt;
    font-weight: 700;
    letter-spacing: .03em;
    color: #9aa7b1 !important;
    text-decoration: none;
    white-space: nowrap;
  }
}

.card-stamp {
  font-size: .8rem;
  color: var(--muted);
}

.nowrap {
  white-space: nowrap;
}

.error-page {
  text-align: center;
  padding: 70px 20px;
}

.error-code {
  font-size: 4rem;
  font-weight: 800;
  background: linear-gradient(135deg, var(--primary), var(--accent));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  margin: 0;
}

/* ---------- Footer ---------- */
.site-footer {
  border-top: 1px solid var(--border);
  background: var(--surface);
  margin-top: 50px;
}

.footer-inner {
  display: grid;
  /* Brand left, everything else right. `minmax(0, …)` on both tracks so a long
     tagline or a wide Telegram card can shrink instead of forcing the grid wider
     than the container — a 1fr track's default `min-width: auto` is what makes a
     footer overflow on a tablet. */
  grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.15fr);
  gap: 28px 44px;
  /* Both columns start at the top: the brand is two lines and the right column is
     two rows, so stretching would strand the tagline in the middle of nowhere. */
  align-items: start;
  padding: 36px 18px 22px;
}

/* The right-hand column: links row, then the Telegram invite. */
.footer-col {
  display: grid;
  gap: 18px;
}

.footer-brand {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
}

.footer-brand .brand-logo {
  width: 30px;
  height: 30px;
}

.footer-brand p {
  margin: 8px 0 0;
  font-size: .9rem;
  flex-basis: 100%;
}

.footer-links {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 18px;
  align-content: start;
}

.footer-links a {
  color: var(--muted);
  font-size: .92rem;
}

/* ---------- Telegram channel card ----------
   Cozy rather than loud: it sits on the accent tint the rest of the site already
   uses for "this is a friendly aside", with a soft border and no shadow at rest.
   The whole card is the link, so the hit area is the block — see footer.ejs. */
.footer-telegram {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 15px 18px;
  border: 1px solid #cfe9e5;
  border-radius: var(--radius);
  background: linear-gradient(180deg, #f2fbf9 0%, var(--accent-soft) 100%);
  color: var(--ink);
  text-decoration: none;
  /* Fills its column, but never becomes a full-width band on a wide screen — that
     reads as a banner ad rather than an invitation. */
  max-width: 560px;
  transition: transform .16s ease, box-shadow .16s ease, border-color .16s ease;
}

.footer-telegram:hover {
  border-color: var(--accent);
  box-shadow: 0 6px 18px rgba(47, 158, 147, .16);
  /* 1px, not 3: a footer invite that leaps at the cursor feels like an ad. */
  transform: translateY(-1px);
  /* Re-stated on purpose. The global `a:hover` underline rule outranks
     `.footer-telegram` on specificity, so without this the card's two lines of
     text pick up an underline on hover. The card signals interactivity with its
     border, its shadow and the moving arrow instead. */
  text-decoration: none;
}

.footer-telegram:focus-visible {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft), 0 0 0 4px var(--accent);
}

.ft-icon {
  display: grid;
  place-items: center;
  flex: none;
  width: 42px;
  height: 42px;
  border-radius: 50%;
  background: var(--accent);
  color: #fff;
  /* The plane's own whitespace sits low-right; nudging it back centres the glyph
     optically rather than mathematically. */
  padding-right: 1px;
}

.ft-text {
  display: grid;
  gap: 2px;
  min-width: 0;   /* lets the sub-line wrap instead of stretching the card */
}

.ft-text strong {
  font-size: .96rem;
  font-weight: 600;
  line-height: 1.35;
}

.ft-sub {
  font-size: .82rem;
  color: var(--muted);
  line-height: 1.4;
}

.ft-cta {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  flex: none;
  margin-left: auto;
  padding: 7px 13px;
  border-radius: 999px;
  background: var(--accent);
  color: #fff;
  font-size: .84rem;
  font-weight: 600;
  white-space: nowrap;
}

.ft-cta svg {
  transition: transform .16s ease;
}

.footer-telegram:hover .ft-cta svg {
  transform: translateX(2px);
}

.footer-bottom {
  padding: 14px 18px 28px;
  font-size: .85rem;
  border-top: 1px solid var(--border);
}

/* ============================================================
   Responsive
   ============================================================ */
@media (max-width: 760px) {

  /* fixed 62px top row (brand | burger); nav drops into row 2, from the header's bottom edge */
  .header-inner {
    display: grid;
    grid-template-columns: 1fr auto;
    grid-template-rows: 62px auto;
    align-items: center;
    height: auto;
    min-height: 0;
    gap: 0;
  }

  .brand {
    grid-area: 1 / 1;
  }

  .nav-burger {
    display: grid;
    grid-area: 1 / 2;
    justify-self: end;
  }

  .site-nav {
    grid-area: 2 / 1 / 3 / 3;
    flex-direction: column;
    align-items: stretch;
    gap: 4px;
    margin: 0;
    max-height: 0;
    overflow: hidden;
    transition: max-height .3s ease;
  }

  .nav-toggle:checked~.site-nav {
    /* Scrollable: the menu grows with the inline search results up to 80vh, then
       scrolls internally so long result lists stay reachable without the header
       taking over the whole screen. overscroll-behavior stops the scroll
       chaining to the page when you hit the end. */
    max-height: 80vh;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    overscroll-behavior: contain;
    padding: 10px 0 12px;
    border-top: 1px solid var(--border);
  }

  /* hamburger → cross is defined with the icon itself (see above). */
  /* Comfortable tap targets in the open menu. */
  .site-nav a {
    padding: 11px 12px;
    font-size: 1rem;
  }

  /* Phones: the glass article loses its side padding so the cards get the
     width; cards themselves slim down so a fact still fits on screen. */
  .post {
    padding: 20px 14px;
    border-radius: 12px;
  }

  .post-body .ca-list {
    gap: 10px;
  }

  .post-body .ca-item {
    padding: 9px 13px 14px;
    border-radius: 12px;
  }

  /* Footer: the two columns become one, in the same reading order — brand,
     links, Telegram. `.footer-col` keeps its own row gap, so the links and the
     invite stay closer to each other than to the brand above them. */
  .footer-inner {
    grid-template-columns: 1fr;
    gap: 24px;
    padding: 30px 18px 20px;
  }

  .footer-col {
    gap: 16px;
  }

  /* Telegram card: icon + text on the first line, then a full-width Join pill.
     Side by side there is no room for all three at 360px — the text would wrap to
     three lines beside a 78px pill. Dropping the pill to its own line also gives
     it a proper 44px tap height. Hover lift is removed: there is no hover on a
     touch screen, and the transform only ever fired as a flash on tap. */
  .footer-telegram {
    max-width: none;
    flex-wrap: wrap;
    gap: 12px 13px;
    padding: 14px 15px;
  }

  .footer-telegram:hover {
    transform: none;
  }

  .ft-text {
    flex: 1 1 0;
  }

  .ft-cta {
    flex: 1 0 100%;
    margin-left: 0;
    justify-content: center;
    padding: 11px 14px;
    font-size: .88rem;
  }
}

/* Very narrow phones (≤ 380px): keep the brand row on one line. */
@media (max-width: 380px) {
  .container {
    padding: 0 14px;
  }

  .brand {
    gap: 8px;
    min-width: 0;
  }

  .brand-logo {
    width: 30px;
    height: 30px;
  }

  .brand-name {
    font-size: 1.02rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  .post,
  .prose {
    padding: 20px 16px;
  }
}

@media (min-width: 640px) {
  .cards {
    grid-template-columns: repeat(2, 1fr);
  }

  .footer-inner {
    grid-template-columns: 1.3fr 2fr;
  }
}

@media (min-width: 920px) {
  .cards {
    grid-template-columns: repeat(3, 1fr);
  }
}

/* ---------- Home ---------- */
.section-more {
  margin-top: 16px;
}

/* ---------- Header search typeahead ---------- */
.nav-search {
  position: relative;
}

.nav-search-form {
  position: relative;
  display: flex;
  align-items: center;
}

.nav-search-icon {
  position: absolute;
  left: 12px;
  color: var(--muted);
  pointer-events: none;
}

.nav-search input {
  border: 1px solid var(--border);
  background: var(--surface);
  border-radius: 999px;
  padding: 8px 14px 8px 34px;
  font: inherit;
  font-size: .9rem;
  width: 190px;
  outline: none;
  transition: width .18s ease, border-color .15s, box-shadow .15s;
}

.nav-search input:focus {
  border-color: var(--primary);
  box-shadow: 0 0 0 3px var(--ring);
  width: 230px;
}

/* Results dropdown (desktop: floating panel anchored to the input) */
.nav-search-panel {
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  z-index: 60;
  width: min(400px, 92vw);
  max-height: min(70vh, 460px);
  overflow-y: auto;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: 0 10px 30px rgba(31, 41, 51, .16);
  padding: 6px;
}

.nav-search-panel[hidden] {
  display: none;
}

.ns-empty {
  margin: 0;
  padding: 14px;
  color: var(--muted);
  font-size: .88rem;
  text-align: center;
}

.ns-item {
  display: block;
  padding: 10px 12px;
  border-radius: 10px;
  border-left: 3px solid transparent;
}

.ns-item+.ns-item {
  border-top: 1px solid var(--border);
}

.ns-item:hover,
.ns-item:focus-visible {
  text-decoration: none;
  background: var(--surface-2);
  border-left-color: var(--accent);
}

.ns-item-en {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  color: var(--ink);
  font-weight: 600;
  font-size: .9rem;
  line-height: 1.45;
}

.ns-item-hi {
  display: -webkit-box;
  -webkit-line-clamp: 1;
  -webkit-box-orient: vertical;
  overflow: hidden;
  color: var(--muted);
  font-size: .86rem;
  line-height: 1.6;
  margin-top: 3px;
  font-family: var(--font-hi);
}

.ns-item-meta {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin-top: 6px;
}

.ns-item-meta>span:first-child {
  font-size: .74rem;
  color: var(--muted);
}

.ns-item-go {
  font-size: .76rem;
  font-weight: 700;
  color: var(--accent);
  white-space: nowrap;
}

/* Mobile search overrides.
   MUST come after the desktop rules above — equal specificity, so source order
   decides. (A media query earlier in the file was being overridden by the
   desktop `width: 190px`, which is why the bar wasn't full width.) */
@media (max-width: 760px) {

  /* Stays inside the menu, in DOM order (after About). */
  .nav-search {
    width: 100%;
    margin: 6px 0 0;
    position: static;
  }

  .nav-search input,
  .nav-search input:focus {
    width: 100%;
    font-size: 1rem;
    padding: 12px 14px 12px 36px;
  }

  .nav-search-icon {
    left: 12px;
  }

  /* Results flow inline: they expand the menu and push page content down. */
  .nav-search-panel {
    position: static;
    width: 100%;
    max-height: none;
    overflow: visible;
    margin-top: 8px;
    box-shadow: none;
    border-radius: var(--radius-sm);
  }
}

/* ---------- Post: language switch ---------- */
.lang-switch {
  display: inline-flex;
  gap: 4px;
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 3px;
  background: var(--surface);
}

.lang-switch a {
  padding: 5px 13px;
  border-radius: 999px;
  font-size: .85rem;
  font-weight: 600;
  color: var(--muted);
}

.lang-switch a:hover {
  text-decoration: none;
  color: var(--ink);
}

.lang-switch a.active {
  background: var(--primary);
  color: #fff;
}


/* ============================================================
   Readability-skin modal (post page)
   ============================================================ */
.skin-overlay {
  position: fixed;
  inset: 0;
  background: rgba(31, 41, 51, .45);
  backdrop-filter: blur(1px);
  z-index: 90;
  animation: skinFadeIn .15s ease;
}

.skin-modal {
  position: fixed;
  z-index: 91;
  background: var(--surface);
  border-radius: var(--radius);
  box-shadow: 0 20px 60px rgba(31, 41, 51, .25);
  width: min(420px, calc(100vw - 28px));
  max-height: min(560px, 86vh);
  overflow-y: auto;
  /* Centred dialog on every viewport, phone included — matches the desktop
     layout instead of a bottom sheet, so the choice looks the same everywhere. */
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  padding: 22px 22px 20px;
  animation: skinSheetIn .2s ease;
  /* Themed scrollbar for when the option list overflows max-height — thin and
     accent-coloured rather than the browser's default grey bar, so it matches
     the modal's own palette instead of looking like a stray OS control.
     Firefox/standard path (scrollbar-color needs no thumb/track selectors). */
  scrollbar-width: thin;
  scrollbar-color: var(--accent) var(--surface-2);
}

/* WebKit path (Chrome/Safari/Edge) — no shorthand equivalent to scrollbar-color,
   so track/thumb are styled individually. Scoped to .skin-modal only; the rest
   of the site keeps the OS default scrollbar. */
.skin-modal::-webkit-scrollbar {
  width: 9px;
}

.skin-modal::-webkit-scrollbar-track {
  background: var(--surface-2);
  border-radius: var(--radius-sm);
}

.skin-modal::-webkit-scrollbar-thumb {
  background: var(--accent);
  border-radius: var(--radius-sm);
  border: 1px solid var(--surface);
  /* thin inset so the thumb doesn't touch the track edge */
}

.skin-modal::-webkit-scrollbar-thumb:hover {
  background: var(--primary-600);
}

@keyframes skinFadeIn {
  from {
    opacity: 0;
  }

  to {
    opacity: 1;
  }
}

@keyframes skinSheetIn {
  from {
    transform: translate(-50%, -46%);
    opacity: 0;
  }

  to {
    transform: translate(-50%, -50%);
    opacity: 1;
  }
}

.skin-modal-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 14px;
}

.skin-modal-head h2 {
  font-size: 1.05rem;
  margin: 0;
}

.skin-close {
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  border-radius: 999px;
  border: 1px solid var(--border);
  background: var(--surface-2);
  color: var(--muted);
  cursor: pointer;
}

.skin-close:hover {
  color: var(--ink);
  background: var(--border);
}

.skin-options {
  display: grid;
  gap: 10px;
}

.skin-option {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  text-align: left;
  padding: 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--surface);
  cursor: pointer;
  transition: .15s;
  font: inherit;
  color: var(--ink);
}

.skin-option:hover {
  border-color: var(--primary);
  background: var(--surface-2);
}

.skin-option:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px var(--ring);
}

.skin-option.is-active {
  border-color: var(--accent);
  background: var(--accent-soft);
}

/* Little preview swatches so a choice reads at a glance, before it's applied. */
.skin-swatch {
  flex: none;
  width: 46px;
  height: 46px;
  border-radius: 8px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 5px;
  padding: 0 8px;
  border: 1px solid var(--border);
}

.skin-swatch-handwritten {
  background: #fcfcfc;
  padding: 4px;
  gap: 3px;
}

.skin-swatch-newspaper {
  background: #fcfcfc;
  padding: 4px;
  gap: 3px;
}

.skin-swatch-row {
  flex: 1;
  border: 1px solid #d8d8d8;
  background: #fff;
  border-radius: 2px;
}

.skin-option-text {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.skin-option-name {
  font-weight: 600;
  font-size: .94rem;
}

.skin-option-desc {
  font-size: .8rem;
  color: var(--muted);
}

.skin-check {
  flex: none;
  width: 20px;
  height: 20px;
  border-radius: 999px;
  border: 1px solid var(--border);
  display: flex;
  align-items: center;
  justify-content: center;
  color: transparent;
  background: var(--surface);
}

.skin-option.is-active .skin-check {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
}

.skin-hint {
  margin: 14px 0 0;
  font-size: .78rem;
  color: var(--muted);
  text-align: center;
}

/* ============================================================
   Post body: the shared soft-card list (both skins)
   ============================================================
   Each one-liner is its own card — white, hairline border, rounded — sitting
   on the frosted article canvas, with a small "#N" chip floated to the top
   right of the card (like the rank chip on a spec card). Cards are written
   once here, scoped to .post-body, so both readability skins share the exact
   same structure and only the type inside a card changes per skin. Scoping
   to .post-body keeps the admin editor's own .ca-item rows (plain list) from
   picking up the card chrome.

   The "#N" chip is a CSS counter on the list (not ::marker), because a chip
   needs a box of its own; ::marker can't be styled as one. It sits on its own
   line at the top right of the card (right-aligned via margin-left:auto, not
   floated — a float pulled the first text line up beside it and left a gap
   before the point started). A small fixed margin below is all that separates
   the chip line from the fact. Tapping a card (the tap-to-mark feature)
   highlights its border in the accent green; hovering tints the border blue;
   the audio player's current line gets the blue border plus the left accent
   bar. All three are border/ring states on the same card — no striped
   backgrounds anywhere. */
.post-body .ca-list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: grid;
  gap: 14px;
  counter-reset: ca;
}

.post-body .ca-item {
  position: relative;
  counter-increment: ca;
  cursor: pointer;
  background: rgba(255, 255, 255, 0.72);
  border: 1px solid rgba(224, 231, 238, 0.9);
  border-radius: var(--radius);
  padding: 10px 18px 16px;
  margin: 0;
  box-shadow: 0 1px 3px rgba(31, 41, 51, 0.05);
  transition: border-color .18s, box-shadow .18s, background-color .18s;
}

/* "#N" rank chip, top right on its own line — its own font/size (absolute rem,
   not the skin's reading size) so it reads as a label, not as part of the
   fact. Deliberately faint (pale grey fill, muted text): the number is a
   reference, not content, and must not compete with the line being read.
   `width: fit-content` keeps the pill to the text's width while the auto
   margin pins it to the right edge; the small negative top margin tucks it
   up against the card's top edge. */
.post-body .ca-item::before {
  content: "#" counter(ca);
  display: block;
  width: fit-content;
  margin: -4px 0 7px auto;
  font: 500 0.62rem/1 var(--font);
  color: rgba(107, 119, 135, 0.75);
  background: rgba(230, 234, 239, 0.45);
  border: 1px solid rgba(230, 234, 239, 0.7);
  border-radius: 999px;
  padding: 3px 7px;
}

/* The default reading face (Anek Devanagari, both scripts) also covers the
   no-JS page, where no [data-skin] attribute exists to trigger a skin block. */
.post-body .ca-en,
.post-body .ca-hi {
  font-family: var(--font-news);
}

.post-body .ca-item:hover {
  border-color: rgba(79, 124, 172, 0.55);
  box-shadow: 0 0 0 3px var(--ring);
  background: rgba(255, 255, 255, 0.88);
}

.post-body .ca-item:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px var(--ring);
}

/* Marked = read: the card's border lights up in the accent green with a soft
   mint fill — a clear "done" state that survives both skins. */
.post-body .ca-item.is-marked {
  border-color: var(--accent);
  background: var(--accent-soft);
  box-shadow: 0 0 0 1px rgba(47, 158, 147, 0.35);
}

.post-body .ca-item.is-marked::before {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
}

/* Currently-spoken line during audio playback — blue border + left accent
   bar, distinct from the marked state's green border so "playing now" and
   "I read this" can't be confused. */
.post-body .ca-item.is-speaking {
  border-color: var(--primary);
  background: rgba(255, 255, 255, 0.88);
  box-shadow: inset 3px 0 0 var(--primary), 0 0 0 3px var(--ring);
}

/* ============================================================
   Skin: Handwritten — Kalam, both languages
   ============================================================
   Scoped to [data-skin="handwritten"] on <html> (set by the inline script in
   post.ejs) so only the post page's own content changes; header, footer and
   the rest of the chrome are untouched. Cursive font only.
   Kalam covers Latin and Devanagari, so one family carries both halves of a
   fact — the English and Hindi lines look like the same hand. The card list
   above is shared with the newspaper skin; this block only sets type.

   Sizes are fluid clamp()s so a phone, tablet and desktop each get the most
   comfortable reading size for that width; the Hindi line keeps its looser
   leading because Kalam's Devanagari matras need the vertical room. */
[data-skin="handwritten"] .ca-en {
  font-family: var(--font-hand);
  font-size: clamp(1.22rem, 1rem + 1vw, 1.5rem);
  line-height: 1.55;
  color: #4a3728;
  letter-spacing: .01em;
}

/* Same family, a hair smaller: Kalam's Devanagari carries more vertical detail
   (matras above and below), so it needs the looser line rather than more size. */
[data-skin="handwritten"] .ca-hi {
  font-family: var(--font-hand);
  font-size: clamp(1.15rem, 0.96rem + 0.9vw, 1.4rem);
  line-height: 1.8;
  color: #4a3728;
  display: block;
  margin-top: 6px;
}

/* On the Hindi page the Hindi line is the headline of the fact — give it the
   same fluid size as the English line gets on the English page. */
[lang="hi"][data-skin="handwritten"] .ca-hi {
  font-size: clamp(1.22rem, 1rem + 1vw, 1.5rem);
}

[data-skin="handwritten"] .ca-item.is-marked .ca-en,
[data-skin="handwritten"] .ca-item.is-marked .ca-hi {
  color: var(--accent);
}

/* ============================================================
   Skin: Newspaper (the default skin) — Anek Devanagari, both languages
   ============================================================
   Scoped to .ca-en/.ca-hi only — the reading face is a property of the
   one-liners themselves, not of .post-body as a whole. The title, dates,
   language switch and every other part of the page stay in Poppins under
   every skin; only the article content varies. The card list above is shared
   with the handwritten skin; this block only sets type.

   Fluid clamp() sizes give each viewport its most comfortable reading size
   (Anek Devanagari is a Devanagari-first face whose Latin is matched to it,
   so one family carries both halves of a fact). The Hindi line keeps looser
   leading for its matras; on the Hindi page it is the headline of the fact
   and steps up to the English line's size. */
[data-skin="newspaper"] .ca-en {
  font-family: var(--font-news);
  font-size: clamp(1.18rem, 0.96rem + 1vw, 1.45rem);
  line-height: 1.6;
  color: #2a4a52;
}

[data-skin="newspaper"] .ca-hi {
  font-family: var(--font-news);
  font-size: clamp(1.08rem, 0.94rem + 0.7vw, 1.28rem);
  line-height: 1.8;
  color: #2a4a52;
  display: block;
  margin-top: 6px;
}

[lang="hi"][data-skin="newspaper"] .ca-hi {
  font-size: clamp(1.18rem, 0.96rem + 1vw, 1.45rem);
}

[data-skin="newspaper"] .ca-item.is-marked .ca-en,
[data-skin="newspaper"] .ca-item.is-marked .ca-hi {
  color: var(--accent);
}

/* ============================================================
   Share block (post footer, after the sources accordion)
   ============================================================
   One responsive grid at every width instead of a wrapping flex row of pills.
   `auto-fit` + `minmax()` gives every button the *same* width — a flex row sized
   each pill to its label, so "WhatsApp" and "Copy link" came out different
   widths and the row looked ragged — and because each track has a floor, the
   buttons re-flow onto another line rather than pushing past the post's edge.

   `min-width: 0` on the button plus `overflow: hidden` on its label is what
   actually prevents the overflow on a narrow phone: a grid item's default
   `min-width: auto` lets its content force the track wider than 1fr, so a long
   label (or a Hindi one, which sets wider) escaped the container. */
.share-block {
  flex: 1 1 100%;
  min-width: 0;
  margin-top: 6px;
}

.share-label {
  display: block;
  font-size: .82rem;
  font-weight: 600;
  color: var(--muted);
  margin-bottom: 10px;
}

.share-row {
  display: grid;
  gap: 9px;
  grid-template-columns: repeat(auto-fit, minmax(148px, 1fr));
}

.share-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  min-width: 0;
  min-height: 42px;
  padding: 9px 14px;
  border-radius: 999px;
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--ink);
  font: inherit;
  font-size: .86rem;
  font-weight: 600;
  line-height: 1.2;
  cursor: pointer;
  transition: background-color .15s, color .15s, border-color .15s, transform .15s, box-shadow .15s;
}

/* The icon keeps its size; only the label gives way. */
.share-btn svg {
  flex: none;
}

.share-btn > span {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.share-btn:hover {
  text-decoration: none;
  transform: translateY(-1px);
  box-shadow: var(--shadow-sm);
}

.share-btn:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px var(--ring);
}

.share-native {
  background: var(--primary);
  color: #fff;
  border-color: var(--primary);
}

.share-native:hover {
  background: var(--primary-600);
}

.share-whatsapp:hover {
  background: #25d366;
  color: #fff;
  border-color: #25d366;
}

.share-telegram:hover {
  background: #229ed9;
  color: #fff;
  border-color: #229ed9;
}

.share-facebook:hover {
  background: #1877f2;
  color: #fff;
  border-color: #1877f2;
}

.share-x:hover {
  background: #0f1419;
  color: #fff;
  border-color: #0f1419;
}

.share-copy.is-copied {
  background: var(--accent);
  color: #fff;
  border-color: var(--accent);
}

@media (max-width: 480px) {

  /* Two per row on a phone: a 44px-tall tap target with room for the longest
     label ("Copy link" / "लिंक कॉपी करें") without truncating it. Where the
     native share sheet exists — most phones — only two buttons are visible
     anyway, so this is the whole row. */
  .share-row {
    grid-template-columns: repeat(auto-fit, minmax(132px, 1fr));
    gap: 8px;
  }

  .share-btn {
    min-height: 44px;
    padding: 10px 12px;
    font-size: .82rem;
  }
}


/* ============================================================
   Audio player — reads one-liners aloud (post footer button + floating bar)
   ============================================================ */
/* A persistent bottom bar, not a modal: playback controls must stay reachable
   while the visitor keeps scrolling/reading, which a page-blocking dialog
   would defeat. Fixed to the viewport, above everything else on the page. */
.audio-player {
  position: fixed;
  left: 50%;
  bottom: 16px;
  transform: translateX(-50%);
  z-index: 80;
  width: min(400px, calc(100vw - 24px));
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 18px;
  box-shadow: 0 14px 36px rgba(31, 41, 51, .2);
  padding: 14px 16px 12px;
  animation: audioBarIn .2s ease;
}

@keyframes audioBarIn {
  from {
    transform: translate(-50%, 12px);
    opacity: 0;
  }

  to {
    transform: translate(-50%, 0);
    opacity: 1;
  }
}

.audio-close {
  position: absolute;
  top: 10px;
  right: 10px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  padding: 0;
  border-radius: 999px;
  border: none;
  background: var(--surface-2);
  color: var(--muted);
  cursor: pointer;
  transition: .15s;
}

.audio-close:hover {
  background: var(--border);
  color: var(--ink);
}

/* "Listening" label + the current line's own text — the visitor can read
   along with the voice, and it doubles as visible proof the button did
   something (silence with no other feedback reads as broken). */
.audio-now-playing {
  padding-right: 26px;
  margin-bottom: 10px;
}

.audio-now-label {
  display: block;
  font-size: .7rem;
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 3px;
}

.audio-now-text {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  font-size: .92rem;
  line-height: 1.4;
  color: var(--ink);
  font-weight: 600;
  min-height: 2.5em;
}

[lang="hi"] .audio-now-text {
  font-family: var(--font-hi);
  font-weight: 500;
}

/* ---- Seek: fixed checkpoint dots, one per one-liner ----
   Not a draggable track: there is nothing continuous to drag along, only N
   discrete lines, so the control is exactly N small dots — no more, no fewer
   — each a real <button> generated in JS once the one-liner count is known.
   Faded/quiet by default so the row doesn't compete with the controls below
   it; the active line's dot is the one visual accent, and hover/focus lift a
   dot just enough to confirm it's clickable without the row looking busy. */
.audio-seek {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  gap: 6px;
  min-height: 22px;
  margin-bottom: 6px;
  padding: 0 2px;
}

.audio-dot {
  flex: none;
  width: 7px;
  height: 7px;
  padding: 0;
  border: none;
  border-radius: 999px;
  background: var(--muted);
  opacity: .35;
  cursor: pointer;
  transition: opacity .15s, transform .15s;
}

.audio-dot:hover {
  opacity: .6;
}

.audio-dot.is-active {
  background: var(--primary);
  opacity: 1;
  transform: scale(1.35);
}

.audio-seek:focus-visible {
  outline: none;
}

.audio-seek:focus-visible .audio-dot.is-active {
  box-shadow: 0 0 0 3px var(--ring);
}

.audio-controls-row {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 2px;
}

.audio-progress-label {
  flex: none;
  width: 46px;
  font-size: .74rem;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}

.audio-buttons {
  flex: 1 1 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
}

.audio-controls-spacer {
  flex: none;
  width: 46px;
}

/* balances the label on the left, so play/pause stays visually centred */

.audio-btn {
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  padding: 0;
  border-radius: 999px;
  border: none;
  background: transparent;
  color: var(--ink);
  cursor: pointer;
  transition: .15s;
}

.audio-btn:hover {
  background: var(--surface-2);
}

.audio-toggle {
  width: 44px;
  height: 44px;
  background: var(--primary);
  color: #fff;
}

.audio-toggle:hover {
  background: var(--primary-600);
}

.audio-toggle svg {
  display: block;
}

/* a single path now, swapped in JS — no overlay trick needed */

.audio-novoice {
  margin: 10px 2px 0;
  font-size: .76rem;
  color: var(--muted);
  text-align: center;
}

@media (max-width: 480px) {

  /* Full width, resting just above the safe area on a phone rather than a
     floating pill that a thumb might miss. */
  .audio-player {
    left: 12px;
    right: 12px;
    bottom: 12px;
    transform: none;
    width: auto;
    padding-bottom: calc(12px + env(safe-area-inset-bottom));
  }

  @keyframes audioBarIn {
    from {
      transform: translateY(12px);
      opacity: 0;
    }

    to {
      transform: translateY(0);
      opacity: 1;
    }
  }
}