/* ==========================================================================
   RABBANI — learning surfaces
   The path, the lesson reader and the review queue.
   Scholarly progression, not a game map: no avatars, no bouncing nodes, no
   cartoon trail. State is carried by shape, weight and a written label — never
   by colour alone.
   ========================================================================== */

/* ---- Back link ----------------------------------------------------------- */
.learn-back { margin-block-end: var(--s-6); }

/* ---- Legend -------------------------------------------------------------- */
.learn-legend {
  display: flex; flex-wrap: wrap; gap: var(--s-4);
  margin-block-end: var(--s-6); font-size: var(--fs-caption); color: var(--ink-400);
}
.learn-legend > span { display: inline-flex; align-items: center; gap: var(--s-2); }
.learn-dot { inline-size: 10px; block-size: 10px; border-radius: 50%; background: var(--line); }
.learn-dot.mastered { background: var(--green-600); }
.learn-dot.available { background: var(--info); }
.learn-dot.locked { background: var(--locked); }
.learn-dot.checkpoint { background: var(--gold-500); }

/* ---- The path ------------------------------------------------------------ */
.learn-path {
  list-style: none; margin: 0; padding: 0;
  position: relative; padding-inline-start: var(--s-10);
}
/* The spine sits behind the markers. In RTL, inline-start is the right edge. */
.learn-path::before {
  content: ''; position: absolute; inset-block: 20px 20px;
  inset-inline-start: 15px; inline-size: 2px;
  background: linear-gradient(var(--green-100), var(--line-hair));
}

.learn-node { position: relative; margin-block-end: var(--s-3); }

.learn-node-link {
  display: flex; align-items: flex-start; gap: var(--s-4);
  padding: var(--s-4) var(--s-5);
  background: var(--surface-raised); border: 1px solid var(--line-hair);
  border-radius: var(--r-lg); text-decoration: none; color: inherit;
  transition: border-color var(--t-fast), box-shadow var(--t-fast), transform var(--t-fast);
}
a.learn-node-link:hover { border-color: var(--line); box-shadow: var(--e-2); transform: translateY(-1px); }

/* The marker straddles the spine. */
.learn-node-badge {
  position: absolute; inset-inline-start: calc(-1 * var(--s-10) + 6px); inset-block-start: var(--s-5);
  inline-size: 22px; block-size: 22px; border-radius: 50%;
  display: grid; place-items: center; flex-shrink: 0;
  font-size: var(--fs-micro); font-weight: var(--fw-bold); font-variant-numeric: tabular-nums;
  background: var(--surface); border: 2px solid var(--line); color: var(--ink-400);
}
.learn-node-badge.mastered { background: var(--green-600); border-color: var(--green-600); color: var(--ink-on-dark); }
.learn-node-badge.current,
.learn-node-badge.partial { background: var(--gold-500); border-color: var(--gold-500); color: var(--green-900); box-shadow: 0 0 0 4px var(--gold-100); }
.learn-node-badge.available { background: var(--surface); border-color: var(--green-500); color: var(--green-700); }
.learn-node-badge.locked { background: var(--surface-sunken); border-color: var(--line); color: var(--locked); }
.learn-node-badge.checkpoint { border-color: var(--gold-500); }

.learn-node-body { display: flex; flex-direction: column; gap: var(--s-1); min-inline-size: 0; }
.learn-node-title { font-weight: var(--fw-medium); color: var(--ink-900); font-size: var(--fs-body-lg); }
.learn-node-meta { font-size: var(--fs-caption); color: var(--ink-400); }
/* A locked node says WHY, using the reason the backend supplied. */
.learn-node-lock {
  display: inline-flex; align-items: center; gap: var(--s-2);
  margin-block-start: var(--s-2); padding: 3px var(--s-3);
  font-size: var(--fs-micro); border-radius: var(--r-pill);
  background: var(--locked-bg); color: var(--locked);
}

.learn-node.locked .learn-node-link { background: var(--surface-sunken); border-color: transparent; }
.learn-node.locked .learn-node-title { color: var(--ink-500); }
.learn-node.mastered .learn-node-title { color: var(--ink-700); }
.learn-node.is-checkpoint .learn-node-link { border-inline-start: 3px solid var(--gold-300); }

/* ---- Discipline grid (learn home) ---------------------------------------- */
.learn-science-grid {
  display: grid; gap: var(--s-4);
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 200px), 1fr));
}
.learn-science-card {
  display: flex; flex-direction: column; gap: var(--s-2);
  padding: var(--s-5); text-decoration: none; color: inherit;
  background: var(--surface-raised); border: 1px solid var(--line-hair);
  border-radius: var(--r-lg);
  transition: border-color var(--t-fast), box-shadow var(--t-fast), transform var(--t-fast);
}
.learn-science-card:hover { border-color: var(--line); box-shadow: var(--e-2); transform: translateY(-1px); }
.learn-science-title { font-family: var(--font-display); font-size: var(--fs-h3); color: var(--ink-900); }
.learn-science-sub { font-size: var(--fs-caption); color: var(--ink-400); }
.learn-group { margin-block-end: var(--s-8); }
.learn-group > h2 { font-size: var(--fs-h3); font-family: var(--font-body); margin-block-end: var(--s-4); }

