/*
 * Written with CSS logical properties throughout (margin-inline-start rather
 * than margin-left, and so on). In an RTL language like Urdu those flip
 * automatically, so the same rules lay out both directions correctly. Going
 * back and converting physical properties later is miserable, so none are
 * used here in the first place.
 */

/* ---------- Urdu webfont ----------
 * Without a Nastaliq face the reader gets either tofu boxes or a Naskh
 * fallback that Urdu readers find hard going. Self-hosted, so no third party
 * sees the reader's IP address.
 */
@font-face {
  font-family: 'Noto Nastaliq Urdu';
  src: url('/fonts/noto-nastaliq-urdu.woff2') format('woff2');
  font-weight: 400 700;
  font-display: swap;
  /* Official Google Fonts Arabic subset range, so the 239kb face is only
     fetched by readers who actually hit Urdu text. Noto is SIL OFL 1.1. */
  unicode-range: U+0600-06FF, U+0750-077F, U+0870-088E, U+0890-0891, U+0897-08E1,
                 U+08E3-08FF, U+200C-200E, U+2010-2011, U+204F, U+2E41,
                 U+FB50-FDFF, U+FE70-FE74, U+FE76-FEFC;
}

:root {
  /* A soft, slightly warm grey rather than white: a full page of #fff is
     glare for long reading. Cards sit on it in --card, which stays white,
     so they lift off the page instead of blending into it. */
  --bg: #f4f4f1;
  --card: #ffffff;
  --surface: #ebebe7;
  --border: #e0e0db;
  --text: #18181b;
  /* Darker than it would need to be on white: on the grey page #6b7280 fell
     to 4.4:1, under the 4.5:1 that small text (dates, bylines) needs. */
  --muted: #5f6470;
  --accent: #b91c1c;
  --accent-soft: #fef2f2;
  --success-bg: #ecfdf5;
  --success-border: #6ee7b7;
  --success-text: #065f46;

  --font-latin: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  --font-urdu: 'Noto Nastaliq Urdu', 'Jameel Noori Nastaleeq', 'Segoe UI', serif;
  --font-mono: ui-monospace, 'Cascadia Mono', 'Consolas', monospace;

  --measure: 68ch;
  --radius: 10px;

  /* Reader preferences. public/js/reader-prefs.js overrides these on <html>;
     the defaults here are the design as drawn, so a reader who never opens
     the panel sees exactly what they saw before it existed. */
  --reader-scale: 1;
  --reader-leading: 1.65;

  /* Native controls and scrollbars follow the theme too, not just our CSS. */
  color-scheme: light;
}

/* ---------- dark palette ----------
 * The values are written out twice on purpose. CSS has no way to name a
 * group of custom properties and apply it under two different selectors, so
 * the palette lives once in the media query (nobody has chosen a theme —
 * follow the OS) and once on the attribute (someone pressed the toggle —
 * their choice wins). Keep the two in step when editing.
 *
 * :not([data-theme='light']) is the part that matters: without it, a reader
 * on a dark OS who explicitly picked Light would still get the dark palette,
 * because the media query would keep applying underneath their choice.
 */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme='light']) {
  --bg: #0b0b0d;
  --card: #141417;
  --surface: #151518;
  --border: #27272a;
  --text: #f4f4f5;
  --muted: #a1a1aa;
  --accent: #f87171;
  --accent-soft: #1f1416;
  --success-bg: #052e21;
  --success-border: #10b981;
  --success-text: #6ee7b7;
  color-scheme: dark;
  }
}

:root[data-theme='dark'] {
  --bg: #0b0b0d;
  --card: #141417;
  --surface: #151518;
  --border: #27272a;
  --text: #f4f4f5;
  --muted: #a1a1aa;
  --accent: #f87171;
  --accent-soft: #1f1416;
  --success-bg: #052e21;
  --success-border: #10b981;
  --success-text: #6ee7b7;
  color-scheme: dark;
}

/* ---------- higher contrast ----------
 * Raises text and border contrast for readers who need more separation than
 * the default greys give. Only the tokens change — no component knows this
 * mode exists.
 */
