.lesson__preview-banner {
  background-color: oklch(var(--lch-yellow) / 0.12);
  border: 1px solid oklch(var(--lch-yellow) / 0.4);
  border-radius: 0.5rem;
  color: var(--color-ink);
  font-size: 0.85rem;
  margin-block-end: 1.5rem;
  padding: 0.6rem 0.9rem;
}

/* Fallback for a missing image asset (e.g. a not-yet-drawn "TODO-*.png")
   so one pending illustration never breaks the lesson. */
.attachment__missing {
  align-items: center;
  background-color: var(--color-subtle-light);
  border: 1px dashed var(--color-subtle);
  border-radius: 0.5rem;
  color: var(--color-subtle-dark);
  display: flex;
  font-size: 0.85rem;
  justify-content: center;
  min-block-size: 6rem;
  padding: var(--block-space);
}

.lesson {
  margin-inline: auto;
  max-inline-size: 44rem;
  padding-block: 2.5rem;
  padding-inline: 1rem;

  @media (min-width: 640px) {
    padding-block: 3.5rem;
    padding-inline: 1.5rem;
  }

  @media (min-width: 1024px) {
    padding-inline: 2rem;
  }
}

.lesson__header {
  margin-block: 0.75rem var(--block-space-double);
}

/* TOC anchors (sections + ## headings) must land below the sticky header. */
.lesson :is(section[id], h2[id]) {
  scroll-margin-block-start: 5rem;
}

/* Regular display face (Inter Tight), not GOST: this is the single most-read
   heading on the site, often safety-critical content — clarity and reading
   speed win over the "engineered" identity, which stays on the profession
   card/hero where a reader only glances at it once. */
.lesson__title {
  /* Capped at 2.1rem (was 2.5) so long multi-word technical titles read as a
     calmer landmark, not a wall. */
  font-size: clamp(1.75rem, 4.5vw, 2.1rem);
  font-weight: 700;
  letter-spacing: -0.025em;
  line-height: 1.1;
  margin-block: 0;
}

.lesson__topbar {
  align-items: center;
  display: flex;
  gap: var(--block-space);
  justify-content: space-between;
  margin-block-end: 0.75rem;
}

.lesson__trail {
  align-items: center;
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem 1rem;
  min-inline-size: 0;
}

.lesson__tools {
  align-items: center;
  color: var(--color-subtle-dark);
  display: flex;
  flex-shrink: 0;
  gap: 0.65rem;
}

.lesson__tool {
  align-items: center;
  background: none;
  border: 0;
  color: inherit;
  cursor: pointer;
  display: inline-flex;
  font: inherit;
  /* 44px hit area (a11y/mobile-first) — the glyph stays small but each button
     fills a full touch target, so neighbours never overlap or mis-tap. */
  justify-content: center;
  min-block-size: 2.75rem;
  min-inline-size: 2.75rem;
  padding: 0;
  transition: color 200ms ease;

  .icon {
    block-size: 1.05rem;
    inline-size: 1.05rem;
  }

  @media (any-hover: hover) {
    &:hover {
      color: var(--color-ink);
    }
  }
}

/* Copy-link feedback is icon-only: the glyph briefly swaps to a green check
   (the controller toggles `--copied` + updates the screen-reader label). */
.lesson__copy-icon {
  display: inline-flex;
}

.lesson__copy-icon--done,
.lesson__copy--copied .lesson__copy-icon--default {
  display: none;
}

.lesson__copy--copied .lesson__copy-icon--done {
  display: inline-flex;
}

.lesson__copy--copied {
  color: var(--color-positive);
}

/* Bookmark keeps just the glyph here, matching the project-card treatment —
   title/aria-label carry the meaning. */
.lesson__tools .bookmark-btn__label {
  display: none;
}

.lesson__intro {
  border-inline-start: 2px solid var(--color-subtle-dark);
  margin-block-end: var(--block-space-double);
  padding-inline-start: 1rem;
}

.lesson__intro-label {
  color: var(--color-subtle-dark);
  font-size: 0.85rem;
  font-weight: 500;
  margin-block: 0 0.25rem;
}

/* Each section (Что изучить / Документы / Задание) gets a hairline divider so
   the lesson reads as distinct chunks, not one wall of text. */
.lesson__section {
  border-block-start: 1px solid var(--color-subtle);
  margin-block-start: 3rem;
  padding-block-start: 2.5rem;
}

/* For a section that's its own card (e.g. the resources panel): the panel is
   the boundary, so drop the divider line and top padding. */
.lesson__section--plain {
  border-block-start: 0;
  padding-block-start: 0;
}

