/* road.css — the road grammar as classes (spec: _specs/course-path.md §7, direction آ «خطِ حاشیه»).
 *
 * WHAT. The margin rule IS the road. Every row draws its OWN 1.5px segment at the container's
 * inline-start 16px — solid --line-gold through done/current rows, dashed --line-disabled from the
 * frontier down — so the solid→dashed break falls out of each row's state instead of being measured
 * by hand. Visual truth: plans/single-path-previews/Margin*.dc.html.
 *
 * WHY a thin residual and not components.css. components.css + tokens.css are FROZEN canonical
 * files (design registry v2.2.0). Nothing here redefines a component; every value resolves through
 * a tokens.css var — there is no literal hex, no shadow, no gradient in this file by construction.
 *
 * GEOMETRY. One number drives the whole grammar: --road-rule-off, the rule's offset from a row's
 * own inline-start edge. The ✓ mark and the hollow tick derive from it (−6px / −4px), and so does
 * the door's negative pull, so a nested context (the slip) only re-declares that ONE property.
 * The road's own padding-inline-start (34px) + the offset (−18px) put the rule at exactly 16px —
 * the same 16px .margin-rule uses, which is why a page carrying both must hide one (see below).
 *
 * THE ONE MOTION. .road__door slides down the rule into place over --dur-slow; nothing else moves.
 * prefers-reduced-motion cuts it. No keyframes, no loop, no auto-play.
 */

/* ── the container ─────────────────────────────────────────────────────────── */
.road{
  --road-rule-off: -18px;                                   /* rule at 34 − 18 = 16px */
  --road-tick-off: calc(var(--road-rule-off) - 4px);        /* the 10px hollow tick crosses the rule */
  --road-mark-off: calc(var(--road-rule-off) - 6px);        /* the 14px ✓ centres on the rule */
  --road-lift: -56px;                                       /* the door's slide-in start offset */
  direction: rtl;
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding-inline-start: 34px;
  padding-inline-end: 22px;
  max-inline-size: 100%;
  box-sizing: border-box;
}

/* The page chrome (.margin-rule, components.css) draws the SAME rule at the same 16px. When a road
   lives inside it they would double-draw at 1.5px + 1.5px — the road owns the rule, so the chrome's
   is hidden. Two rules, never one selector list: an unsupported :has() would invalidate the whole
   list and leave the double-draw in place on exactly the old browsers this system still serves. */
.margin-rule.has-road::before{ display: none; }
@supports selector(:has(*)){
  .margin-rule:has(.road)::before{ display: none; }
}

/* ── a row + its rule segment ──────────────────────────────────────────────── */
.road__row{
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  min-height: 44px;
  min-inline-size: 0;
}
.road__row::before{
  content: "";
  position: absolute;
  inset-block: 0;
  inset-inline-start: var(--road-rule-off);
  inline-size: 1.5px;
  background: var(--line-gold);
  pointer-events: none;
}
/* below the frontier the rule goes dashed — zero-width box + a dashed inline-start border, so the
   dash phase is the browser's and never a hand-drawn repeat */
.road__row.is-locked::before,
.road__tail::before{
  inline-size: 0;
  background: none;
  border-inline-start: 1.5px dashed var(--line-disabled);
}
/* a two-line row (label + unlock line) stacks; the mark still centres on the row */
.road__row--stack{
  flex-direction: column;
  align-items: stretch;
  justify-content: center;
  gap: 2px;
  min-height: 50px;
}
.road__row--wide{ justify-content: space-between; }
/* the inner line of a STACKED row: ordinal + label together at the inline-start, minutes pushed to
   the inline-end by .road__minutes' auto margin. A locked row must read exactly like a done row —
   never --wide here, whose space-between tears the ordinal off its label. */
.road__line{
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  inline-size: 100%;
  min-inline-size: 0;
}
.road__line--wide{ justify-content: space-between; }
/* A short lesson identifier must not split into letters when its neighboring title wraps. */
.road__line--wide > a.road__label{
  flex: 0 0 auto;
  white-space: nowrap;
}

.road__row.is-current{ font-weight: 600; }
.road__row.is-locked{ cursor: default; }

/* the dashed tail that carries the rule to the foot of the screen */
.road__tail{
  position: relative;
  flex: 1 1 auto;
  min-height: var(--sp-2);
}
.road__tail::before{
  content: "";
  position: absolute;
  inset-block: 0;
  inset-inline-start: var(--road-rule-off);
  pointer-events: none;
}