/* ---- Statistics row ------------------------------------------------------
   The four standing figures, read at a glance. Grid rather than flex so the
   cells divide the width evenly: a "3" and an "89" should not produce cells of
   different sizes. Hairline rules between cells instead of gaps — at this size
   a separator reads as one instrument, where floating columns read as debris.

   The previous rules here were dead: the markup emitted .learn-snapshot while
   the stylesheet defined .learn-snap, so the items fell back to plain blocks
   and stacked vertically down the card. */
.stat-row {
  display: grid;
  grid-template-columns: repeat(var(--stat-cols, 4), 1fr);
  border: 1px solid var(--line-hair);
  border-radius: var(--radius-lg);
  background: var(--surface-raised);
  overflow: hidden;
  margin-block-end: var(--s-6);
}
.stat-cell {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--s-1);
  padding-block: var(--s-5);
  padding-inline: var(--s-3);
  border-inline-start: 1px solid var(--line-hair);
  min-inline-size: 0;
  text-align: center;
}
.stat-cell:first-child { border-inline-start: 0; }
.stat-num {
  font-family: var(--font-display);
  font-size: clamp(1.5rem, 1.1rem + 1.1vw, 1.9rem);
  font-weight: var(--fw-bold);
  color: var(--green-800);
  line-height: 1;
}
.stat-label {
  font-size: var(--fs-caption);
  color: var(--ink-400);
  line-height: 1.3;
}

/* Four Arabic labels across a phone become unreadable slivers; two rows of two
   keep every label on one line. The border resets follow the 2-column grid so
   no cell carries a rule against the card edge. */
@media (max-width: 640px) {
  .stat-row { grid-template-columns: repeat(min(var(--stat-cols, 4), 2), 1fr); }
  .stat-cell:nth-child(odd) { border-inline-start: 0; }
  .stat-cell:nth-child(-n+2) { border-block-end: 1px solid var(--line-hair); }
  /* A three-cell row pairs then leaves one alone; that last cell owns the
     whole width and must not draw a rule against the card edge. */
  .stat-row:not([style*="--stat-cols: 2"]) .stat-cell:last-child:nth-child(odd) {
    grid-column: 1 / -1; border-block-end: 0;
  }
}

/* ---- Lesson reader -------------------------------------------------------
   Reading first. Chrome recedes; the measure is set by ch, not by viewport. */
.learn-prose {
  font-size: var(--fs-body-lg); line-height: var(--lh-reading);
  color: var(--ink-700); max-inline-size: var(--reading-max);
}
.learn-prompt { font-family: var(--font-display); font-size: 1.2rem; color: var(--ink-900); }
.learn-step { margin-block-end: var(--s-6); }
.learn-muted { color: var(--ink-400); font-size: var(--fs-caption); }
.learn-cta { margin-block-start: var(--s-4); }

.learn-controls {
  display: flex; justify-content: space-between; gap: var(--s-4);
  margin-block-start: var(--s-8); padding-block-start: var(--s-6);
  border-block-start: 1px solid var(--line-hair);
}

/* ---- Level exams --------------------------------------------------------- */
.learn-level-exams {
  display: grid;
  gap: var(--s-3);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 240px), 1fr));
  margin-block-start: var(--s-4);
}
.learn-level-exam {
  display: flex;
  flex-direction: column;
  gap: var(--s-1);
  min-inline-size: 0;
  padding: var(--s-4) var(--s-5);
  border: 1px solid var(--line-hair);
  border-radius: var(--r-lg);
  background: var(--surface-raised);
  color: inherit;
  text-decoration: none;
}
a.learn-level-exam:hover {
  border-color: var(--green-500);
  box-shadow: var(--e-1);
}
.learn-level-exam.is-available,
.learn-level-exam.is-in_progress { border-inline-start: 3px solid var(--gold-400); }
.learn-level-exam.is-passed { border-inline-start: 3px solid var(--green-600); }
.learn-level-exam.is-locked {
  background: var(--surface-sunken);
  color: var(--ink-400);
}
.learn-level-exam-title { font-weight: var(--fw-bold); color: var(--ink-900); }
.learn-level-exam-meta,
.learn-level-exam-reason { font-size: var(--fs-caption); color: var(--ink-400); }
.learn-level-exam-action {
  margin-block-start: var(--s-2);
  font-size: var(--fs-caption);
  font-weight: var(--fw-bold);
  color: var(--green-700);
}