/* The body section has no own heading (the prose opens with its first ##),
   so the prose must sit flush under the section divider. */
.lesson__section .prose > :first-child {
  margin-block-start: 0;
}

/* A step above the in-prose ## subheadings in the hierarchy. */
.lesson__heading {
  color: var(--color-ink);
  font-family: var(--font-display);
  font-size: 1.4rem;
  font-weight: 700;
  letter-spacing: -0.015em;
  margin-block: 0 1.25rem;
}
.lesson__heading--task {
  -webkit-text-stroke: 0.25px currentColor;
  align-items: center;
  border-block-end: 1px solid var(--color-subtle);
  display: flex;
  font-family: var(--font-technical);
  font-size: 1.35rem;
  font-weight: 400;
  gap: 0.7ch;
  letter-spacing: 0.1em;
  margin-block: 0 1.25rem;
  padding-block-end: 0.7rem;
  text-transform: uppercase;
}

.lesson__heading--task .icon {
  block-size: 1.25em;
  color: var(--color-subtle-dark);
  flex-shrink: 0;
  inline-size: 1.25em;
}

.lesson__task {
  border-block-end: 1px solid var(--color-subtle);
  padding-block-end: 2.2rem;
}

/* When the brief is the last block before the end-of-lesson action bar, the
   bar's own top border already serves as the divider — so drop the brief's
   closing hairline (and its bottom padding) to avoid a stacked double line. */
.lesson__section:has(+ .lesson-complete) .lesson__task {
  border-block-end: 0;
  padding-block-end: 0;
}

/* GOST is a thin, narrow monoline face with wide built-in side-bearings, so it
   reads "airy" by default. To match Inter's density we drop the extra tracking
   and word-spacing, keep compact leading, and hold a modest size. The hairline
   text-stroke thickens the light weight to Inter 400's typographic colour. */
.lesson__task .prose {
  -webkit-text-stroke: 0.25px currentColor;
  font-family: var(--font-technical);
  font-size: 1.15rem;
  letter-spacing: -0.01em;
  line-height: 1.45;
}

/* All in-brief headings stay bright (ink) — a heading must never be dimmer
   than the text it leads; hierarchy comes from size, not colour. */
.lesson__task .prose :is(h2, h3, h4) {
  color: var(--color-ink);
  font-family: var(--font-technical);
  font-weight: 400;
  text-transform: uppercase;
}

.lesson__task .prose :is(h2, h3) {
  border-block-end: 1px solid var(--color-subtle);
  font-size: 1.15rem;
  letter-spacing: 0.1em;
  margin-block: 1.9rem 0.6rem;
  padding-block-end: 0.35rem;
}

/* Sub-steps get a leading tick via ::before, like a drawing annotation mark. */
.lesson__task .prose h4 {
  align-items: baseline;
  display: flex;
  font-size: 1rem;
  gap: 0.8ch;
  letter-spacing: 0.08em;
  margin-block: 1.5rem 0.4rem;
}

.lesson__task .prose h4::before {
  background: var(--color-subtle-dark);
  block-size: 2px;
  content: "";
  flex: 0 0 1.4ch;
  transform: translateY(-0.35em);
}

/* Callouts keep their own sans voice so a safety [!ОПАСНО] block stays
   recognisable — must NOT inherit the GOST stroke-thickening (already Inter). */
.lesson__task .callout {
  -webkit-text-stroke: 0;
  font-family: var(--font-sans);
}

.lesson-task-journal {
  margin-block-start: 1.25rem;

  .icon {
    block-size: 1.1rem;
    inline-size: 1.1rem;
  }
}

/* The learner's own past entries for this task — the practice loop, visible. */
.lesson-task-entries {
  margin-block-start: var(--block-space);
}

.lesson-task-entries__title {
  color: var(--color-subtle-dark);
  font-size: 0.85rem;
  margin-block: 0 0.35rem;
}

.lesson-task-entries__list {
  display: flex;
  flex-direction: column;
  font-size: 0.9rem;
  gap: 0.25rem;
  list-style: none;
  margin-block: 0;
  padding-inline-start: 0;
}

/* Grid, not flex: the lang badge is optional per row, and with a flex row
   that meant a row without one had its title start ~2rem further left than
   its neighbours — every row's title visibly ragged against the others.
   The grid lives on .resource-block__list (the shared ancestor of BOTH group
   <ul>s), not here — a lone "Рекомендуемые" list with no lang badge on any
   row would otherwise size its own columns independently of "Обязательные"
   above it. Both this <ul> and its <li>s are display: contents purely to pass
   their children through to that shared grid. */
.lesson-resources {
  display: contents;
  list-style: none;
  margin-block: 0;
  padding-inline-start: 0;
}

