/* ════════════════════════════════════════════════════════════════════════════
   READER SURFACE — shared by the blog/archive article (.ad-intro) and the
   course konspekt (.lesson-notes).

   Loaded UNCONDITIONALLY wherever a body is shown — unlike components.css,
   which the blog only pulls in when a post contains a `:::directive`. That is
   the point of this file being separate: a prose-only post with a photo still
   needs the size ratio, the figure styling and the zoom.

   Four jobs:
     1. the A−/A+ size ratio, and every block that ignored it
     2. callout bodies that laid multiple paragraphs out side by side
     3. figures, captions and the image zoom (lightbox.js)
     4. «Читать подробнее» / «Смотреть видео» cards between videos and articles
   ════════════════════════════════════════════════════════════════════════════ */


/* ── 1. SIZE RATIO ────────────────────────────────────────────────────────────
   The steppers set html[data-reader-size]. Body copy already followed it via
   the container's font-size — but 21 block styles on an article (35 counting
   the lesson page) were pinned in px or rem, and rem is ROOT-relative, so it
   never sees a container's font-size either. Measured: at XL the paragraphs
   grew to 23px while every Arabic table cell, vocab row, quiz option and
   checklist stayed at 17px.

   --rdr is the body's own step ratio (0.94 / 1.06 / 1.2 / 1.36 rem) normalised
   to «m» = 1. Each override below is the ORIGINAL declaration × --rdr, so the
   default size is pixel-identical to before and every other size moves in
   lockstep with the paragraphs.

   --rdr-d is for display text (headings, pull-quotes): half the rate. At XL the
   body grows 28% and a heading 14% — otherwise a bigger reading size turns
   every heading into a poster, which is the opposite of what the reader asked
   for. Both live on <html> so they resolve against the same element that
   carries data-reader-size. */
:root { --rdr: 1; }
html[data-reader-size='s']  { --rdr: 0.887; }
html[data-reader-size='l']  { --rdr: 1.132; }
html[data-reader-size='xl'] { --rdr: 1.283; }
:root { --rdr-d: calc(1 + (var(--rdr) - 1) * 0.5); }

/* `:is(.ad-intro, .lesson-notes) .x` is (0,2,0) — it beats every base rule in
   components.css, which is (0,1,0) or (0,2,1) at most for these, regardless of
   which file loads last. */
:is(.ad-intro, .lesson-notes) .aoa-table-caption   { font-size: calc(13px * var(--rdr)); }
:is(.ad-intro, .lesson-notes) .aoa-table [lang="ar"],
:is(.ad-intro, .lesson-notes) .aoa-table :is(td, th):lang(ar) {
  font-size: calc(17px * var(--rdr));
}

:is(.ad-intro, .lesson-notes) .vocab-title         { font-size: calc(12px * var(--rdr)); }
:is(.ad-intro, .lesson-notes) .vocab-ar            { font-size: calc(19px * var(--rdr)); }
:is(.ad-intro, .lesson-notes) .vocab-tr            { font-size: calc(14px * var(--rdr)); }
:is(.ad-intro, .lesson-notes) .vocab-ru            { font-size: calc(15px * var(--rdr)); }

:is(.ad-intro, .lesson-notes) .quiz-question       { font-size: calc(1.15rem * var(--rdr)); }
:is(.ad-intro, .lesson-notes) .quiz-option         { font-size: calc(1rem * var(--rdr)); }
:is(.ad-intro, .lesson-notes) .quiz-option .quiz-letter { font-size: calc(0.92rem * var(--rdr)); }

:is(.ad-intro, .lesson-notes) .todo-title          { font-size: calc(0.72rem * var(--rdr)); }
:is(.ad-intro, .lesson-notes) .todo-item           { font-size: calc(1rem * var(--rdr)); }

:is(.ad-intro, .lesson-notes) .match-chip          { font-size: calc(15px * var(--rdr)); }
:is(.ad-intro, .lesson-notes) .match-chip[lang="ar"] { font-size: calc(18px * var(--rdr)); }
:is(.ad-intro, .lesson-notes) .tf-statement        { font-size: calc(17px * var(--rdr)); }
:is(.ad-intro, .lesson-notes) .tf-option           { font-size: calc(15px * var(--rdr)); }
:is(.ad-intro, .lesson-notes) .practice-kicker     { font-size: calc(11px * var(--rdr)); }
:is(.ad-intro, .lesson-notes) .practice-btn        { font-size: calc(13px * var(--rdr)); }
:is(.ad-intro, .lesson-notes) .compare-kicker      { font-size: calc(11px * var(--rdr)); }