:root[data-contrast='high'] {
  --bg: #ffffff;
  --text: #000000;
  --muted: #3f3f46;
  --border: #52525b;
  --accent: #991b1b;
}

:root[data-theme='dark'][data-contrast='high'] {
  --bg: #0b0b0d;
  --text: #ffffff;
  --muted: #e4e4e7;
  --border: #a1a1aa;
  --accent: #fca5a5;
}

*, *::before, *::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  /* 16px is the browser default, so scale 1 changes nothing. Every rem in
     this file is relative to it, which is how one control resizes the page
     without a second set of rules. */
  font-size: calc(16px * var(--reader-scale, 1));
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--reader-font, var(--font-latin));
  font-size: 1.0625rem;  /* 17px at the default scale */
  line-height: var(--reader-leading, 1.65);
  -webkit-font-smoothing: antialiased;
}

/*
 * Urdu needs a larger size and much looser leading than Latin text: Nastaliq
 * glyphs cascade diagonally and collide at normal line-height.
 */
[lang='ur'], .is-rtl {
  /* Not var(--reader-font): the serif option is a Latin typeface, and the
     Nastaliq face is not a preference — it is what makes Urdu readable. */
  font-family: var(--font-urdu);
  font-size: 1.25em;
  /* Offset rather than a fixed value, so the spacing control still applies.
     +0.55 lands on the original 2.2 at the default 1.65. */
  line-height: calc(var(--reader-leading, 1.65) + 0.55);
}

a { color: var(--accent); text-decoration-thickness: 1px; text-underline-offset: 2px; }
a:hover { text-decoration-thickness: 2px; }

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

.wrap {
  max-width: 1080px;
  margin-inline: auto;
  padding-inline: 20px;
}

/* ---------- header ---------- */

/* White (--card) on the grey page, like the cards, so the header reads as
   its own band; the shadow keeps it distinct as content scrolls under it. */
.site-header {
  border-block-end: 1px solid var(--border);
  background: var(--card);
  box-shadow: 0 1px 12px -6px rgb(0 0 0 / 0.18);
  position: sticky;
  inset-block-start: 0;
  z-index: 10;
}

.site-header .wrap {
  display: flex;
  align-items: center;
  gap: 20px;
  min-block-size: 64px;
  flex-wrap: wrap;
}

.brand {
  font-weight: 700;
  font-size: 1.15rem;
  color: var(--text);
  text-decoration: none;
  margin-inline-end: auto;
}

.nav { display: flex; gap: 18px; align-items: center; }
.nav a { color: var(--muted); text-decoration: none; font-size: 0.95rem; }
.nav a:hover, .nav a.is-current { color: var(--text); }

.lang-switch { display: flex; gap: 6px; }
.lang-switch a {
  padding: 4px 10px;
  border: 1px solid var(--border);
  border-radius: 999px;
  font-size: 0.85rem;
  text-decoration: none;
  color: var(--muted);
}
.lang-switch a.is-active {
  background: var(--accent-soft);
  border-color: var(--accent);
  color: var(--accent);
}

/* ---------- section headings ---------- */

.section-title {
  display: flex;
  align-items: center;
  gap: 14px;
  font-size: 0.78rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--muted);
  margin-block: 48px 18px;
}
/* A hairline running out from the label, so sections read as chapters. */
.section-title::after {
  content: '';
  flex: 1;
  block-size: 1px;
  background: var(--border);
}

.more-link { text-align: center; margin-block: 36px 8px; }

.btn-pill {
  display: inline-block;
  padding: 10px 20px;
  border: 1px solid var(--border);
  border-radius: 999px;
  color: var(--text);
  text-decoration: none;
  font-size: 0.92rem;
  font-weight: 600;
  transition: border-color 150ms, background 150ms;
}
.btn-pill:hover { border-color: var(--accent); color: var(--accent); background: var(--accent-soft); }

/* ---------- thumbnails ----------
 * Every post shows one: its featured image, or a generated gradient on the
 * post's own hue (see partials/thumb.ejs). Always 16:9 in a list, cropped to
 * fill, so a grid of mixed photos lines up like a video shelf.
 */