/* ---- Assessment options -------------------------------------------------- */
/*
   Answer choices inherit .btn's one-line treatment by default. Learner answers
   are prose-like content, not toolbar actions: they must wrap inside the card
   at narrow widths and browser zoom without widening the page. overflow-wrap
   "anywhere" is deliberate because authored options can contain long references
   or unbroken tokens; unlike break-word, it also contributes wrap opportunities
   to min-content sizing and prevents the flex item from forcing overflow.
*/
.learn-opt {
  inline-size: 100%;
  max-inline-size: 100%;
  min-inline-size: 0;
  min-block-size: 44px;
  block-size: auto;
  justify-content: flex-start;
  align-items: flex-start;
  text-align: start;
  white-space: normal;
  overflow-wrap: anywhere;
  word-break: normal;
  line-height: 1.7;
  margin-block-end: var(--s-3);
  font-size: var(--fs-body);
  background: var(--surface-raised);
  border: 1px solid var(--line);
  color: var(--ink-700);
}
.learn-opt:hover:not(:disabled) { border-color: var(--green-500); background: var(--green-50); }
/* Verdicts carry a mark as well as a colour. Keep the mark as a non-shrinking
   flex item so wrapped answer text gets the available measure instead of
   pushing the verdict outside the card. */
.learn-opt::after { flex: 0 0 auto; align-self: flex-start; }
.learn-opt.correct { border-color: var(--ok); background: var(--ok-bg); color: var(--ok); font-weight: var(--fw-medium); }
.learn-opt.correct::after { content: ' ✓'; margin-inline-start: auto; }
.learn-opt.wrong { border-color: var(--danger); background: var(--danger-bg); color: var(--danger); }
.learn-opt.wrong::after { content: ' ✕'; margin-inline-start: auto; }
.learn-check-status { margin-block: var(--s-3); font-size: var(--fs-sm); color: var(--ink-500); }

.learn-finish { text-align: center; padding: var(--s-8); }
.learn-finish.pass h3 { color: var(--ok); }
.learn-finish.fail h3 { color: var(--warn); }

/* ---- Review queue -------------------------------------------------------- */
.learn-flash-host { display: block; }
.review-progress { margin-block-end: var(--s-5); }
.flash-card { padding: clamp(var(--s-6), 4vw, var(--s-10)); text-align: center; }
.flash-count { font-size: var(--fs-caption); color: var(--ink-400); margin-block-end: var(--s-5); }
.flash-front { font-family: var(--font-display); font-size: 1.45rem; line-height: 1.9; color: var(--ink-900); }
.flash-back {
  margin-block-start: var(--s-6); padding-block-start: var(--s-6);
  border-block-start: 1px solid var(--line-hair);
  font-size: var(--fs-body-lg); line-height: var(--lh-reading); color: var(--ink-700);
}
.flash-actions { margin-block-start: var(--s-6); display: flex; gap: var(--s-3); justify-content: center; flex-wrap: wrap; }

@media (max-width: 600px) {
  .learn-path { padding-inline-start: var(--s-8); }
  .learn-path::before { inset-inline-start: 11px; }
  .learn-node-badge { inset-inline-start: calc(-1 * var(--s-8) + 2px); }
  .learn-controls { flex-direction: column; }
  .learn-controls .btn { inline-size: 100%; }
}

/* ==========================================================================
   Lesson reader
   Reading is the product here. Chrome recedes; the measure is set in ch, the
   leading is looser than UI text, and nothing competes with the prose.
   ========================================================================== */
.reader { padding-block-start: var(--s-6); }

.reader-head { margin-block-end: var(--s-6); }
.reader-meta { display: flex; align-items: center; gap: var(--s-3); flex-wrap: wrap; margin-block-end: var(--s-3); }
.reader-head h1 {
  font-family: var(--font-display);
  font-size: clamp(1.6rem, 1.2rem + 1.6vw, 2.2rem);
  line-height: 1.5;
  color: var(--ink-900);
}

/* The reader's progress is information, not decoration: thin, quiet, and it
   does not move while you read. */
.reader .learn-progress-wrap,
.reader .progress { margin-block-end: var(--s-8); }

/* No card border around prose — a box around reading material adds nothing and
   narrows the measure. */
.reader-body { background: none; border: 0; padding: 0; }
.reader-body .learn-step h3 {
  font-family: var(--font-display); font-size: var(--fs-h3);
  color: var(--ink-900); margin-block-end: var(--s-4);
}
.reader-body .learn-prose { font-size: 1.0938rem; line-height: 2.1; }
.reader-body .learn-prose + .learn-prose { margin-block-start: var(--s-5); }