:is(.ad-intro, .lesson-notes) .pullquote .pullquote-body {
  font-size: calc(clamp(1.3rem, 0.7rem + 4.2cqi, 2.05rem) * var(--rdr-d));
}
:is(.ad-intro, .lesson-notes) .pullquote :is(.pullquote-author, .pullquote-role) {
  font-size: calc(0.78rem * var(--rdr));
}


/* ── 2. CALLOUT BODIES ────────────────────────────────────────────────────────
   `.n-body` / `.v-body` are `display:flex; align-items:center` in the DEFAULT
   row direction — built for one paragraph. Give one two paragraphs, or a
   paragraph and a list, and they sit side by side as columns. Column direction
   keeps a lone paragraph vertically centred and stacks everything else. */
:is(.ad-intro, .lesson-notes) :is(.callout-note .n-body, .callout-vertical .v-body) {
  flex-direction: column;
  align-items: stretch;
  justify-content: center;
}
:is(.ad-intro, .lesson-notes) :is(.callout-note .n-body, .callout-vertical .v-body) > * + * {
  margin-top: 0.6em;
}
:is(.ad-intro, .lesson-notes) :is(.callout-note .n-body, .callout-vertical .v-body) :is(ul, ol) {
  margin: 0;
  padding-left: 1.2em;
}
:is(.ad-intro, .lesson-notes) :is(.callout-note .n-body, .callout-vertical .v-body) li + li {
  margin-top: 0.35em;
}

/* Phones: the rotated side label (ЗАМЕТКА / ВАЖНО) plus its rule take ~90px
   out of a 390px screen, so the text inside wraps every three words. Lay the
   label flat above the text instead. */
@media (max-width: 560px) {
  :is(.ad-intro, .lesson-notes) :is(.callout-note, .callout-vertical) {
    flex-direction: column;
    gap: 0.45em;
    min-height: 0;
  }
  :is(.ad-intro, .lesson-notes) :is(.callout-note .n-badge, .callout-vertical .v-label) {
    writing-mode: horizontal-tb;
    transform: none;
    align-self: flex-start;
    padding: 0.25em 0.75em;
    letter-spacing: 0.22em;
  }
  :is(.ad-intro, .lesson-notes) .callout-vertical .v-label { padding-inline: 0; opacity: 0.7; }
  :is(.ad-intro, .lesson-notes) :is(.callout-note .n-rule, .callout-vertical .v-rule) { display: none; }
  :is(.ad-intro, .lesson-notes) :is(.callout-note .n-body, .callout-vertical .v-body) {
    padding: 0.9em 1.05em;
  }
}


/* ── 3. FIGURES, CAPTIONS, ZOOM ───────────────────────────────────────────────
   Markdown gives an image as `<p><img></p>`. Treat that paragraph as a figure.
   The authoring convention is a short line right after the image — that line
   is its caption. It is styled muted and slightly smaller, not radically
   different, so a paragraph that merely happens to follow a picture still
   reads normally. */
:is(.ad-intro, .lesson-notes) p:has(> img:only-child) {
  margin: 1.4em 0 0.5em;
  text-align: center;
}
:is(.ad-intro, .lesson-notes) p:has(> img:only-child) > img {
  display: block;
  max-width: 100%;
  height: auto;
  margin-inline: auto;
  border-radius: 14px;
  border: 1px solid var(--rule, rgba(0, 0, 0, 0.1));
  box-shadow: 0 1px 2px rgba(40, 28, 8, 0.06), 0 10px 28px -18px rgba(40, 28, 8, 0.35);
}
:is(.ad-intro, .lesson-notes) p:has(> img:only-child) + p {
  margin-top: 0;
  font-size: 0.9em;
  line-height: 1.5;
  color: var(--fg-muted, currentColor);
  text-align: center;
}
/* Inside a :::columns row, the caption belongs to its own cell only. */
:is(.ad-intro, .lesson-notes) .columns .col > p:has(> img:only-child) { margin-top: 0; }
:is(.ad-intro, .lesson-notes) .columns .col > p:has(> img:only-child) + p {
  text-align: left;
  font-size: 0.86em;
}