.thumb {
  display: block;
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
  transition: transform 400ms ease;
}

.thumb--generated {
  display: grid;
  place-items: center;
  background:
    radial-gradient(120% 90% at 15% 10%, hsl(var(--thumb-hue) 70% 62% / 0.85), transparent 60%),
    linear-gradient(135deg, hsl(var(--thumb-hue) 55% 42%), hsl(calc(var(--thumb-hue) + 45) 60% 26%));
  color: rgb(255 255 255 / 0.92);
  font-size: clamp(2.5rem, 7vw, 4.5rem);
  font-weight: 700;
  line-height: 1;
  user-select: none;
}
.thumb--generated [lang='ur'] { font-size: 1em; line-height: 1.6; }

/* ---------- cards ---------- */

.card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 28px 24px;
}

.card {
  display: flex;
  flex-direction: column;
  border: 1px solid var(--border);
  border-radius: calc(var(--radius) + 4px);
  overflow: hidden;
  background: var(--card);
  transition: transform 200ms ease, box-shadow 200ms ease, border-color 200ms;
}
.card:hover {
  transform: translateY(-3px);
  box-shadow: 0 14px 30px -12px rgb(0 0 0 / 0.22);
  border-color: transparent;
}
.card:hover .thumb { transform: scale(1.04); }

.card__media,
.hero__media { color: inherit; text-decoration: none; }

.card__media {
  position: relative;
  display: block;
  aspect-ratio: 16 / 9;
  overflow: hidden;
  background: var(--surface);
}

/* Reading time on the thumbnail, where a video shows its length. */
.card__duration {
  position: absolute;
  inset-block-end: 10px;
  inset-inline-end: 10px;
  padding: 2px 8px;
  border-radius: 6px;
  background: rgb(0 0 0 / 0.72);
  color: #fff;
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.02em;
}

.card__body { padding: 18px 20px 20px; display: flex; flex-direction: column; gap: 10px; flex: 1; }