.reader-foot {
  display: flex; justify-content: space-between; align-items: center; gap: var(--s-4);
  margin-block-start: var(--s-10); padding-block-start: var(--s-5);
  border-block-start: 1px solid var(--line-hair);
}

@media (max-width: 600px) {
  .reader { padding-block-start: var(--s-3); }
  .reader-head h1 { font-size: 1.45rem; }
  /* Slightly tighter leading on a narrow column keeps lines from feeling loose. */
  .reader-body .learn-prose { font-size: 1.0625rem; line-height: 1.95; }
}

/* ---- Lesson progress ----------------------------------------------------
   Width comes from a class, not an inline style: the project's CSP forbids
   inline style attributes in renderers. */
.learn-progress-bar {
  block-size: 4px; inline-size: 100%;
  background: var(--surface-sunken); border-radius: var(--r-pill);
  overflow: hidden; margin-block-end: var(--s-8);
}
.learn-progress-fill {
  display: block; block-size: 100%; inline-size: 0;
  background: var(--green-600); border-radius: var(--r-pill);
  transition: inline-size var(--t-slow);
}
.learn-progress-fill.w0  { inline-size: 0; }
.learn-progress-fill.w1  { inline-size: 10%; }
.learn-progress-fill.w2  { inline-size: 20%; }
.learn-progress-fill.w3  { inline-size: 30%; }
.learn-progress-fill.w4  { inline-size: 40%; }
.learn-progress-fill.w5  { inline-size: 50%; }
.learn-progress-fill.w6  { inline-size: 60%; }
.learn-progress-fill.w7  { inline-size: 70%; }
.learn-progress-fill.w8  { inline-size: 80%; }
.learn-progress-fill.w9  { inline-size: 90%; }
.learn-progress-fill.w10 { inline-size: 100%; }

/* ---- The thirteen-level journey ------------------------------------------
   A cross-section of every discipline, so this reads as one continuous track
   rather than as cards: a numbered spine on the inline-start edge, each step
   joined to the next. Restraint is deliberate — no medals, no confetti; the
   states are carried by weight and a single muted accent. */
.level-track { list-style: none; margin: var(--s-5) 0 0; padding: 0; }
.level-step {
  display: flex;
  align-items: center;
  gap: var(--s-4);
  padding-block: var(--s-3);
  position: relative;
}
/* The spine: a hairline joining consecutive steps, stopping at the last. */
.level-step::before {
  content: '';
  position: absolute;
  inset-inline-start: calc(var(--s-7) / 2);
  inset-block-start: 50%;
  block-size: 100%;
  inline-size: 1px;
  background: var(--line-hair);
}
.level-step:last-child::before { display: none; }

.level-index {
  flex: 0 0 auto;
  inline-size: var(--s-7);
  block-size: var(--s-7);
  display: grid;
  place-items: center;
  border-radius: 50%;
  border: 1px solid var(--line);
  background: var(--surface-raised);
  color: var(--ink-500);
  font-size: var(--fs-caption);
  font-weight: var(--fw-bold);
  position: relative;
  z-index: 1;
}
.level-body { display: flex; flex-direction: column; gap: 2px; min-inline-size: 0; }
.level-name { font-weight: var(--fw-bold); color: var(--ink-900); }
.level-state { font-size: var(--fs-caption); color: var(--ink-400); }
.level-count { margin-inline-start: auto; font-size: var(--fs-caption); color: var(--ink-500); }

/* States. `unplaced` is the honest default while the curriculum is still
   assigning lessons to levels, and must not look like a reward or a penalty. */
.level-step.is-unplaced .level-index { opacity: 0.55; }
.level-step.is-unplaced .level-name { font-weight: var(--fw-regular); color: var(--ink-700); }
.level-step.is-completed .level-index {
  background: var(--brand-fill); border-color: var(--brand-fill); color: var(--brand-fill-ink);
}
.level-step.is-current .level-index {
  border-color: var(--green-800); border-width: 2px; color: var(--green-800);
}
.level-step.is-current .level-state { color: var(--green-800); font-weight: var(--fw-bold); }
.level-step.is-locked .level-index { opacity: 0.4; }
.level-step.is-locked .level-name { color: var(--ink-400); }

@media (max-width: 480px) {
  .level-count { display: none; }
}

/* ---- Authored-curriculum level/unit grouping on the map (additive; the
   DB-backed map never sets `groups` and never renders these) ------------- */
.learn-level-groups { display: flex; flex-direction: column; gap: var(--s-6); }
.learn-level-group-title { font-size: var(--fs-h3); margin-block-end: var(--s-3); }
.learn-unit-divider {
  list-style: none; font-size: var(--fs-caption); color: var(--ink-400);
  font-weight: 600; padding-inline-start: var(--s-10);
  margin-block: var(--s-4) var(--s-2);
}
.learn-unit-divider:first-child { margin-block-start: 0; }