/* Zoomable affordance — lightbox.js adds [data-zoomable] only to images it
   will actually open, so nothing here promises a click that does nothing. */
:is(.ad-intro, .lesson-notes) img[data-zoomable] {
  cursor: zoom-in;
  transition: transform 0.18s ease, box-shadow 0.18s ease;
}
:is(.ad-intro, .lesson-notes) img[data-zoomable]:hover {
  transform: translateY(-1px);
  box-shadow: 0 2px 4px rgba(40, 28, 8, 0.08), 0 16px 34px -18px rgba(40, 28, 8, 0.45);
}
:is(.ad-intro, .lesson-notes) img[data-zoomable]:focus-visible {
  outline: 3px solid var(--accent, #d4a437);
  outline-offset: 3px;
}

/* The overlay lives on <body>, outside both reading surfaces, so it cannot use
   their tokens. A dark scrim is the correct choice in either theme: it is what
   makes a white diagram and a dark photo both read, and it is what every image
   viewer uses for the same reason. */
.aoa-lb {
  position: fixed;
  inset: 0;
  z-index: 2147483000;
  display: grid;
  grid-template-rows: auto minmax(0, 1fr) auto;
  background: rgba(12, 10, 8, 0.95);
  /* Even at 95% the article's text reads through behind a zoomed picture.
     Blurring it turns legible words into texture — nothing competes with the
     image. Where backdrop-filter is unsupported the scrim alone still works. */
  -webkit-backdrop-filter: blur(14px) saturate(0.7);
          backdrop-filter: blur(14px) saturate(0.7);
  color: #f4ece0;
  opacity: 0;
  transition: opacity 0.2s ease;
  -webkit-tap-highlight-color: transparent;
}
.aoa-lb.is-open { opacity: 1; }
.aoa-lb[hidden] { display: none !important; }

.aoa-lb-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  padding: calc(0.6rem + env(safe-area-inset-top, 0px)) 0.8rem 0.6rem;
  font: 600 0.82rem/1.2 system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
  letter-spacing: 0.02em;
}
.aoa-lb-count { opacity: 0.7; font-variant-numeric: tabular-nums; }
.aoa-lb-tools { display: flex; gap: 0.4rem; }