/* ── the marks on the rule ─────────────────────────────────────────────────── */
.road__mark{
  position: absolute;
  inset-inline-start: var(--road-mark-off);
  inset-block-start: 50%;
  inline-size: 14px;
  block-size: 14px;
  transform: translateY(-50%);
  color: var(--mark-check-stroke);
  pointer-events: none;
}
/* strand header: a 10px ink dash, not a tick — it marks a section, not a completion */
.road__mark--strand{
  inset-inline-start: var(--road-tick-off);
  inline-size: 10px;
  block-size: 0;
  border-block-start: 2.2px solid var(--ink);
}
/* locked: a hollow 10px tick, no icon, no lock glyph */
.road__mark--locked{
  inset-inline-start: var(--road-tick-off);
  inline-size: 10px;
  block-size: 0;
  border-block-start: 1.5px solid var(--line-disabled);
}
/* waived = grandfathered: the ✓ is there but it never claims anything */
.road__row.is-waived .road__mark{ color: var(--ink-meta-deco); }

/* ── the row's parts ───────────────────────────────────────────────────────── */
.road__ordinal{
  flex: 0 0 auto;
  font-size: var(--fs-meta);
  line-height: var(--lh-heading);
  color: var(--ink-meta);
}
.road__label{
  min-inline-size: 0;
  overflow-wrap: anywhere;
  font-size: var(--fs-body);
  line-height: var(--lh-heading);
  font-weight: 500;
  color: var(--ink-soft);
}
.road__row.is-current .road__label{ color: var(--ink); font-weight: 600; }
.road__minutes{
  margin-inline-start: auto;                                /* the left end of an RTL row */
  flex: 0 0 auto;
  font-size: var(--fs-meta);
  line-height: var(--lh-heading);
  color: var(--ink-meta);
}
.road__unlock{
  font-size: var(--fs-meta);
  line-height: var(--lh-heading);
  color: var(--ink-meta);
}
/* the drip-locked frontier's quiet companion line — the tools are still open */
.road__aside{
  font-size: var(--fs-meta);
  line-height: var(--lh-body);
  color: var(--ink-meta);
}
.road__en{ font-size: var(--fs-meta); line-height: var(--lh-heading); color: var(--ink-meta); }
.road__en{ min-inline-size: 0; overflow-wrap: anywhere; }
.road__label[href],
a.road__unlock{
  display: flex;
  align-items: center;
  min-block-size: 44px;
}
.road__label[href]:focus-visible,
a.road__unlock:focus-visible{
  outline: 2px solid var(--ink);
  outline-offset: 2px;
}

/* ── strand rows ───────────────────────────────────────────────────────────── */
.road__strand{
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  min-height: 44px;
  min-inline-size: 0;
}
.road__strand::before{
  content: "";
  position: absolute;
  inset-block: 0;
  inset-inline-start: var(--road-rule-off);
  inline-size: 1.5px;
  background: var(--line-gold);
  pointer-events: none;
}
.road__strand.is-locked::before{
  inline-size: 0;
  background: none;
  border-inline-start: 1.5px dashed var(--line-disabled);
}
/* the eyebrow variant: a section header inside the slip and on the map */
.road__strand--head{
  min-height: 24px;
  font-size: var(--fs-meta);
  line-height: var(--lh-body);
  font-weight: 600;
  color: var(--ink-meta);
}

/* ── the current strand, expanded as a slip ────────────────────────────────── */
.road__slip{
  /* border 1.5 + padding 12 = 13.5 inset, so the rows inside pull 31.5px back to the same 16px */
  --road-rule-off: -31.5px;
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--sp-1);
  padding: var(--sp-3);
  min-inline-size: 0;
  max-inline-size: 100%;
  box-sizing: border-box;
  background: var(--slip);
  border: 1.5px solid var(--ink);
  border-radius: var(--r-row);
}
.road__slip .road__row::before,
.road__slip .road__strand::before{ background: var(--line-gold); }

/* ── the door: the one highlighter on the screen ───────────────────────────── */
.road__door{
  position: relative;
  z-index: var(--z-raised);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-2);
  margin-inline-start: var(--road-rule-off);                /* its edge lands ON the rule */
  min-height: 56px;
  padding-inline: var(--sp-4);
  background: var(--highlighter);
  border: 1.5px solid var(--ink);
  border-radius: var(--r-surface);
  color: var(--on-highlighter);
  font-family: inherit;
  font-size: var(--fs-body);
  line-height: var(--lh-heading);
  font-weight: 700;
  text-align: start;
  text-decoration: none;
  cursor: pointer;
  transition: transform var(--dur-slow) var(--ease);
  min-inline-size: 0;
  box-sizing: border-box;
}
.road__door:focus-visible{ outline: 2px solid var(--ink); outline-offset: 2px; }
.road__door:active{ opacity: .82; }
.road__door__lead{ display: flex; align-items: center; gap: var(--sp-2); flex: 1 1 auto; min-inline-size: 0; overflow-wrap: anywhere; }
.road__door__ord{ font-size: var(--fs-meta); font-weight: 600; }
.road__door__min{ flex: 0 0 auto; font-size: var(--fs-meta); font-weight: 600; }
/* THE ONE MOTION — the door slides down the rule from the finished node to the next one.
   road.js sets .is-lifted, forces a reflow, removes it; the transition above carries it home. */