.card__title { margin: 0; font-size: 1.18rem; line-height: 1.35; }
.card__title a { color: var(--text); text-decoration: none; }
.card__title a:hover { color: var(--accent); }
/* Two lines at most, so one long title does not stretch a whole row. */
.card__title,
.card__excerpt {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.card__title { -webkit-line-clamp: 2; line-clamp: 2; }
.card__excerpt { -webkit-line-clamp: 3; line-clamp: 3; margin: 0; color: var(--muted); font-size: 0.95rem; }
/* Clamping hides overflow, and at Latin leading that slices the tops off
   Nastaliq ascenders. Urdu gets its own leading and a little headroom. */
.card__title[lang='ur'] { line-height: 1.95; padding-block-start: 0.1em; }
.card__excerpt[lang='ur'] { line-height: 2; padding-block-start: 0.1em; }

/* Byline pinned to the bottom so bylines line up across a row. */
.card__foot { margin-block-start: auto; padding-block-start: 4px; }

/* ---------- home: lead story ---------- */

.hero {
  display: grid;
  gap: 0;
  margin-block-start: 36px;
  border: 1px solid var(--border);
  border-radius: calc(var(--radius) + 8px);
  overflow: hidden;
  background: var(--card);
}
.hero:hover .thumb { transform: scale(1.03); }

.hero__media { display: block; aspect-ratio: 16 / 9; overflow: hidden; background: var(--border); }
.hero__media .thumb--generated { font-size: clamp(4rem, 12vw, 8rem); }

.hero__body {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 14px;
  padding: 28px;
}

.hero__title { margin: 0; font-size: clamp(1.6rem, 3.2vw, 2.4rem); line-height: 1.15; letter-spacing: -0.01em; }
.hero__title[lang='ur'] { line-height: 1.9; }
.hero__title a { color: var(--text); text-decoration: none; }
.hero__title a:hover { color: var(--accent); }
.hero__excerpt { margin: 0; color: var(--muted); font-size: 1.05rem; }

.hero__cta {
  align-self: flex-start;
  margin-block-start: 6px;
  font-weight: 600;
  text-decoration: none;
}
.hero__cta:hover { text-decoration: underline; }

@media (min-width: 860px) {
  .hero { grid-template-columns: 1.35fr 1fr; }
  .hero__media { aspect-ratio: auto; min-block-size: 360px; }
  .hero__body { padding: 40px; }
}

.meta {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 10px;
  align-items: center;
  font-size: 0.82rem;
  color: var(--muted);
}

.badge {
  display: inline-block;
  padding: 2px 9px;
  border-radius: 999px;
  background: var(--accent-soft);
  color: var(--accent);
  font-size: 0.75rem;
  font-weight: 600;
  line-height: 1.6;
}
.badge--quiet { background: var(--surface); color: var(--text); border: 1px solid var(--border); }

/* ---------- article ---------- */

/* Reading progress, pinned under the sticky header. */
.reading-progress {
  position: fixed;
  inset-inline: 0;
  inset-block-start: 0;
  block-size: 3px;
  z-index: 20;
  pointer-events: none;
}
.reading-progress__bar {
  display: block;
  block-size: 100%;
  background: var(--accent);
  transform: scaleX(0);
  transform-origin: left;
}
[dir='rtl'] .reading-progress__bar { transform-origin: right; }

.article {
  --wide: min(1040px, calc(100vw - 40px));
  max-inline-size: var(--measure);
  margin-inline: auto;
  padding: 0 20px 40px;
  box-sizing: content-box;
}

/* The header sits on a soft wash of the post's own hue — the same colour as
   its generated thumbnail — so even a post with no image has an identity. */
.article__header {
  position: relative;
  padding-block: 56px 32px;
  isolation: isolate;
}
.article__header::before {
  content: '';
  position: absolute;
  z-index: -1;
  inset-block: 0;
  inset-inline: calc((100% - var(--wide)) / 2);
  border-radius: 0 0 28px 28px;
  background: radial-gradient(90% 120% at 50% 0%, hsl(var(--post-hue) 70% 55% / 0.14), transparent 70%);
}

.article__kicker { display: flex; gap: 8px; flex-wrap: wrap; margin-block-end: 18px; }

.article__title {
  margin: 0;
  font-size: clamp(2rem, 5vw, 3.1rem);
  line-height: 1.12;
  letter-spacing: -0.02em;
  font-weight: 800;
  text-wrap: balance;
}
/* Nastaliq's descenders need the room, or the title collides with the dek. */
.article[lang='ur'] .article__title { line-height: 1.85; letter-spacing: 0; font-weight: 700; }

.article__dek {
  margin: 16px 0 0;
  font-size: 1.22rem;
  line-height: 1.55;
  color: var(--muted);
  text-wrap: pretty;
}
.article[lang='ur'] .article__dek { line-height: 2.1; }

.article__byline {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-block-start: 26px;
  font-family: var(--font-latin);
  font-size: 0.9rem;
  line-height: 1.4;
}
.article__byline-text { display: flex; flex-direction: column; }
.article__author { font-weight: 600; }
.article__facts { color: var(--muted); display: flex; gap: 6px; }

/* Same width as the text, and cropped 16:9 — the crop the writer sees in the
   editor's preview and readers see as the thumbnail. Letting it run wider
   than the column, at the photo's own height, made a tall upload dwarf the
   post it belonged to. */
.article__cover {
  margin: 8px 0 40px;
  aspect-ratio: 16 / 9;
  border-radius: 14px;
  overflow: hidden;
  background: var(--surface);
  box-shadow: 0 18px 40px -24px rgb(0 0 0 / 0.35);
}
.article__cover img {
  display: block;
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
}

.article__rule {
  inline-size: 64px;
  margin: 4px 0 40px;
  border: 0;
  border-block-start: 3px solid hsl(var(--post-hue) 60% 50%);
  border-radius: 3px;
}

/* ---------- end of article ---------- */

.article__footer {
  margin-block-start: 56px;
  padding-block-start: 28px;
  border-block-start: 1px solid var(--border);
  display: grid;
  gap: 28px;
  font-family: var(--font-latin);
  font-size: 1rem;
  line-height: 1.5;
}

.share { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.share__label {
  margin-inline-end: 6px;
  font-size: 0.78rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--muted);
}
.share__link {
  padding: 6px 14px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: transparent;
  color: var(--text);
  font: inherit;
  font-size: 0.85rem;
  text-decoration: none;
  cursor: pointer;
}
.share__link:hover { border-color: var(--accent); color: var(--accent); }

.author-card {
  display: flex;
  align-items: center;
  gap: 18px;
  padding: 20px;
  border-radius: calc(var(--radius) + 6px);
  background: var(--surface);
}
.author-card .avatar--lg { inline-size: 64px; block-size: 64px; font-size: 1.4rem; }
.author-card p { margin: 0; }
.author-card__label {
  font-size: 0.75rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--muted);
}
.author-card__name { font-size: 1.15rem; font-weight: 700; }