.lesson-resource {
  display: contents;
}

/* Sits at the top-left so the badge stays put when a long title wraps. */
.lesson-resource__badge {
  grid-column: 1;
  gap: 0.3em;
  margin-block-start: 0.1em;
}

.lesson-resource__lang {
  grid-column: 2;
  margin-block-start: 0.1em; /* matches the kind badge's optical nudge */
}

.lesson-resource__badge .icon {
  block-size: 0.95em;
  flex-shrink: 0;
  inline-size: 0.95em;
}

.lesson-resource__link {
  color: var(--color-link);
  font-size: 0.95rem;
  text-decoration: underline;
  text-decoration-color: var(--color-subtle);
  transition: text-decoration-color 200ms ease;

  @media (any-hover: hover) {
    &:hover {
      text-decoration-color: var(--color-link);
    }
  }
}

/* Importance is conveyed by the group heading and weight — not by link colour,
   so every resource still reads as a clickable link. */
.lesson-resource--required .lesson-resource__link {
  font-weight: 600;
}

/* A name-only source: readable (the exact title IS the value), just not a link —
   ink colour + no underline reads as "reference", the blue links read as clickable. */
.lesson-resource__link--pending {
  color: var(--color-ink);
  text-decoration: none;
}

.lesson-resource__body {
  display: grid;
  gap: 0.15rem;
  grid-column: 3;
}

/* The curator's one-liner: WHAT exactly to read in a 400-page document. */
.lesson-resource__note {
  color: var(--color-subtle-dark);
  font-size: 0.85rem;
  line-height: 1.5;
}

.lesson-edit-prompt {
  color: var(--color-subtle-dark);
  font-size: 0.9rem;
  margin-block-start: 2.5rem;
}

/* Faint by default so touch users can still find it; on pointer devices it
   stays hidden until the reader hovers the section or tabs to it —
   discoverable, never visual noise. */
.lesson-section-edit {
  font-size: 0.8rem;
  margin-block: var(--block-space) 0;
  opacity: 0.4;
  transition: opacity 200ms ease;

  .lesson-edit-link .icon {
    block-size: 0.9rem;
    inline-size: 0.9rem;
  }
}

@media (any-hover: hover) {
  .lesson__intro .lesson-section-edit,
  .lesson__section .lesson-section-edit {
    opacity: 0;
  }

  .lesson__intro:hover .lesson-section-edit,
  .lesson__section:hover .lesson-section-edit,
  .lesson-section-edit:focus-within {
    opacity: 1;
  }
}

.lesson-edit-link {
  align-items: center;
  display: inline-flex;
  gap: 0.25rem;
}

/* TOP-style: completion toggle on the left, "next lesson" always available
   on the right — marking done is encouraged, never required to move on. */
.lesson-complete {
  align-items: center;
  border-block-start: 1px solid var(--color-subtle);
  display: flex;
  flex-wrap: wrap;
  gap: var(--block-space);
  justify-content: space-between;
  margin-block-start: 3rem;
  padding-block-start: var(--block-space-double);

  /* btn--large's 2em horizontal padding makes the toggle overrun the narrow
     44rem lesson column when its label is long ("Отметить пройденным"),
     orphaning it on its own wrapped row while the shorter "Урок пройден"
     state still fits. Trim the footprint so both states sit on one line. */
  .btn--large {
    --btn-padding: 0.65em 1.3em;
    font-size: 1em;
  }

  .btn .icon {
    block-size: 1.1rem;
    inline-size: 1.1rem;
  }
}

/* Marking done swaps in a fresh "completed" button (Turbo Stream replace). On
   its own that snaps grey→green; @starting-style (below) gives it a starting
   look identical to the grey "to-do" button, and this slower-than-default
   transition glides it to green — a deliberate state change, not a snap.
   min-inline-size pins both labels («Отметить пройденным» / «Урок пройден»)
   to one footprint, so the swap never reflows the row — only colour moves. */
.lesson-complete__toggle {
  min-inline-size: 15.6em;
  transition-duration: 320ms;
  transition-timing-function: ease-out;
}

@media (prefers-reduced-motion: no-preference) {
  /* The completed button's first frame mimics the grey reversed button, so the
     .btn colour transition has somewhere to travel FROM. Only fires because the
     element is freshly inserted (a morph would keep the node and skip this). */
  @starting-style {
    .lesson-complete__toggle.btn--positive {
      background-color: var(--color-ink);
      border-color: var(--color-ink);
      color: var(--color-bg);
    }
  }
}