.road__door.is-lifted{ transform: translateY(var(--road-lift)); transition: none; }

/* ── the handoff's own parts ───────────────────────────────────────────────── */
.road__result{
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 2px;
  min-height: 70px;
}
.road__result::before{
  content: "";
  position: absolute;
  inset-block: 0;
  inset-inline-start: var(--road-rule-off);
  inline-size: 1.5px;
  background: var(--line-gold);
  pointer-events: none;
}
.road__result__t{
  font-family: var(--font-display);
  font-size: var(--fs-h3);
  line-height: var(--lh-heading);
  font-weight: 700;
  color: var(--ink);
}
.road__result__d{
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  color: var(--ink-soft);
}
.road__next{
  position: relative;
  display: flex;
  align-items: center;
  min-height: 24px;
  font-size: var(--fs-meta);
  line-height: var(--lh-body);
  color: var(--ink-meta);
}
.road__next::before{
  content: "";
  position: absolute;
  inset-block: 0;
  inset-inline-start: var(--road-rule-off);
  inline-size: 1.5px;
  background: var(--line-gold);
  pointer-events: none;
}
.road__pause{
  display: flex;
  align-items: center;
  min-height: 44px;
  background: none;
  border: 0;
  padding: 0;
  font-family: inherit;
  font-size: var(--fs-body);
  line-height: var(--lh-heading);
  font-weight: 500;
  color: var(--ink);
  text-decoration: none;
  cursor: pointer;
}
.road__pause:focus-visible{ outline: 2px solid var(--ink); outline-offset: 2px; }

/* ── course scale ──────────────────────────────────────────────────────────── */
/* the chapter marker sits ON the rule and carries no segment of its own — it is a caption for the
   stretch below it, not a stop on the road */
.road__chapter{
  display: flex;
  align-items: center;
  min-height: 28px;
  font-size: var(--fs-meta);
  line-height: var(--lh-heading);
  font-weight: 600;
  color: var(--ink-meta);
}
/* Pre-IELTS keeps the long road fully discoverable without rendering six open chapters on entry.
   Native disclosure supplies the state semantics; this is only the quiet 44px touch treatment. */
.road__chapter-group{
  min-inline-size: 0;
  max-inline-size: 100%;
}
.road__chapter-group__summary{
  /* Keep summary's native list-item display: it supplies the disclosure marker without an extra
     icon, while the minimum block size keeps the real summary control comfortably tappable. */
  display: list-item;
  min-block-size: 44px;
  cursor: pointer;
  color: var(--ink);
}
/* Keep the native marker and chapter label on one line without hiding the disclosure cue. */
.road__chapter-group__summary .road__chapter{
  display: inline-flex;
  vertical-align: middle;
  min-block-size: 44px;
}
.road__chapter-group__summary:focus-visible,
.road__map-toggle:focus-visible{
  outline: 2px solid var(--ink);
  outline-offset: 2px;
}
.road__chapter-group__body{
  display: flex;
  flex-direction: column;
  gap: var(--sp-1);
  min-inline-size: 0;
}
.road__map-toggle{
  align-self: flex-start;
  display: flex;
  align-items: center;
  min-block-size: 44px;
  padding-inline: var(--sp-2);
  background: none;
  border: 1.5px solid var(--paper-rule);
  border-radius: var(--r-control);
  color: var(--ink-meta);
  font-family: inherit;
  font-size: var(--fs-meta);
  line-height: var(--lh-heading);
  font-weight: 600;
  cursor: pointer;
}
/* RoadCard keeps its existing bookmark shell. Astra's integration gives only its open learning
   action this existing door class; unavailable retry and every non-learning action stay slip-quiet. */
.neshanak .road__door{
  margin-inline-start: 0;
  inline-size: 100%;
}

/* ── the lesson title block ────────────────────────────────────────────────── */
.road__title{
  display: flex;
  flex-direction: column;
  gap: var(--sp-1);
  padding-block-end: var(--sp-3);
}
.road__title__row{ display: flex; align-items: baseline; justify-content: space-between; gap: var(--sp-2); min-inline-size: 0; }
.road__title__h{
  font-family: var(--font-display);
  font-size: var(--fs-h2);
  line-height: var(--lh-heading);
  font-weight: 700;
  color: var(--ink);
  min-inline-size: 0;
  overflow-wrap: anywhere;
}
.road__title__prog{ font-size: var(--fs-meta); line-height: var(--lh-heading); color: var(--ink-meta); }
.road__title__sub{ font-size: var(--fs-body); line-height: var(--lh-heading); color: var(--ink-soft); }