.more-reading { margin-block-start: 24px; }

/*
 * Rendered post body. Every rule here has to survive both directions, which
 * is why blockquote uses border-inline-start rather than border-left.
 */
.prose { font-size: 1.08rem; }
.prose > * + * { margin-block-start: 1.15em; }
.prose > :first-child { margin-block-start: 0; }

.prose h2 {
  font-size: 1.65rem;
  line-height: 1.25;
  letter-spacing: -0.01em;
  margin-block-start: 2em;
}
.prose h3 { font-size: 1.3rem; line-height: 1.35; margin-block-start: 1.7em; }
.article[lang='ur'] .prose h2,
.article[lang='ur'] .prose h3 { line-height: 1.9; letter-spacing: 0; }

.prose a { text-decoration-color: color-mix(in srgb, var(--accent) 45%, transparent); text-underline-offset: 3px; }
.prose a:hover { text-decoration-color: var(--accent); }

/* A pull quote, not a grey aside: larger, with a hanging mark. */
.prose blockquote {
  position: relative;
  margin: 2em 0;
  padding: 6px 0 6px 0;
  padding-inline-start: 28px;
  border-inline-start: 4px solid hsl(var(--post-hue, 0) 60% 50%);
  font-size: 1.18em;
  line-height: 1.55;
  color: var(--text);
}
.article[lang='ur'] .prose blockquote { line-height: 2.2; }
.prose blockquote > * { margin: 0; }
.prose blockquote > * + * { margin-block-start: 0.6em; }

.prose ul, .prose ol { padding-inline-start: 1.4em; }
.prose li + li { margin-block-start: 0.45em; }
.prose li::marker { color: var(--accent); }

.prose code {
  font-family: var(--font-mono);
  font-size: 0.86em;
  background: var(--surface);
  border: 1px solid var(--border);
  padding: 1px 5px;
  border-radius: 5px;
}

.prose pre {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 16px 18px;
  overflow-x: auto;   /* long lines scroll inside the block, never the page */
  line-height: 1.55;
}
.prose pre code { background: none; border: 0; padding: 0; font-size: 0.85em; }

.prose figure { margin-block: 2em; margin-inline: 0; }
.prose figure img { border-radius: var(--radius); display: block; }
.prose figcaption {
  font-size: 0.85rem;
  color: var(--muted);
  margin-block-start: 10px;
  text-align: center;
}

/* A section break drawn as three dots rather than a hard line. */
.prose hr {
  border: 0;
  margin-block: 2.6em;
  text-align: center;
  overflow: visible;
}
.prose hr::after {
  content: '•  •  •';
  white-space: pre;
  letter-spacing: 0.5em;
  color: hsl(var(--post-hue, 0) 45% 55%);
  font-size: 0.9rem;
}


/* Alignment classes. 'left'/'right' are the author's visual intent, so they
 * stay physical — flipping them would fight the choice they made. */
.ta-left { text-align: left; }
.ta-center { text-align: center; }
.ta-right { text-align: right; }
.ta-justify { text-align: justify; }

/* ---------- pagination, footer, empty states ---------- */

.pagination {
  display: flex;
  gap: 10px;
  align-items: center;
  justify-content: center;
  margin-block: 40px;
}
.pagination a, .pagination span {
  padding: 8px 14px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  text-decoration: none;
  color: var(--text);
  font-size: 0.9rem;
}
.pagination .is-disabled { opacity: 0.4; }