.aoa-lb-btn {
  display: inline-grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border: 1px solid rgba(255, 255, 255, 0.16);
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.07);
  color: inherit;
  font: inherit;
  cursor: pointer;
  transition: background 0.15s ease, border-color 0.15s ease;
}
.aoa-lb-btn:hover { background: rgba(255, 255, 255, 0.16); border-color: rgba(255, 255, 255, 0.3); }
.aoa-lb-btn:focus-visible { outline: 2px solid #e6bd6a; outline-offset: 2px; }
.aoa-lb-btn svg { width: 20px; height: 20px; }
.aoa-lb-btn[disabled] { opacity: 0.3; cursor: default; }
/* `display:inline-grid` above outranks the UA's [hidden] rule. */
.aoa-lb-btn[hidden] { display: none; }

/* The stage scrolls when zoomed past the viewport — that scroll IS the pan, on
   a mouse wheel, a trackpad and a finger alike, with no custom drag code to get
   wrong. `touch-action` is left alone so phones keep native pinch-zoom. */
.aoa-lb-stage {
  position: relative;
  overflow: auto;
  overscroll-behavior: contain;
  display: grid;
  place-items: center;
  padding: 0 clamp(0.5rem, 3vw, 4.5rem);
}
.aoa-lb-img {
  display: block;
  max-width: 100%;
  max-height: 100%;
  width: auto;
  height: auto;
  object-fit: contain;
  border-radius: 10px;
  background: #fff;
  box-shadow: 0 30px 80px -30px rgba(0, 0, 0, 0.8);
  cursor: zoom-in;
  user-select: none;
  -webkit-user-drag: none;
}
/* Vector diagrams arrive at their small intrinsic size (the anatomy SVGs are
   424 px wide) — "fit to screen" means scaling them UP, which a raster photo
   must never do. lightbox.js sets data-kind="vector" for SVGs. */
.aoa-lb-img[data-kind='vector'] {
  width: min(100%, calc((100vh - 9rem) * var(--lb-ratio, 1.6)));
  /* dvh: on phones 100vh includes the collapsing URL bar and overshoots. */
  width: min(100%, calc((100dvh - 9rem) * var(--lb-ratio, 1.6)));
  max-height: none;
}
.aoa-lb.is-zoomed .aoa-lb-stage { place-items: start; }
.aoa-lb.is-zoomed .aoa-lb-img {
  max-width: none;
  max-height: none;
  width: var(--lb-zoom-w);
  cursor: zoom-out;
  margin: auto;
}

.aoa-lb-cap {
  padding: 0.7rem clamp(1rem, 4vw, 3rem) calc(0.9rem + env(safe-area-inset-bottom, 0px));
  text-align: center;
  font: 400 0.95rem/1.5 system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
  color: rgba(244, 236, 224, 0.86);
  max-width: 62rem;
  margin-inline: auto;
}
.aoa-lb-cap:empty { display: none; }

/* Prev/next float over the stage edges on wide screens; on a phone they would
   cover the image, and a swipe does the same job, so they step aside. */
.aoa-lb-nav {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  z-index: 1;
}
.aoa-lb-prev { left: 0.8rem; }
.aoa-lb-next { right: 0.8rem; }
/* The stage scrolls when zoomed, and these would scroll away with it. */
.aoa-lb.is-zoomed .aoa-lb-nav { display: none; }
@media (max-width: 640px) {
  .aoa-lb-nav { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  .aoa-lb,
  :is(.ad-intro, .lesson-notes) img[data-zoomable] { transition: none; }
  :is(.ad-intro, .lesson-notes) img[data-zoomable]:hover { transform: none; }
}

html.aoa-lb-lock,
html.aoa-lb-lock body { overflow: hidden; }


/* ── 4. VIDEO ↔ ARTICLE CARDS ─────────────────────────────────────────────────
   «Читать подробнее» under a video, «Смотреть видео» under an article.
   Rendered by the pages (see RelatedLinks.astro); styled here so the blog and
   the lesson player share one look. Tokens fall back to neutral values because
   the lesson page and the blog define different sets. */
.rel {
  margin: 2.2rem 0 0;
  padding: 1.1rem 1.15rem 1.2rem;
  border: 1px solid var(--rule, rgba(0, 0, 0, 0.1));
  border-radius: 18px;
  background: var(--surface, rgba(255, 255, 255, 0.5));
}
.rel-kicker {
  margin: 0 0 0.75rem;
  font: 700 0.7rem/1.2 system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--accent, var(--gold, #b07f12));
}
.rel-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.55rem; }
.rel-item {
  display: grid;
  grid-template-columns: 2.6rem minmax(0, 1fr) auto;
  align-items: center;
  gap: 0.85rem;
  padding: 0.75rem 0.85rem;
  border-radius: 13px;
  border: 1px solid transparent;
  color: inherit;
  text-decoration: none;
  transition: background 0.15s ease, border-color 0.15s ease;
}
.rel-item:hover {
  background: color-mix(in srgb, var(--accent, #b07f12) 7%, transparent);
  border-color: color-mix(in srgb, var(--accent, #b07f12) 26%, transparent);
}
.rel-item:focus-visible { outline: 2px solid var(--accent, #b07f12); outline-offset: 2px; }
.rel-icon {
  display: grid;
  place-items: center;
  width: 2.6rem;
  height: 2.6rem;
  border-radius: 11px;
  background: color-mix(in srgb, var(--accent, #b07f12) 14%, transparent);
  color: var(--accent, #b07f12);
}
.rel-icon svg { width: 1.15rem; height: 1.15rem; }
.rel-body { min-width: 0; }
.rel-title {
  display: block;
  font-weight: 650;
  line-height: 1.3;
  color: var(--fg, inherit);
}
.rel-meta {
  display: block;
  margin-top: 0.15rem;
  font-size: 0.84em;
  color: var(--fg-muted, currentColor);
  opacity: 0.9;
}
.rel-go { color: var(--accent, #b07f12); font-size: 1.1rem; }