/* ── the lesson map: the same grammar, compressed, orientation only ────────── */
.road-map{ gap: var(--sp-1); }
/* the map's rows stay at the 44px tap floor: they are tappable (locked_tap) and the map scrolls,
   so density is never worth dropping below the minimum target size. */
.road-map .road__row{ min-height: 44px; }
.road-map .road__strand--head{ min-height: 20px; }
.road-map .road__title{ padding-block-end: var(--sp-2); }

/* ── the tools bar: a place, never a next step ─────────────────────────────── */
.toolsbar{
  position: fixed;
  inset-inline: 0;
  inset-block-end: 0;
  z-index: var(--z-chrome);
  display: flex;
  align-items: stretch;
  min-height: 64px;
  background: var(--slip);
  border-block-start: 1.5px solid var(--paper-rule);
  padding-block-end: env(safe-area-inset-bottom, 0px);
}
.toolsbar--static{ position: static; }
.toolsbar__item{
  flex: 1 1 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--sp-1);
  min-height: 44px;
  color: var(--ink);
  font-size: var(--fs-meta);
  line-height: var(--lh-heading);
  font-weight: 600;
  text-decoration: none;
}
.toolsbar__item:focus-visible{ outline: 2px solid var(--ink); outline-offset: -2px; }
.toolsbar__item svg{ inline-size: 20px; block-size: 20px; }
/* the road must end ABOVE the bar, not under it */
.has-toolsbar{ padding-block-end: calc(64px + env(safe-area-inset-bottom, 0px)); }

/* ── the one-time notice ───────────────────────────────────────────────────── */
.road-notice{
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
  padding: var(--sp-5);
  background: var(--slip);
  border: 1.5px solid var(--ink);
  border-radius: var(--r-surface);
}
.road-notice__t{
  font-family: var(--font-display);
  font-size: var(--fs-h3);
  line-height: var(--lh-heading);
  font-weight: 700;
  color: var(--ink);
}
.road-notice__b{
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  color: var(--ink-soft);
}
/* slip-style button, NOT the highlighter — the notice is not a next step */
.road-notice__ok{
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 56px;
  background: var(--slip);
  border: 1.5px solid var(--ink);
  border-radius: var(--r-surface);
  font-family: inherit;
  font-size: var(--fs-body);
  line-height: var(--lh-heading);
  font-weight: 700;
  color: var(--ink);
  cursor: pointer;
}
.road-notice__ok:focus-visible{ outline: 2px solid var(--ink); outline-offset: 2px; }

/* ── the remedial stop ─────────────────────────────────────────────────────── */
.road-remedial{
  direction: rtl;
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
}
.road-remedial__k{ font-size: var(--fs-meta); line-height: var(--lh-heading); color: var(--ink-meta); }
.road-remedial__h{
  font-family: var(--font-display);
  font-size: var(--fs-h3);
  line-height: var(--lh-heading);
  font-weight: 700;
  color: var(--ink);
}
.road-remedial__p{
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  color: var(--ink-soft);
}
.road-remedial__sum{ display: flex; flex-direction: column; gap: var(--sp-2); padding-block-start: var(--sp-2); }
.road-remedial__rule{
  block-size: 0;
  border-block-start: 1.5px solid var(--line-gold);
  margin-block-start: var(--sp-4);
}
/* the item host — the player's own item chrome mounts INSIDE this; nothing here restyles an item */
.road-remedial__host{
  margin-block-start: var(--sp-4);
  padding: var(--sp-4);
  background: var(--slip);
  border: 1.5px solid var(--ink);
  border-radius: var(--r-row);
}
.road-remedial__count{ font-size: var(--fs-meta); line-height: var(--lh-heading); color: var(--ink-meta); }
.road-remedial__go{
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 56px;
  margin-block-start: var(--sp-5);
  background: var(--highlighter);
  border: 1.5px solid var(--ink);
  border-radius: var(--r-surface);
  font-family: inherit;
  font-size: var(--fs-body);
  line-height: var(--lh-heading);
  font-weight: 700;
  color: var(--on-highlighter);
  cursor: pointer;
}
.road-remedial__go:focus-visible{ outline: 2px solid var(--ink); outline-offset: 2px; }

/* ── reduced motion: the one motion is the first thing to go ───────────────── */
/* Keep keyboard destinations clear of the fixed course tools. */
.has-toolsbar .road :focus,
.has-toolsbar .neshanak :focus{
  scroll-margin-block-end: calc(80px + env(safe-area-inset-bottom, 0px));
  scroll-margin-block-start: var(--sp-4);
}

@media (prefers-reduced-motion: reduce){
  html{ scroll-behavior: auto; }
  .road__door,
  .road__map-toggle{ transition: none; }
  .road__door.is-lifted{ transform: none; }
}