.empty {
  text-align: center;
  padding: 60px 20px;
  color: var(--muted);
  border: 1px dashed var(--border);
  border-radius: var(--radius);
}

.site-footer {
  border-block-start: 1px solid var(--border);
  margin-block-start: 60px;
  padding-block: 30px;
  color: var(--muted);
  font-size: 0.88rem;
}

/* ---------- theme toggle ---------- */

.theme-toggle {
  display: inline-grid;
  place-items: center;
  inline-size: 34px;
  block-size: 34px;
  padding: 0;
  flex: none;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: transparent;
  color: var(--muted);
  cursor: pointer;
}
.theme-toggle:hover { color: var(--text); border-color: var(--muted); }
.theme-toggle svg { inline-size: 17px; block-size: 17px; display: block; }

/* data-mode names the theme the button switches TO, so the moon shows on a
 * light page and the sun on a dark one. Both icons ship in the markup and CSS
 * reveals one, which keeps theme.js free of innerHTML — and therefore
 * uncontroversial under the CSP. */
/* Two classes, so this outranks `.theme-toggle svg` above (a class plus an
 * element). With only `.theme-toggle__icon` here, that sizing rule's
 * display: block won and both icons showed at once. */
.theme-toggle .theme-toggle__icon { display: none; }
.theme-toggle[data-mode='light'] .theme-toggle__icon--light,
.theme-toggle[data-mode='dark'] .theme-toggle__icon--dark { display: block; }

/* Before theme.js sets data-mode — and if JS never runs at all — show the
 * moon rather than an empty circle. */
.theme-toggle:not([data-mode]) .theme-toggle__icon--dark { display: block; }

/* ---------- avatars ---------- */

.avatar {
  display: inline-grid;
  place-items: center;
  flex: none;
  border-radius: 50%;
  overflow: hidden;
  background: var(--surface);
  object-fit: cover;
  /* A hairline ring keeps a photo whose edges match the page from dissolving
     into the background — most visible on white product shots in light mode. */
  box-shadow: inset 0 0 0 1px rgb(0 0 0 / 0.08);
  vertical-align: middle;
}

.avatar--sm { inline-size: 26px; block-size: 26px; font-size: 0.62rem; }
.avatar--md { inline-size: 36px; block-size: 36px; font-size: 0.82rem; }
.avatar--lg { inline-size: 96px; block-size: 96px; font-size: 2rem; }

/* Initials fallback. Saturation and lightness are fixed and only the hue
   varies, so every generated colour clears contrast against white text —
   letting lightness vary per name is how these end up illegible. */
.avatar--initials {
  background: hsl(var(--avatar-hue, 220) 42% 42%);
  color: #fff;
  font-weight: 600;
  letter-spacing: 0.02em;
  line-height: 1;
  user-select: none;
}

:root[data-theme='dark'] .avatar--initials { background: hsl(var(--avatar-hue, 220) 38% 46%); }

/* Name-with-avatar rows, used in bylines and admin tables alike. */
.byline {
  display: inline-flex;
  align-items: center;
  gap: 8px;
}

/* ---------- reading settings panel ---------- */

.reader-prefs { position: relative; flex: none; }

/* The default disclosure triangle would sit next to the icon. */
.reader-prefs > summary { list-style: none; }
.reader-prefs > summary::-webkit-details-marker { display: none; }

.reader-prefs__button {
  display: inline-grid;
  place-items: center;
  inline-size: 34px;
  block-size: 34px;
  border: 1px solid var(--border);
  border-radius: 999px;
  color: var(--muted);
  cursor: pointer;
}
.reader-prefs__button:hover { color: var(--text); border-color: var(--muted); }
.reader-prefs[open] .reader-prefs__button { color: var(--text); border-color: var(--muted); }
.reader-prefs__button svg { inline-size: 17px; block-size: 17px; display: block; }

.reader-prefs__panel {
  position: absolute;
  inset-block-start: calc(100% + 8px);
  /* inset-inline-end, so the panel hangs from the button in both directions
     and never opens off the edge of an RTL page. */
  inset-inline-end: 0;
  z-index: 20;
  inline-size: 270px;
  max-inline-size: calc(100vw - 40px);
  padding: 16px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--card);
  box-shadow: 0 10px 30px rgb(0 0 0 / 0.12);
}