/* The earned check "pops" once — but only when the lesson was just marked done
   (the Turbo Stream passes popped: true). Page loads of an already-done lesson
   carry no --pop class, so the reward never gets stale. */
.lesson-complete__check {
  align-items: center;
  display: inline-flex;
}

@media (prefers-reduced-motion: no-preference) {
  .lesson-complete__check--pop {
    animation: pop 450ms ease-in-out both;
  }
}

/* A quiet invitation, never a wall — a guest who won't register still owns the
   page. The line is muted; the actions read as links by WEIGHT + BRIGHTNESS,
   not by the loud --color-link blue or a permanent underline (both fought the
   real action, the "next" button, and cluttered the sentence). Ink + 600 is an
   unmistakable but calm signal; the underline only confirms on hover. */
.lesson-complete__signin {
  color: var(--color-subtle-dark);
  font-size: 0.9rem;
  line-height: 1.5;
  margin-block: 0;
  max-inline-size: 26rem;

  a {
    color: var(--color-ink);
    font-weight: 600;
    text-decoration: none;
    text-underline-offset: 0.15em;

    @media (any-hover: hover) {
      &:hover {
        text-decoration: underline;
      }
    }
  }
}

/* "Next" is the guest's real action, so it's pinned to the right — under the
   right thumb on a phone, and it stays there even when the invitation above it
   wraps to its own row (margin-auto beats the base space-between). */
.lesson-complete__side {
  align-items: center;
  display: flex;
  flex-wrap: wrap;
  gap: var(--block-space);
  margin-inline-start: auto;
}

/* Narrow screens, signed in: the two large buttons ("Урок пройден" + "Следующий")
   can't share a row without wrapping into an ugly diagonal stagger. Stack them
   full-width instead — the reader's two actions, big and thumb-friendly, read
   top→bottom in the order they're used. Scoped to :has(toggle) so the guest's
   text + single right-aligned button keeps its own (already clean) layout. */
@media (max-width: 40rem) {
  .lesson-complete:has(.lesson-complete__toggle) {
    align-items: stretch;
    flex-direction: column;
    gap: 0.75rem;
  }

  .lesson-complete:has(.lesson-complete__toggle) .lesson-complete__side {
    margin-inline-start: 0;
  }

  .lesson-complete:has(.lesson-complete__toggle)
    :is(.lesson-complete__form, .lesson-complete__side,
        .lesson-complete__toggle, .lesson-complete__next) {
    inline-size: 100%;
  }
}

/* Renders only when someone real stands behind the material (curators +
   accepted contributors). */
.lesson-attribution {
  color: var(--color-subtle-dark);
  display: flex;
  flex-wrap: wrap;
  font-size: 0.8rem;
  gap: 0.35rem 1.5rem;
  margin-block: 2.5rem 0;
}

/* ── "Посчитать по этой теме" ────────────────────────────────────────
   Calculators for the lesson's topic, derived from the calculator registry
   rather than written into the text. Deliberately lighter than the resource
   panel next to it: reading material is the lesson's substance, the tool is
   an offer — so this is a list of rows, not a second heavy card. */
.lesson-calculators {
  border-block-start: 1px solid var(--color-subtle);
  padding-block-start: 1.25rem;
}

.lesson-calculators__title {
  align-items: center;
  color: var(--color-subtle-dark);
  display: flex;
  font-size: 0.8rem;
  gap: 0.5em;
  letter-spacing: 0.06em;
  margin-block: 0 var(--block-space-half);
  text-transform: uppercase;

  .icon {
    block-size: 1.1rem;
    inline-size: 1.1rem;
  }
}

.lesson-calculators__list {
  display: grid;
  list-style: none;
  margin: 0;
  padding: 0;
}

.lesson-calculator {
  align-items: center;
  border-block-end: 1px solid var(--color-subtle);
  color: var(--color-ink);
  display: flex;
  gap: var(--block-space);
  padding-block: 0.8rem;

  .icon {
    block-size: 1rem;
    color: var(--color-subtle);
    flex-shrink: 0;
    inline-size: 1rem;
    transition: color 150ms ease-out, transform 150ms ease-out;
  }

  &:hover .icon {
    color: var(--color-ink);
    transform: translateX(0.2rem);
  }
}

.lesson-calculators__list li:last-child .lesson-calculator {
  border-block-end: 0;
  padding-block-end: 0;
}

.lesson-calculator__text {
  flex: 1;
  min-inline-size: 0;
}

.lesson-calculator__title {
  display: block;
  font-weight: 600;
  line-height: 1.3;
}

.lesson-calculator__desc {
  color: var(--color-subtle-dark);
  display: block;
  font-size: 0.9rem;
  margin-block-start: 0.15rem;
}