.reader-prefs__title {
  margin: 0 0 12px;
  font-size: 0.8rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--muted);
}

.reader-prefs__group { margin: 0 0 14px; padding: 0; border: 0; }
.reader-prefs__group legend {
  padding: 0;
  font-size: 0.78rem;
  font-weight: 600;
  margin-block-end: 6px;
}

.reader-prefs__options { display: flex; flex-wrap: wrap; gap: 6px; }

/* The radio itself is hidden but still focusable and still the thing being
   clicked — the label's span is only its skin. Removing it from the DOM, or
   using display:none, would take it out of the tab order and off the
   accessibility tree, which is the opposite of the point here. */
.reader-prefs__options input {
  position: absolute;
  opacity: 0;
  inline-size: 1px;
  block-size: 1px;
}

.reader-prefs__options label { cursor: pointer; }
.reader-prefs__options span {
  display: inline-block;
  padding: 4px 10px;
  border: 1px solid var(--border);
  border-radius: 999px;
  font-size: 0.8rem;
  color: var(--muted);
}
.reader-prefs__options label:hover span { color: var(--text); }
.reader-prefs__options input:checked + span {
  background: var(--accent-soft);
  border-color: var(--accent);
  color: var(--accent);
  font-weight: 600;
}
.reader-prefs__options input:focus-visible + span {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.reader-prefs__note {
  margin: 6px 0 0;
  font-size: 0.72rem;
  color: var(--muted);
}

.reader-prefs__switch {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 0.82rem;
  margin-block-end: 14px;
  cursor: pointer;
}

.reader-prefs__reset {
  inline-size: 100%;
  padding: 7px 12px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--surface);
  color: var(--text);
  font: inherit;
  font-size: 0.82rem;
  cursor: pointer;
}
.reader-prefs__reset:hover { border-color: var(--muted); }

/* ---------- motion ----------
 * Honours the OS setting rather than offering a control for it: the reader
 * has already answered this question at system level.
 */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* ---------- images placed by the writer ---------- */

/* Each is a figure with an .img--* class from the renderer. Left/right are
 * physical, like the .ta-* alignment classes: the writer's visual choice. */
.prose figure.img { display: flex; flex-direction: column; }
.prose .img--center { align-items: center; }
.prose .img--left   { align-items: flex-start; }
.prose .img--right  { align-items: flex-end; }

.prose .img--wrap-left,
.prose .img--wrap-right { display: block; max-inline-size: 100%; }
.prose .img--wrap-left  { float: left;  margin: 0.3em 1.4em 0.8em 0; }
.prose .img--wrap-right { float: right; margin: 0.3em 0 0.8em 1.4em; }
.prose::after { content: ''; display: block; clear: both; }

/* Free: anchored where it sits in the text, drawn at the writer's offset
 * (inline left/top), over the text. The text underneath is covered. */
.prose .img--free {
  position: relative;
  block-size: 0;
  margin: 0;
  z-index: 2;
}
.prose .img--free img { position: absolute; max-inline-size: 100%; }

/* On a phone the column is too narrow to share: a free image would cover
 * most of the words. It goes back into the text, centred, instead. */
@media (max-width: 640px) {
  .prose .img--wrap-left,
  .prose .img--wrap-right { float: none; margin: 1em 0; }
  .prose .img--free { block-size: auto; margin-block: 1em; display: flex; justify-content: center; }
  .prose .img--free img { position: static; translate: none; }
}

/* ---------- video embeds ---------- */

.prose .video-embed {
  position: relative;
  aspect-ratio: 16 / 9;
  inline-size: 100%;
  margin: 1.5em 0;
  border-radius: var(--radius);
  overflow: hidden;
  background: #000;
}
.prose .video-embed iframe { position: absolute; inset: 0; inline-size: 100%; block-size: 100%; border: 0; }

/* A writer's own address: their avatar and name stand in for the site's. */
.brand--writer { display: inline-flex; align-items: center; gap: 10px; }
