/* ═══════════════════════════════════════════════════════════════════════════
   fe-ds.css — the FreeEdu design system.

   SOURCE OF TRUTH: docs/free-taleem-new-design/assets/theme.css — the design
   system as a standalone stylesheet, which is where it now lives. It began as
   an inline block inside docs/free-taleem-new-design/index.html and the pages that consumed it moved
   into that folder with it; the class names and values did not change in the
   move, so everything already transposed here still matches rule for rule.

   Everything here is that stylesheet, transposed onto this app's
   conventions. It is the ONE visual language for every /fe page: Home, Azkar,
   Give, About, App, How-to-use, the Find flow, subject pages and chapter
   sheets all draw from it. A page that needs a look this file does not have
   should GAIN A RULE HERE, not a private copy in its own .razor.css — a
   scoped stylesheet duplicated into a second page is the one kind of
   duplication you cannot see from either copy.

   ── Why every selector is prefixed [data-fe-site] ───────────────────────────
   The mock names its classes unprefixed: .btn, .nav, .card, .stat, .status.
   This document is shared with the admin portal, whose design system
   (ds/styles.css) already defines .btn and the token --border-strong. Loading
   the mock's names globally would restyle every button in the portal and
   repaint its borders.

   App.razor stamps data-fe-site="1" on <html> for FreeEdu paths ONLY
   (FeRoutes.IsFreeEduPath) and omits the attribute entirely elsewhere, so it
   is an exact fence. Prefixing costs one attribute selector of specificity
   (0,1,1 vs the portal's 0,1,0), which is also the direction we want: on a
   FreeEdu page these rules win, on a portal page they do not exist.

   The token block is fenced the same way and for the same reason. The mock
   defines --border-strong, --surface-2 and --bg at :root; the portal's
   --border-strong is a different colour. Declaring them on
   html[data-fe-site] confines the whole palette to this site.

   ── Language ────────────────────────────────────────────────────────────────
   The mock switches Urdu typography on body.lang-ur, because it swaps text in
   place, never changes direction, and has exactly one language on screen at a
   time. None of those three hold here.

   Every one of its body.lang-ur rules is written X:lang(ur) below, NOT
   html[lang="ur"] X. The two are identical for a page whose content is all in
   the reader's own language — :lang(ur) resolves from <html lang>, which
   fe-lang-boot.js stamps before first paint — and they differ in exactly the
   case this library actually has:

     AN URDU-ONLY CHAPTER OPENED BY AN ENGLISH READER. Mutala-e-Quran-e-Hakeem
     ships with no English medium at all: its solution files carry a "ur" array
     and no "en" one. An English reader who opens one gets a page whose chrome
     is English and whose content is Urdu, and FeQuestionCard stamps lang="ur"
     on the card to say so. Keyed on the SITE language, every Urdu word in that
     card would be set in JetBrains Mono with .07em of letter-spacing — a joined
     script pulled apart, in a face that has no Nastaliq glyphs at all. Keyed on
     :lang(ur), the card's own attribute wins: the content sets correctly and
     the chrome around it stays English.

   THE ONE EXCEPTION IS A LABEL WHOSE TEXT IS CHROME. .answer .lbl reads
   "Answer" out of FeStrings, so it follows the reader's language even though it
   sits inside a content-language card; it stays keyed on html[lang="ur"] and
   carries a note saying why. That is the whole rule: content follows :lang(),
   chrome follows the site.
   ═══════════════════════════════════════════════════════════════════════════ */

html[data-fe-site] {
  --mint: #2ED4A5;
  --mint-deep: #1FA981;
  --navy: #0B0F1E;
  --purple: #A78BFA;
  --purple-deep: #7C5CE0;
  --coral: #FF6B6B;

  --accent: var(--mint);
  --accent-2: var(--purple);
  --negative: var(--coral);

  --bg: #F7F8FA;
  --surface: #FFFFFF;
  --surface-2: #EEF1F5;
  --surface-ink: #0B0F1E;
  --fg: #0B0F1E;
  --fg-on-ink: #E8EBF2;
  --muted: #5B6478;
  --muted-on-ink: #8B94A8;
  --border: rgba(11, 15, 30, .12);
  --border-strong: rgba(11, 15, 30, .22);
  --border-ink: rgba(255, 255, 255, .14);
  --rule: rgba(11, 15, 30, .07);
  --on-accent: #04231A;

  --r-sm: 6px;
  --r: 10px;
  --r-lg: 14px;
  --t: .12s ease;

  /* WHAT THE BROWSER PAINTS THAT THIS FILE CANNOT. Everything below the tokens is
     ours; the page scrollbar, the text caret, a search field's clear button, the
     focus ring on a native control and an autofilled input's background are the
     USER AGENT's, and it picks their colours from color-scheme alone. Undeclared,
     that is "light" — so a reader in dark mode got a near-black page with a pale
     grey scrollbar down the side of it and a dark-on-dark caret in the search box.

     The mock does not declare it either, and does not need to: it is one static
     page with no scrolling rail and no form fields. This app has /search, the
     reader rail's filter and the share page's link field, and a document that
     scrolls on every screen. Stated in both blocks rather than only in dark, so
     the light value is never inherited from whatever the portal's half of the
     document decided. */
  color-scheme: light;

  --max: 1160px;
  --step--1: clamp(.78rem, .75rem + .2vw, .86rem);
  --step-0: clamp(1rem, .96rem + .25vw, 1.06rem);
  --step-1: clamp(1.18rem, 1.1rem + .5vw, 1.38rem);
  --step-2: clamp(1.5rem, 1.3rem + 1vw, 2rem);
  --step-3: clamp(1.9rem, 1.55rem + 2.1vw, 2.95rem);
  --step-4: clamp(2.4rem, 1.85rem + 3.2vw, 4.05rem);
}

/* theme-boot.js stamps [data-theme] pre-paint. It supports "system", but
   resolves that to an explicit light/dark value before writing the attribute,
   so matching the attribute alone is enough — no prefers-color-scheme block. */
html[data-fe-site][data-theme="dark"] {
  --bg: #0B0F1E;
  --surface: #121829;
  --surface-2: #182036;
  --surface-ink: #060A15;
  --fg: #E8EBF2;
  --muted: #8B94A8;
  --border: rgba(255, 255, 255, .12);
  --border-strong: rgba(255, 255, 255, .2);
  --rule: rgba(255, 255, 255, .05);
  --on-accent: #04231A;

  /* The other half of the pair above: this is what turns the scrollbar, the caret
     and every native control dark along with the tokens. It is the ONE declaration
     here that is not a custom property, and it is here rather than in the base
     block because it has to follow the attribute, not the site. */
  color-scheme: dark;
}

[data-fe-site] *,
[data-fe-site] *::before,
[data-fe-site] *::after { box-sizing: border-box }

html[data-fe-site] { -webkit-text-size-adjust: 100%; scroll-behavior: smooth }

[data-fe-site] body {
  margin: 0; background: var(--bg); color: var(--fg);
  font-family: var(--font-sans); font-size: var(--step-0);
  line-height: 1.6; overflow-x: hidden;
  transition: background var(--t), color var(--t);
}
[data-fe-site] body.no-scroll { overflow: hidden }

@media (prefers-reduced-motion: reduce) {
  html[data-fe-site] { scroll-behavior: auto }
  [data-fe-site] *,
  [data-fe-site] *::before,
  [data-fe-site] *::after { animation-duration: .001ms !important; transition-duration: .001ms !important }
}

/* The ruled margin line. inset-inline-start, so it lands on the correct edge
   when the document flips to RTL for Urdu. */
[data-fe-site] body::before {
  content: ""; position: fixed; top: 0; bottom: 0; inset-inline-start: 52px;
  width: 1px; background: var(--accent); opacity: .22; z-index: 5; pointer-events: none;
}
@media (max-width: 960px) { [data-fe-site] body::before { display: none } }

[data-fe-site] h1,
[data-fe-site] h2,
[data-fe-site] h3,
[data-fe-site] .display {
  font-family: var(--font-display); font-weight: 600;
  letter-spacing: -.018em; line-height: 1.12; margin: 0;
  font-variation-settings: "SOFT" 0, "WONK" 0;
}
[data-fe-site] p { margin: 0 }

/* ── Neutralising the portal's element defaults ──────────────────────────────
   ds/styles.css loads on this document too, and its base.css styles BARE
   ELEMENTS at specificity (0,0,1): body, h1-h5, a, :focus-visible, ::selection.
   Fencing this file behind [data-fe-site] beats all of them, but only for the
   properties it actually restates — and the block above restates family, weight
   and line-height on headings and nothing else. Everything below is a property
   the old design was still setting on a FreeEdu page because nothing here had
   an opinion about it. This is the seam where the two systems were mixing.

   HEADINGS. base.css sets `color: var(--text-strong)` and then
   `h1 { font: var(--type-h1) }` — a SHORTHAND, so it carries font-size as well.
   Headings were therefore drawing the portal's ink and, wherever a heading was
   not inside .hero / .page-head / .head-row / .illum / .give / .q-section, the
   portal's size too. The design system sizes headings by context, exactly as
   the mock does, so these are the fallbacks for a heading that has none. */
[data-fe-site] h1 { color: var(--fg); font-size: var(--step-3) }
[data-fe-site] h2 { color: var(--fg); font-size: var(--step-2) }
[data-fe-site] h3 { color: var(--fg); font-size: var(--step-1) }
[data-fe-site] h4,
[data-fe-site] h5 { color: var(--fg); font-family: var(--font-display); letter-spacing: -.018em; margin: 0 }

/* LINKS. base.css underlines every anchor, tints it --text-link, transitions it
   and gives it a focus ring — all in the portal's mint, not this one. The mock
   sets `a { color: inherit }` and lets each component decide the rest, so the
   underline has to be removed here rather than fought component by component.
   Anchors that SHOULD be underlined say so themselves: .subj-dl, .link-btn and
   .give-card a.out-link each declare text-decoration with their own offset. */
[data-fe-site] a {
  color: inherit;
  text-decoration-line: none;
  text-decoration-color: currentColor;
  transition: color var(--t);
}
[data-fe-site] a:hover { color: inherit }

/* FOCUS. base.css draws its ring with box-shadow and the design system draws
   one with outline, so a focused control on a FreeEdu page was wearing BOTH —
   a mint outline inside the portal's shadow ring. box-shadow:none leaves the
   outline as the single focus indicator. */
[data-fe-site] :focus-visible { box-shadow: none }

[data-fe-site] ::selection { background: var(--accent); color: var(--on-accent) }

[data-fe-site] .mono { font-family: var(--font-mono); font-size: var(--step--1); letter-spacing: .08em; text-transform: uppercase }
[data-fe-site] .num { font-family: var(--font-mono); font-variant-numeric: tabular-nums }
[data-fe-site] .ar { font-family: var(--fe-font-arabic); direction: rtl; line-height: 1.9 }
[data-fe-site] .ur-text { font-family: var(--fe-font-urdu); direction: rtl; line-height: 2.5 }

/* Urdu. The mock keys these on body.lang-ur; this app carries the language on
   <html lang>, stamped before first paint by fe-lang-boot.js. */
[data-fe-site] body:lang(ur){ font-family: var(--fe-font-urdu); line-height: 2.4 }

/* THE SAME BASE FACE, ESTABLISHED ONE LEVEL DOWN — and this is the rule that actually
   carries Mutala-e-Quran-e-Hakeem to an English reader. The line above is what gives every
   ordinary element its Nastaliq: not a font rule per component, but one declaration on <body>
   that the whole document INHERITS. It can only ever fire when the SITE is Urdu, because
   <body> takes its language from <html>.

   An Urdu-only chapter opened on the English site is Urdu text under body[lang="en"], so all
   of it inherited var(--font-sans) — the rail's rows, the question text, the translation
   paragraphs, everything without a font rule of its own — and set a joined script in a face
   carrying no Nastaliq glyphs. The :lang(ur) rules below could not help: they style headings
   and .mono, never the inherited body copy.

   ChapterPage and SubjectPage declare the sheet's own chrome language on .fe-wrap
   (SheetLangCode), so this restates the base there. The subtree inherits Nastaliq exactly as
   it does on the Urdu site; the header and footer sit outside .fe-wrap and keep the face the
   reader actually chose. */
[data-fe-site] .fe-wrap:lang(ur){ font-family: var(--fe-font-urdu); line-height: 2.4 }
[data-fe-site] h1:lang(ur),
[data-fe-site] h2:lang(ur),
[data-fe-site] h3:lang(ur),
[data-fe-site] .display:lang(ur) { font-family: var(--fe-font-urdu); font-weight: 700; line-height: 1.9; letter-spacing: 0 }
[data-fe-site] .mono:lang(ur){ font-family: var(--fe-font-urdu); letter-spacing: 0; text-transform: none; font-size: .82rem }
[data-fe-site] .num:lang(ur){ font-family: var(--font-mono) }

[data-fe-site] .wrap { max-width: var(--max); margin-inline: auto; padding-inline: clamp(1.1rem, 4vw, 2.5rem) }
[data-fe-site] .section { padding-block: clamp(3.5rem, 7vw, 6.5rem) }
[data-fe-site] .ruled { background-image: repeating-linear-gradient(to bottom, transparent 0 35px, var(--rule) 35px 36px); background-position: 0 12px }
[data-fe-site] .ruled-soft { background-image: repeating-linear-gradient(to bottom, transparent 0 35px, var(--rule) 35px 36px) }

[data-fe-site] .eyebrow { display: flex; align-items: center; gap: .7rem; color: var(--accent); margin-bottom: 1.3rem; flex-wrap: wrap }
[data-fe-site] .eyebrow .dot { width: 4px; height: 4px; background: currentColor; border-radius: 50%; flex: none }
[data-fe-site] .lede { color: var(--muted); font-size: var(--step-1); max-width: 56ch }

/* Buttons — filled mint or hairline ghost, never a shadow. */
[data-fe-site] .btn {
  display: inline-flex; align-items: center; gap: .55rem; font-family: var(--font-sans); font-weight: 600; font-size: .98rem;
  padding: .8rem 1.4rem; border-radius: var(--r); border: 1px solid var(--accent); background: var(--accent); color: var(--on-accent);
  text-decoration: none; cursor: pointer; transition: background var(--t), border-color var(--t), color var(--t);
}
[data-fe-site] .btn:lang(ur){ font-family: var(--fe-font-urdu) }
[data-fe-site] .btn:hover { background: var(--mint-deep); border-color: var(--mint-deep) }
[data-fe-site] .btn--ghost { background: transparent; color: var(--fg); border-color: var(--border-strong) }
[data-fe-site] .btn--ghost:hover { background: transparent; border-color: var(--accent); color: var(--accent) }
[data-fe-site] .btn--alt { background: var(--accent-2); border-color: var(--accent-2); color: #14082E }
[data-fe-site] .btn--alt:hover { background: var(--purple-deep); border-color: var(--purple-deep); color: #fff }
[data-fe-site] :focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; border-radius: var(--r-sm) }

/* ── The navbar ──────────────────────────────────────────────────────────────
   docs/free-taleem-new-design/about.html · app.html · azkar.html · give.html — nav.nav > .wrap.nav-in.
   All four carry it identically, and it is the same bar on every page.

   THESE ARE THE MOCK'S OWN CLASS NAMES, replacing .fe-header / .fe-headbar /
   .fe-brand / .fe-brandmark / .fe-brandname / .fe-navlist / .fe-nav / .fe-pill /
   .fe-icobtn / .fe-divider. Those were the previous design's header, on the
   admin portal's tokens, with a 58px bar, 28px mint rounded-square brand mark,
   padded pill links and a text glyph for the theme toggle. None of that is what
   the new files draw.

   WHAT THE MOCK DOES NOT HAVE IS A MOBILE MENU. Below 860px it sets
   .nav-links{display:none} and stops — its five links are simply unreachable on
   a phone. This app has a burger and a slide-down menu, and they stay: dropping
   them to match the mock exactly would leave a phone reader with no navigation
   at all. They keep their .fe-* names because there is no mock rule to name
   them after, and they are styled from these tokens. */

[data-fe-site] .nav {
  position: sticky; top: 0; z-index: 40;
  background: var(--bg);
  background: color-mix(in srgb, var(--bg) 88%, transparent);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--border);
}
[data-fe-site] .nav-in { display: flex; align-items: center; gap: 1.2rem; min-height: 66px }

[data-fe-site] .brand { display: flex; align-items: center; gap: .6rem; text-decoration: none; font-family: var(--font-display); font-weight: 600; font-size: 1.16rem; letter-spacing: -.015em }
html[data-fe-site][lang="ur"] .brand { font-family: var(--fe-font-urdu); letter-spacing: 0 }
[data-fe-site] .brand-mark { width: 28px; height: 28px; flex: none }

[data-fe-site] .nav-links { display: flex; gap: 1.4rem; margin-inline-start: auto; align-items: center }
[data-fe-site] .nav-links a { text-decoration: none; color: var(--muted); font-size: .94rem; transition: color var(--t) }
[data-fe-site] .nav-links a:hover { color: var(--accent) }
[data-fe-site] .nav-tools { display: flex; gap: .5rem; margin-inline-start: auto; align-items: center }
[data-fe-site] .nav-links + .nav-tools { margin-inline-start: 0 }

/* ── The language pill holds ONE position in both languages ──────────────────
   A DELIBERATE DEVIATION FROM THE MOCK, and the only one in this bar. The mock
   flips <html dir> and lets every group mirror, so its language control sits on
   the right in English and on the left in Urdu. Asked for directly, and the
   reasoning stands on its own: a reader who cannot read the language currently
   showing finds that control by POSITION, and mirroring is precisely what takes
   the position away. Everything else in the bar still mirrors.

   .nav-lang is a direct child of .nav-in (see FeHeader.razor) so `order` can
   reach it — order sorts an element among its flex siblings, and inside
   .nav-tools it could only have swapped with the theme button.

   order:-1 makes it the FIRST item of the bar. In a right-to-left row the first
   item is the right-hand end, which is the edge it already occupies in English.
   The brand shifts left by the width of one pill; nothing else moves. */
html[data-fe-site][lang="ur"] .nav-lang { order: -1 }

/* Leaving .nav-tools cost the pill that group's .5rem gap and gave it the bar's
   1.2rem instead, so the theme button drifted away from it. Pulled back to .5rem
   — English only, because in Urdu the pill is at the far end with the brand
   beside it and the bar's own 1.2rem is the correct distance there.
   :not([lang="ur"]) rather than [lang="en"]: the attribute is stamped per request
   and pre-paint by fe-lang-boot.js, and "not Urdu" is the condition that holds
   however it got there. */
html[data-fe-site]:not([lang="ur"]) .nav-lang { margin-inline-start: calc(.5rem - 1.2rem) }

[data-fe-site] .lang-btn,
[data-fe-site] .theme-btn {
  border: 1px solid var(--border-strong); background: transparent; color: var(--fg);
  border-radius: var(--r-sm); cursor: pointer;
  transition: border-color var(--t), color var(--t), background var(--t);
  /* 44px, where the mock leaves these ~30px tall. §13 rule 9 is this app's
     tap-target floor and D24 relaxed it only for the old 58px bar; the new one
     is 66px, so the floor fits inside it with room to spare and there is
     nothing to trade against. The mock's WIDTH (38px) and every other value
     here are its own. */
  min-height: 44px;
  display: inline-flex; align-items: center; justify-content: center;
}
[data-fe-site] .lang-btn { font-family: var(--fe-font-urdu); font-size: .92rem; line-height: 1; padding: .45rem .9rem .72rem }
html[data-fe-site][lang="ur"] .lang-btn { font-family: var(--font-sans); padding: .55rem .9rem }
[data-fe-site] .theme-btn { width: 38px; padding: 0 }
[data-fe-site] .theme-btn svg { width: 17px; height: 17px; stroke: currentColor; fill: none; stroke-width: 1.6; stroke-linecap: round }
[data-fe-site] .theme-btn .moon { display: none }
html[data-fe-site][data-theme="dark"] .theme-btn .moon { display: block }
html[data-fe-site][data-theme="dark"] .theme-btn .sun { display: none }
[data-fe-site] .lang-btn:hover,
[data-fe-site] .theme-btn:hover { border-color: var(--accent); color: var(--accent) }

@media (max-width: 860px) {
  [data-fe-site] .nav-links { display: none }

  /* TWO LANGUAGE BUTTONS WERE BEING DRAWN HERE. .nav-tools is displayed at every
     width and carried one; .fe-navmob appears below 860px and carries another, so
     a phone got a pill beside the brand AND a pill beside the burger. The burger
     row's is the one that belongs to this width — it is the group a thumb reaches
     — so the bar's is hidden and .nav-tools is left holding the theme button alone. */
  [data-fe-site] .nav-lang { display: none }

  /* The same statement as the bar's pill, applied to the row that replaces it: the
     language control does not mirror. order:-1 puts the row at the right-hand end
     of a right-to-left bar, the auto margin that would push it back to the left is
     dropped, and row-reverse keeps the pill and the burger in the order English
     shows them, so the pill sits second from the edge in both languages. */
  html[data-fe-site][lang="ur"] .fe-navmob {
    order: -1;
    margin-inline-start: 0;
    flex-direction: row-reverse;
  }

  /* With the burger row pinned and .nav-links gone there is no auto margin left to
     absorb the bar's free space, so the brand would drift in beside it. This is the
     mobile-only replacement — and it is guarded to this width for that reason: on
     desktop .nav-links already absorbs it, and a second auto margin would split the
     free space between them and centre the brand. */
  html[data-fe-site][lang="ur"] .brand { margin-inline-start: auto }
}

/* The burger and the slide-down menu — this app's, not the mock's. .fe-navmob is
   hidden above 860px by fe.css, which owns that swap, so exactly one of
   .nav-links / .fe-navmob is ever displayed. */
[data-fe-site] .fe-navmob { margin-inline-start: auto }
[data-fe-site] .fe-burger { width: 44px; min-height: 44px; display: inline-flex; align-items: center; justify-content: center; font-size: 1.1rem; background: transparent; border: 1px solid var(--border-strong); border-radius: var(--r-sm); color: var(--fg); cursor: pointer; transition: border-color var(--t), color var(--t) }
[data-fe-site] .fe-burger:hover { border-color: var(--accent); color: var(--accent) }
[data-fe-site] .fe-menu { border-top: 1px solid var(--border); background: var(--bg) }
[data-fe-site] .fe-menurow { display: flex; flex-direction: column; padding-block: .5rem 1rem }
[data-fe-site] .fe-menuitem { display: flex; align-items: center; min-height: 44px; text-decoration: none; color: var(--muted); font-size: .98rem; border-bottom: 1px solid var(--rule); transition: color var(--t) }
[data-fe-site] .fe-menuitem:last-child { border-bottom: 0 }
[data-fe-site] .fe-menuitem:hover { color: var(--accent) }

[data-fe-site] .skip { position: absolute; inset-inline-start: -9999px }
[data-fe-site] .skip:focus { position: fixed; inset-inline-start: 1rem; top: 1rem; z-index: 99; background: var(--accent); color: var(--on-accent); padding: .7rem 1.2rem; border-radius: var(--r-sm) }
[data-fe-site] .vh { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap }

/* Scroll reveals.
   DELIBERATE DIVERGENCE FROM THE MOCK, carried over from the first port. The
   mock hides .reveal unconditionally and relies on script to bring it back, so
   a blocked script, a missing IntersectionObserver or a JS error leaves the
   whole page blank. Here the fade-out lives behind html.fe-motion, a class
   fe-home.js adds only once an observer exists to reveal them again. No JS, no
   observer, or reduced motion: the class is never added and the page renders at
   full opacity. A stylesheet must not be able to blank the page on its own. */
html[data-fe-site].fe-motion .reveal { opacity: 0; transform: translateY(10px); transition: opacity .4s ease, transform .4s ease }
html[data-fe-site].fe-motion .reveal.in { opacity: 1; transform: none }

/* ═══════════════════════════════════════════════════════════════════════════
   Landing sections — hero, worked example, scripture band, stats
   ═══════════════════════════════════════════════════════════════════════════ */

[data-fe-site] .hero { padding-block: clamp(2.6rem, 6vw, 5rem) 0 }
[data-fe-site] .hero-grid { display: grid; grid-template-columns: 1.05fr .95fr; gap: clamp(2rem, 5vw, 4rem); align-items: center }
@media (max-width: 900px) { [data-fe-site] .hero-grid { grid-template-columns: 1fr } }
[data-fe-site] .hero h1 { font-size: var(--step-4); max-width: 14ch }
[data-fe-site] .hero h1 .mark { color: var(--accent) }
[data-fe-site] .hero .lede { margin-top: 1.4rem }
[data-fe-site] .hero-actions { display: flex; gap: .7rem; margin-top: 1.9rem; flex-wrap: wrap }
[data-fe-site] .hero-note { display: flex; gap: 1.4rem; margin-top: 1.7rem; flex-wrap: wrap; color: var(--muted) }
[data-fe-site] .hero-note span { display: flex; align-items: center; gap: .45rem }
[data-fe-site] .tick { color: var(--accent); font-weight: 700 }

/* The worked-example card in the hero. The 3.2rem inline-start padding clears
   the mint rule drawn by ::after, so the RTL pair below is a real correction
   and not a mirror-image nicety: without it the text sits on top of the rule. */
[data-fe-site] .paper-card { background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-lg); overflow: hidden; position: relative }
[data-fe-site] .paper-card::after { content: ""; position: absolute; top: 0; bottom: 0; inset-inline-start: 34px; width: 1px; background: var(--accent); opacity: .18 }
[data-fe-site] .pc-head { display: flex; flex-wrap: wrap; gap: .5rem 1rem; align-items: center; padding: .9rem 1.2rem .9rem 3.2rem; border-bottom: 1px solid var(--border); color: var(--muted) }
html[data-fe-site][dir="rtl"] .pc-head { padding: .9rem 3.2rem .9rem 1.2rem }
[data-fe-site] .pc-head .chip { color: var(--accent) }
[data-fe-site] .pc-body { padding: 1.4rem 1.4rem 1.6rem 3.2rem }
html[data-fe-site][dir="rtl"] .pc-body { padding: 1.4rem 3.2rem 1.6rem 1.4rem }
[data-fe-site] .pc-q { font-weight: 600; margin-bottom: .3rem }
[data-fe-site] .pc-q-ur { font-family: var(--fe-font-urdu); direction: rtl; text-align: right; font-size: .95rem; line-height: 2.3; color: var(--muted); margin-bottom: 1.1rem }
[data-fe-site] .pc-step { display: grid; grid-template-columns: auto 1fr; gap: .9rem; padding-block: .5rem; border-top: 1px solid var(--border) }
[data-fe-site] .pc-step .k { color: var(--accent); padding-top: .2rem }
[data-fe-site] .pc-ans { margin-top: 1rem; padding: .7rem 1rem; background: var(--surface-2); border-radius: var(--r-sm); border-inline-start: 2px solid var(--accent); display: flex; justify-content: space-between; gap: 1rem; align-items: baseline; flex-wrap: wrap }
[data-fe-site] .pc-ans strong { font-family: var(--font-mono); font-size: 1.12rem; color: var(--accent) }
[data-fe-site] .pc-foot { margin-top: 1rem; display: flex; justify-content: flex-end }

[data-fe-site] .link-btn { background: none; border: 0; padding: .3rem 0; cursor: pointer; color: var(--accent); font-family: var(--font-mono); font-size: .74rem; letter-spacing: .08em; text-transform: uppercase; text-decoration: underline; text-underline-offset: 4px }
[data-fe-site] .link-btn:lang(ur){ font-family: var(--fe-font-urdu); letter-spacing: 0; text-transform: none; font-size: .92rem }
[data-fe-site] .link-btn:hover { color: var(--fg) }

/* Scripture band — an inverse (dark) ground in BOTH themes. Everything inside
   it uses the on-ink tokens, so it does not depend on the section hosting it. */
[data-fe-site] .band { margin-top: clamp(2.5rem, 5vw, 3.5rem); background: var(--surface-ink); color: var(--fg-on-ink); border: 1px solid var(--border-ink); border-radius: var(--r-lg); position: relative; overflow: hidden }
[data-fe-site] .band::before {
  content: ""; position: absolute; inset: 0; opacity: .16; pointer-events: none;
  background-image: radial-gradient(circle at 0 0, transparent 68%, var(--accent-2) 69%, transparent 71%),
                    radial-gradient(circle at 100% 100%, transparent 68%, var(--accent) 69%, transparent 71%);
  background-size: 52px 52px;
}
[data-fe-site] .band-in { position: relative; display: grid; grid-template-columns: auto 1fr auto; gap: clamp(1.2rem, 3vw, 2.5rem); align-items: center; padding-block: clamp(1.6rem, 3.5vw, 2.3rem) }
@media (max-width: 900px) { [data-fe-site] .band-in { grid-template-columns: 1fr; gap: 1.2rem } }
[data-fe-site] .band-label { display: flex; flex-direction: column; gap: .5rem }
[data-fe-site] .band-label .mono { color: var(--accent-2) }
[data-fe-site] .tabs { display: flex; gap: .4rem; flex-wrap: wrap }
[data-fe-site] .tab { font-family: var(--font-mono); font-size: .7rem; letter-spacing: .08em; text-transform: uppercase; background: transparent; border: 1px solid var(--border-ink); color: rgba(232, 235, 242, .72); padding: .35rem .75rem; cursor: pointer; border-radius: var(--r-sm); transition: all var(--t) }
[data-fe-site] .tab:lang(ur){ font-family: var(--fe-font-urdu); letter-spacing: 0; text-transform: none; padding: .45rem .85rem .65rem }
[data-fe-site] .tab[aria-selected="true"] { background: var(--accent-2); border-color: var(--accent-2); color: #14082E }
[data-fe-site] .tab:hover { color: #fff; border-color: var(--accent-2) }
[data-fe-site] .band-body { border-inline-start: 1px solid var(--border-ink); padding-inline-start: clamp(1.2rem, 3vw, 2.5rem) }
@media (max-width: 900px) { [data-fe-site] .band-body { border-inline-start: 0; border-top: 1px solid var(--border-ink); padding-inline-start: 0; padding-top: 1.2rem } }
[data-fe-site] .ayah { font-family: var(--fe-font-arabic); direction: rtl; text-align: right; font-size: clamp(1.5rem, 3vw, 2.05rem); line-height: 2; color: #F2F4F8 }
[data-fe-site] .rosette { display: inline-block; width: 1em; height: 1em; vertical-align: -.14em; margin-inline: .2em }
[data-fe-site] .trans-ur { font-family: var(--fe-font-urdu); direction: rtl; text-align: right; line-height: 2.5; color: rgba(232, 235, 242, .9); margin-top: 1rem; font-size: .98rem }
[data-fe-site] .trans-en { color: rgba(232, 235, 242, .74); margin-top: .6rem; line-height: 1.7 }
[data-fe-site] .ref { color: var(--accent-2); font-family: var(--font-mono); font-size: .73rem; letter-spacing: .08em; margin-top: 1rem }

/* THE CITATION LINES ARE ISOLATED, NOT FORCED LTR. .ref under the band, .src under a dua
   row and under a hadith quote all hold a Latin citation - "Surah Ash-Sharh · 94:6" - in a
   paragraph whose direction follows the reader.

   They used to carry dir="ltr" in the markup. On a BLOCK that sets direction, and a block's
   text-align: start then resolves to LEFT, so on the Urdu site every citation pinned itself
   to the left edge while the Arabic, the Urdu and the panel around it sat right. The mocks
   put no dir on any of them for exactly that reason.

   unicode-bidi: isolate keeps what the attribute was actually wanted for - the citation's
   own run cannot be reordered by the script around it, and cannot reorder it - while leaving
   direction inherited, so the line sits on the reader's side. Same mechanism as .stat-n
   (reference doc §6.3). Inline numerals elsewhere keep dir="ltr": on a <span> it orders the
   run without touching the block's alignment. */
[data-fe-site] .ref,
[data-fe-site] .dua-row .src,
[data-fe-site] .hadith-quote .src { unicode-bidi: isolate }
[data-fe-site] .ref:lang(ur){ font-family: var(--fe-font-urdu); letter-spacing: 0; font-size: .9rem }
[data-fe-site] .band-next button { background: transparent; border: 1px solid var(--border-ink); color: var(--accent-2); cursor: pointer; padding: .55rem 1rem; border-radius: var(--r-sm); font-family: var(--font-mono); font-size: .7rem; letter-spacing: .08em; text-transform: uppercase; transition: all var(--t) }
[data-fe-site] .band-next button:lang(ur){ font-family: var(--fe-font-urdu); letter-spacing: 0; text-transform: none; font-size: .9rem }
[data-fe-site] .band-next button:hover { border-color: var(--accent-2); color: #fff }

/* NOTE ON .trans-en: the mock hides the English gloss in Urdu with
   body.lang-ur .trans-en{display:none}. That rule is still NOT ported, but the
   reason has changed and the old one was wrong.

   IT USED TO SAY "this app renders one language at a time, so there is no second
   copy to hide". True of chrome, false of scripture. An ayah, a dua and a hadith are
   shown in Arabic with BOTH renderings under them — the mock stacks .ayah, .trans-ur
   and .trans-en and drops only the English for an Urdu reader. Resolving to one
   language deleted the Urdu line for every English-medium reader, which is a line of
   content and not a duplicate of the interface.

   The components now render .trans-ur / .ur unconditionally and wrap the English in
   an @if, so the Urdu reader's markup carries no hidden second copy and this rule
   still has nothing to do. Same in .dua-row and .hadith-quote below. */

[data-fe-site] .stats { border-block: 1px solid var(--border); background: var(--surface-2) }
[data-fe-site] .stats-grid { display: grid; grid-template-columns: repeat(4, 1fr) }
@media (max-width: 820px) { [data-fe-site] .stats-grid { grid-template-columns: repeat(2, 1fr) } }
[data-fe-site] .stat { padding: clamp(1.6rem, 3.5vw, 2.4rem) clamp(1rem, 2.5vw, 1.6rem); border-inline-start: 1px solid var(--border) }
[data-fe-site] .stat:first-child { border-inline-start: 0 }
@media (max-width: 820px) {
  [data-fe-site] .stat:nth-child(odd) { border-inline-start: 0 }
  [data-fe-site] .stat:nth-child(n+3) { border-top: 1px solid var(--border) }
}
[data-fe-site] .stat-n { font-family: var(--font-mono); font-variant-numeric: tabular-nums; font-size: clamp(1.9rem, 4.2vw, 2.7rem); line-height: 1; color: var(--accent); font-weight: 500 }
[data-fe-site] .stat-n .suf { color: var(--accent-2) }
[data-fe-site] .stat-l { margin-top: .7rem; color: var(--fg); line-height: 1.5 }
[data-fe-site] .stat-sub { color: var(--muted); font-size: var(--step--1); margin-top: .25rem }

/* ═══════════════════════════════════════════════════════════════════════════
   Coverage — board chips, class cards, subject cards, status pills
   Shared by the landing grid AND the Find flow (FindBoard/FindClass/
   FindSubject), which is the whole point of them living here.
   ═══════════════════════════════════════════════════════════════════════════ */

[data-fe-site] .head-row { display: flex; justify-content: space-between; align-items: flex-end; gap: 2rem; flex-wrap: wrap; margin-bottom: 2.3rem }
[data-fe-site] .head-row h2 { font-size: var(--step-3); max-width: 18ch }

[data-fe-site] .board-row { display: flex; flex-wrap: wrap; gap: .5rem; margin-bottom: 1.8rem }
[data-fe-site] .board-chip { font: inherit; font-size: .92rem; background: var(--surface); border: 1px solid var(--border); color: var(--muted); padding: .42rem .9rem; border-radius: 999px; cursor: pointer; display: flex; align-items: baseline; gap: .5rem; transition: all var(--t) }
[data-fe-site] .board-chip .code { font-family: var(--font-mono); font-size: .66rem; letter-spacing: .08em; opacity: .7 }
[data-fe-site] .board-chip:hover { border-color: var(--accent); color: var(--fg) }
[data-fe-site] .board-chip[aria-pressed="true"] { background: var(--accent); border-color: var(--accent); color: var(--on-accent) }
[data-fe-site] .board-chip[aria-pressed="true"] .code { opacity: .85 }
/* .board-row / .board-chip HAS NO CALLER and is kept as the design file writes it. The courses
   page briefly drew its board picker with these, then moved to the region-grouped .subj-card
   tiles the Find flow uses, so that the two screens asking "which board" answer with one list.
   The aria-current and [disabled] variants that supported the chip version went with it: a
   dormant component should carry what the design file states and nothing invented around it. */

[data-fe-site] .status { font-family: var(--font-mono); font-size: .65rem; letter-spacing: .07em; text-transform: uppercase; border: 1px solid currentColor; padding: .18rem .5rem; border-radius: 999px; white-space: nowrap; display: inline-block }
[data-fe-site] .status:lang(ur){ font-family: var(--fe-font-urdu); letter-spacing: 0; text-transform: none; font-size: .8rem; padding: .24rem .6rem .34rem }
[data-fe-site] .status--soon { color: var(--muted) }
[data-fe-site] .status--wip { color: var(--negative) }
[data-fe-site] .status--part { color: var(--accent-2) }
[data-fe-site] .status--done { color: var(--accent) }

/* The fill width is the one inline style the guardrail allows: a bare custom
   property assignment, style="--bar-pct:@pct". Anything else in a style
   attribute fails InlineStyleGuardrailTests. */
[data-fe-site] .bar { display: block; height: 3px; background: var(--border); border-radius: 999px; margin-top: .85rem; overflow: hidden }
[data-fe-site] .bar i { display: block; height: 100%; background: var(--accent); width: var(--bar-pct, 0); border-radius: 999px; transition: width .3s ease }
/* is-done is the default fill and sets no colour of its own, but it IS declared, because
   the markup writes it: the mock tags a finished bar `bar is-done` and leaves it to the
   base rule. A class that appears in markup and in no stylesheet reads as a mistake to
   the next person who greps for it. */
[data-fe-site] .bar.is-done i { background: var(--accent) }
[data-fe-site] .bar.is-wip i { background: var(--negative) }
[data-fe-site] .bar.is-part i { background: var(--accent-2) }
[data-fe-site] .bar.is-soon i { background: transparent }

[data-fe-site] .class-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(148px, 1fr)); gap: 1px; background: var(--border); border: 1px solid var(--border); border-radius: var(--r-lg); overflow: hidden }
[data-fe-site] .class-card { background: var(--surface); padding: 1.4rem 1.1rem 1.2rem; text-decoration: none; display: block; width: 100%; border: 0; font: inherit; color: inherit; text-align: start; transition: background var(--t), color var(--t); cursor: pointer }
[data-fe-site] .cc-n,
[data-fe-site] .cc-t,
[data-fe-site] .cc-sub { display: block }
[data-fe-site] .cc-n { font-family: var(--font-mono); font-size: 2.4rem; line-height: 1; color: var(--accent); font-weight: 500 }
[data-fe-site] .cc-t { font-family: var(--font-display); font-weight: 600; margin-top: .55rem }
[data-fe-site] .cc-t:lang(ur){ font-family: var(--fe-font-urdu) }
[data-fe-site] .cc-sub { color: var(--muted); font-size: var(--step--1); margin-top: .2rem }
[data-fe-site] .class-card[aria-pressed="true"],
[data-fe-site] .class-card:hover,
[data-fe-site] .class-card:focus-visible { background: var(--surface-ink); color: var(--fg-on-ink) }
[data-fe-site] .class-card[aria-pressed="true"] .cc-sub,
[data-fe-site] .class-card:hover .cc-sub,
[data-fe-site] .class-card:focus-visible .cc-sub { color: var(--muted-on-ink) }
[data-fe-site] .class-card[aria-pressed="true"] .bar,
[data-fe-site] .class-card:hover .bar,
[data-fe-site] .class-card:focus-visible .bar { background: rgba(255, 255, 255, .16) }
[data-fe-site] .class-card[aria-pressed="true"] .status--soon,
[data-fe-site] .class-card:hover .status--soon { color: var(--muted-on-ink) }

[data-fe-site] .subj-panel { margin-top: 2.4rem }
[data-fe-site] .subj-head { display: flex; justify-content: space-between; align-items: baseline; gap: 1rem; flex-wrap: wrap; margin-bottom: 1rem }
[data-fe-site] .subj-head .who { font-family: var(--font-display); font-weight: 600; font-size: 1.05rem }
[data-fe-site] .subj-head .who:lang(ur){ font-family: var(--fe-font-urdu) }
[data-fe-site] .subj-head .roll { color: var(--muted) }
[data-fe-site] .subj-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(164px, 1fr)); gap: 1px; background: var(--border); border: 1px solid var(--border); border-radius: var(--r-lg); overflow: hidden }
[data-fe-site] .subj-card { background: var(--surface); padding: 1.05rem 1rem .95rem; display: flex; flex-direction: column; min-height: 130px; transition: background var(--t) }
[data-fe-site] .subj-card:hover { background: var(--surface-2) }
/* The mock's subject cell is a <div> — it has nowhere to go, because the mock has no
   routing. Ours is an <a> on the Find flow and on the landing grid, so the cell has to
   survive being a link: strip the underline and the visited colour, and give it the
   same focus-visible treatment hovering already has. Declared here rather than in each
   page, because "this cell is sometimes a link" is a fact about the cell. */
[data-fe-site] a.subj-card { text-decoration: none; color: inherit }
[data-fe-site] a.subj-card:focus-visible { background: var(--surface-2) }
[data-fe-site] .subj-name { font-family: var(--font-display); font-weight: 600; font-size: .98rem; line-height: 1.28 }
[data-fe-site] .subj-name:lang(ur){ font-family: var(--fe-font-urdu); line-height: 1.9 }
/* One muted line of detail under a card's name. The mock's subject cell has no such
   line — it shows a status pill and a coverage bar and nothing else — but this app
   knows the chapter count and the Find flow has always shown it. Declared here, beside
   the cell it belongs to, rather than as a private rule on FindSubject: the moment a
   second page wants "a quiet line under a card name" it must not invent a third name
   for it. Same metrics as .cc-sub, which is that line on a class card. */
[data-fe-site] .subj-sub { color: var(--muted); font-size: var(--step--1); margin-top: .2rem }
[data-fe-site] .subj-card .status { align-self: flex-start; margin-top: .55rem }
[data-fe-site] .subj-card .bar { margin-top: auto }
[data-fe-site] .subj-dl { background: none; border: 0; cursor: pointer; color: var(--accent); font-family: var(--font-mono); font-size: .65rem; letter-spacing: .08em; text-transform: uppercase; text-decoration: underline; text-underline-offset: 4px; padding: .35rem 0 0; white-space: nowrap; align-self: flex-start }
[data-fe-site] .subj-dl:lang(ur){ font-family: var(--fe-font-urdu); letter-spacing: 0; text-transform: none; font-size: .85rem }
[data-fe-site] .subj-dl:hover { color: var(--fg) }
[data-fe-site] .subj-dl[hidden] { display: none }
[data-fe-site] .subj-legend { display: flex; flex-wrap: wrap; gap: .5rem .9rem; margin-top: 1.2rem; color: var(--muted); font-size: var(--step--1) }
[data-fe-site] .subj-legend span { display: flex; align-items: center; gap: .4rem }
[data-fe-site] .swatch { width: 9px; height: 9px; flex: none; border-radius: 999px }
[data-fe-site] .swatch-done { background: var(--accent) }
[data-fe-site] .swatch-part { background: var(--accent-2) }
[data-fe-site] .swatch-wip { background: var(--negative) }
[data-fe-site] .swatch-soon { background: var(--border-strong) }

/* ═══════════════════════════════════════════════════════════════════════════
   Azkar, why-free, give, footer
   ═══════════════════════════════════════════════════════════════════════════ */

[data-fe-site] .illum { background: var(--surface-ink); color: var(--fg-on-ink); position: relative; overflow: hidden }
[data-fe-site] .illum::before {
  content: ""; position: absolute; inset: 0; opacity: .16; pointer-events: none;
  background-image: radial-gradient(circle at 0 0, transparent 68%, var(--accent-2) 69%, transparent 71%),
                    radial-gradient(circle at 100% 100%, transparent 68%, var(--accent) 69%, transparent 71%);
  background-size: 52px 52px;
}
[data-fe-site] .illum-in { position: relative }
[data-fe-site] .illum h2 { font-size: var(--step-2); color: #F2F4F8 }
[data-fe-site] .illum .eyebrow { color: var(--accent-2) }
[data-fe-site] .illum-grid { display: grid; grid-template-columns: .85fr 1.15fr; gap: clamp(1.5rem, 4vw, 3rem); margin-top: 2.4rem; align-items: start }
@media (max-width: 900px) { [data-fe-site] .illum-grid { grid-template-columns: 1fr } }

[data-fe-site] .tasbeeh { border: 1px solid var(--border-ink); border-radius: var(--r-lg); padding: clamp(1.3rem, 3vw, 1.8rem); background: rgba(255, 255, 255, .03) }
[data-fe-site] .tasbeeh h3 { font-size: 1.12rem; color: #F2F4F8 }
[data-fe-site] .tasbeeh .sub { color: var(--muted-on-ink); font-size: var(--step--1); margin-top: .4rem }
[data-fe-site] .tb-phrase { font-family: var(--fe-font-arabic); direction: rtl; font-size: 1.95rem; text-align: center; color: var(--accent); margin: 1.3rem 0 .3rem; line-height: 1.6 }
[data-fe-site] .tb-roman { text-align: center; color: var(--muted-on-ink); font-size: .88rem; font-family: var(--font-mono); letter-spacing: .07em; min-height: 1.2em }
[data-fe-site] .tb-count { display: block; width: 100%; margin: 1.3rem 0 0; cursor: pointer; background: transparent; border: 1px solid var(--border-ink); color: #F2F4F8; border-radius: var(--r); padding: 1.1rem; font-family: var(--font-mono); font-size: 2.5rem; line-height: 1; font-variant-numeric: tabular-nums; transition: background var(--t), border-color var(--t) }
[data-fe-site] .tb-count:hover { background: rgba(46, 212, 165, .1); border-color: var(--accent) }
[data-fe-site] .tb-count:active { background: rgba(46, 212, 165, .18) }
[data-fe-site] .tb-count .of { font-size: .95rem; color: var(--muted-on-ink) }
[data-fe-site] .tb-bar { height: 3px; background: rgba(255, 255, 255, .14); border-radius: 999px; margin-top: .6rem; overflow: hidden }
[data-fe-site] .tb-fill { height: 100%; background: var(--accent); width: var(--tb-pct, 0); border-radius: 999px; transition: width .2s ease }
[data-fe-site] .tb-foot { display: flex; justify-content: space-between; align-items: center; margin-top: .85rem; gap: 1rem }
[data-fe-site] .tb-reset { background: none; border: 0; color: var(--muted-on-ink); cursor: pointer; font-family: var(--font-mono); font-size: .72rem; letter-spacing: .08em; text-transform: uppercase; padding: .3rem }
[data-fe-site] .tb-reset:lang(ur){ font-family: var(--fe-font-urdu); letter-spacing: 0; text-transform: none; font-size: .9rem }
[data-fe-site] .tb-reset:hover { color: var(--accent) }
[data-fe-site] .tb-status { color: var(--muted-on-ink); font-size: var(--step--1) }

[data-fe-site] .dua-list { display: grid; gap: 1px; background: var(--border-ink); border: 1px solid var(--border-ink); border-radius: var(--r-lg); overflow: hidden }
[data-fe-site] .dua-row { background: var(--surface-ink); padding: clamp(1.1rem, 2.6vw, 1.5rem) }
[data-fe-site] .dua-row .when { color: var(--accent-2) }
[data-fe-site] .dua-row .ar { font-family: var(--fe-font-arabic); direction: rtl; text-align: right; font-size: 1.42rem; line-height: 1.9; color: #F2F4F8; margin: .8rem 0 .7rem }
[data-fe-site] .dua-row .ur { font-family: var(--fe-font-urdu); direction: rtl; text-align: right; font-size: .95rem; line-height: 2.4; color: rgba(232, 235, 242, .9) }
[data-fe-site] .dua-row .en { color: rgba(232, 235, 242, .72); font-size: .95rem; margin-top: .5rem }
[data-fe-site] .dua-row .src { color: var(--accent); font-family: var(--font-mono); font-size: .7rem; letter-spacing: .08em; margin-top: .7rem }
[data-fe-site] .dua-row .src:lang(ur){ font-family: var(--fe-font-urdu); letter-spacing: 0; font-size: .88rem }

[data-fe-site] .free-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 2.2rem; margin-top: 2.4rem }
[data-fe-site] .free-item h3 { font-size: var(--step-1); margin-bottom: .6rem }
[data-fe-site] .free-item p { color: var(--muted) }
[data-fe-site] .free-item .rule { width: 32px; height: 2px; background: var(--accent); border-radius: 999px; margin-bottom: 1.1rem }

[data-fe-site] .give { background: var(--surface-ink); color: var(--fg-on-ink) }
[data-fe-site] .give h2 { font-size: var(--step-3); color: #F2F4F8; max-width: 17ch }

/* THE ch CAP IS LIFTED FOR URDU, and the reason is a unit, not a taste.

   ch is defined as the advance of the "0" glyph in the element's font. The mock loads Noto
   Nastaliq Urdu from Google with no unicode-range, so its "0" is the one ch measures and 17ch
   is a wide, Nastaliq-sized measure. This app SELF-HOSTS the same family with a unicode-range
   covering the Arabic blocks only (fe-fonts.css) — U+0030 is not in it — so the face does not
   supply "0" and ch resolves from the next font in the chain that does, which on Windows is
   Segoe UI. Same rule, materially narrower measure, and this heading broke onto two lines
   where the mock keeps it on one.

   Lifted rather than retuned: any em figure here would be a guess at a Nastaliq "0", and the
   heading is already bounded by its .give-head column (1fr of the page measure), which is what
   actually shapes it. English is untouched and keeps the mock's 17ch.

   The same unit applies to every other ch measure on the Urdu site — .hero h1 at 14ch,
   .head-row h2 at 18ch, .page-head h1 at 22ch, .lede at 56ch. They are all narrower in Urdu
   than the mock draws them for the same reason. Only the one that visibly broke is changed
   here; widen the others the same way if they do. */
[data-fe-site] .give h2:lang(ur) { max-width: none }
[data-fe-site] .give .eyebrow { color: var(--accent) }
[data-fe-site] .give p { color: rgba(232, 235, 242, .82) }
[data-fe-site] .give-head { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(2rem, 5vw, 4rem); align-items: end }
@media (max-width: 880px) { [data-fe-site] .give-head { grid-template-columns: 1fr } }
[data-fe-site] .give-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 1px; background: var(--border-ink); border: 1px solid var(--border-ink); border-radius: var(--r-lg); overflow: hidden; margin-top: clamp(2.2rem, 5vw, 3rem) }
[data-fe-site] .give-card { background: var(--surface-ink); padding: clamp(1.4rem, 3vw, 1.8rem); display: flex; flex-direction: column; gap: .7rem; transition: background var(--t) }
[data-fe-site] .give-card:hover { background: rgba(255, 255, 255, .03) }
[data-fe-site] .give-card h3 { font-size: 1.14rem; color: #F2F4F8 }
[data-fe-site] .give-card p { font-size: .96rem }
[data-fe-site] .give-card .kicker { color: var(--accent-2) }
[data-fe-site] .give-card .out { margin-top: auto; padding-top: .6rem }
[data-fe-site] .give-card a.out-link { color: var(--accent); text-decoration: underline; text-underline-offset: 4px; font-family: var(--font-mono); font-size: .72rem; letter-spacing: .08em; text-transform: uppercase }
[data-fe-site] .give-card a.out-link:lang(ur){ font-family: var(--fe-font-urdu); letter-spacing: 0; text-transform: none; font-size: .92rem }
[data-fe-site] .give-card a.out-link:hover { color: #fff }
[data-fe-site] .hadith-quote { border-inline-start: 2px solid var(--accent); padding-inline-start: 1.3rem; margin-top: clamp(2.2rem, 5vw, 3rem); max-width: 74ch }
[data-fe-site] .hadith-quote .ar { font-family: var(--fe-font-arabic); direction: rtl; text-align: right; font-size: 1.48rem; line-height: 2; color: #F2F4F8 }
[data-fe-site] .hadith-quote .en { margin-top: .8rem; color: rgba(232, 235, 242, .85) }
[data-fe-site] .hadith-quote .ur { font-family: var(--fe-font-urdu); direction: rtl; text-align: right; line-height: 2.5; margin-top: .6rem; color: rgba(232, 235, 242, .9); font-size: .97rem }
[data-fe-site] .hadith-quote .src { color: var(--accent-2); margin-top: .9rem }
[data-fe-site] .give-note { margin-top: 1.5rem; color: var(--muted-on-ink); font-size: var(--step--1); max-width: 70ch }

/* ── The footer ──────────────────────────────────────────────────────────────
   docs/free-taleem-new-design/index.html footer.foot. An inverse (ink) ground in BOTH themes, like the
   scripture band and the give block, so it closes every page the same way.

   FOUR COLUMNS, AND THE VALUES ARE THE NEW FILES'. docs/free-taleem-new-design/index.html still
   declares grid-template-columns:1.4fr 1fr 1fr — three columns for four
   children, so its fourth group wraps under the wordmark. about/app/azkar/give
   are newer and fix it: 1.5fr 1fr 1fr 1fr at gap 2.2rem, with an extra 980px
   step to three columns before the 760px step to two. Those four files agree
   byte-for-byte and are the authority here; index.html is behind. */

[data-fe-site] .foot { background: var(--surface-ink); color: var(--muted-on-ink); padding-block: 3rem 2rem; border-top: 1px solid var(--border-ink) }
[data-fe-site] .foot-grid { display: grid; grid-template-columns: 1.5fr 1fr 1fr 1fr; gap: 2.2rem }
@media (max-width: 980px) { [data-fe-site] .foot-grid { grid-template-columns: 1fr 1fr 1fr } }
@media (max-width: 760px) { [data-fe-site] .foot-grid { grid-template-columns: 1fr 1fr } }

[data-fe-site] .foot h4 { font-family: var(--font-mono); font-size: .72rem; letter-spacing: .1em; text-transform: uppercase; color: var(--accent); margin: 0 0 1rem; font-weight: 400 }
[data-fe-site] .foot h4:lang(ur){ font-family: var(--fe-font-urdu); letter-spacing: 0; text-transform: none; font-size: .92rem }

/* button.as-link is in the selector because the mock's footer has one — a control
   that reads as a link. This app has none today; the rule is kept so that adding
   one is a markup change and not a stylesheet change. */
[data-fe-site] .foot a,
[data-fe-site] .foot button.as-link {
  color: var(--muted-on-ink); text-decoration: none; display: block; padding: .25rem 0;
  background: none; border: 0; font: inherit; text-align: start; cursor: pointer; transition: color var(--t);
}
[data-fe-site] .foot a:hover,
[data-fe-site] .foot button.as-link:hover { color: var(--accent) }
[data-fe-site] .foot .brand { color: #F2F4F8 }

/* The mock sets these two with style="" attributes on the elements themselves.
   InlineStyleGuardrailTests fails any style attribute in .razor markup that is not
   a bare custom-property assignment (L22), so they are classes here. The wordmark
   is --font-display rather than the mock's literal 'Fraunces', serif — same face,
   one definition, and it becomes Nastaliq under html[lang="ur"] like every other
   heading on the site. */
[data-fe-site] .foot-brand { font-family: var(--font-display); font-weight: 600; font-size: 1.15rem }
[data-fe-site] .foot-brand:lang(ur){ font-family: var(--fe-font-urdu); font-weight: 700 }
[data-fe-site] .foot-blurb { margin-top: .6rem; max-width: 34ch }

[data-fe-site] .foot-bottom { margin-top: 2.4rem; padding-top: 1.4rem; border-top: 1px solid var(--border-ink); display: flex; justify-content: space-between; gap: 1rem; flex-wrap: wrap; font-size: var(--step--1) }

/* ═══════════════════════════════════════════════════════════════════════════
   About · Give · Azkar · Share · App

   THE MOCK'S OWN SECTION HEADING, and its own grouping. docs/free-taleem-new-design/about.html and
   docs/free-taleem-new-design/app.html carry this block byte-for-byte identically, under that exact
   title — every page of the mock ships the same superset stylesheet. So these
   are NOT page-specific components that happen to appear on two pages; they are
   part of the shared design system, and the mock says so.

   That matters because .badge-soon and the whole .wb-* whiteboard set were
   living in Home.razor.css, where Blazor scoped them to Home alone. The App
   page draws the same whiteboard and could not reach them.
   ═══════════════════════════════════════════════════════════════════════════ */

[data-fe-site] .badge-soon { display: inline-flex; align-items: center; gap: .5rem; border: 1px solid var(--accent-2); color: var(--accent-2); border-radius: 999px; padding: .25rem .8rem; font-family: var(--font-mono); font-size: .66rem; letter-spacing: .09em; text-transform: uppercase }
[data-fe-site] .badge-soon:lang(ur){ font-family: var(--fe-font-urdu); letter-spacing: 0; text-transform: none; font-size: .85rem; padding: .3rem .85rem .45rem }
[data-fe-site] .badge-soon::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: var(--accent-2) }

/* The promise list. A <ul> whose rows are hairline-separated cells, each marked
   with a mono glyph — mint for a promise kept, coral on li.never for one the
   product refuses. The colour IS the meaning here, so the mark itself must carry
   a character (✓ / ✕) and not be a coloured bullet. */
[data-fe-site] .pledge { list-style: none; padding: 0; margin: 1.8rem 0 0; display: grid; gap: 1px; background: var(--border); border: 1px solid var(--border); border-radius: var(--r-lg); overflow: hidden }
[data-fe-site] .pledge li { background: var(--surface); padding: 1rem 1.1rem; display: grid; grid-template-columns: 1.6rem 1fr; gap: .8rem; align-items: start }
[data-fe-site] .pledge .mk { font-family: var(--font-mono); font-weight: 500; line-height: 1.6; color: var(--accent) }
[data-fe-site] .pledge li.never .mk { color: var(--negative) }
[data-fe-site] .pledge strong { font-weight: 600 }
[data-fe-site] .pledge span.t { color: var(--muted) }

/* Numbered explainer steps. The numeral is a CSS counter, not markup: the rows
   are authored as a list of records and renumbering them must not mean editing
   the markup. Forced through the mono face like every other numeral on the site. */
[data-fe-site] .numbered { counter-reset: s; display: grid; gap: 1.6rem; margin-top: 2rem }
[data-fe-site] .numbered > div { display: grid; grid-template-columns: 2.4rem 1fr; gap: 1.1rem; align-items: start }
[data-fe-site] .numbered > div::before { counter-increment: s; content: counter(s); font-family: var(--font-mono); font-size: 1.5rem; color: var(--accent); line-height: 1.1 }
[data-fe-site] .numbered h3 { font-size: var(--step-1); margin-bottom: .4rem }
[data-fe-site] .numbered p { color: var(--muted) }

/* Share — the copy field and the pre-written message box. */
[data-fe-site] .copy-row { display: flex; gap: .6rem; flex-wrap: wrap; margin-top: 1.1rem }
[data-fe-site] .copy-field { flex: 1 1 250px; font: inherit; font-family: var(--font-mono); font-size: .9rem; background: var(--surface-2); color: var(--fg); border: 1px solid var(--border); border-radius: var(--r-sm); padding: .75rem .85rem }
[data-fe-site] .msg-box { background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-lg); padding: 1.3rem; margin-top: 1.1rem }
[data-fe-site] .msg-box .lbl { font-family: var(--font-mono); font-size: .66rem; letter-spacing: .09em; text-transform: uppercase; color: var(--muted); margin-bottom: .7rem }
[data-fe-site] .msg-box .lbl:lang(ur){ font-family: var(--fe-font-urdu); letter-spacing: 0; text-transform: none; font-size: .85rem }
/* The pre-written message itself. .body.ur is the Urdu copy a reader sends on:
   Nastaliq, right-aligned and RTL regardless of the site language, because the
   message is composed IN Urdu and stays Urdu when an English reader shares it. */
[data-fe-site] .msg-box .body { line-height: 1.75 }
[data-fe-site] .msg-box .body.ur { font-family: var(--fe-font-urdu); direction: rtl; text-align: right; line-height: 2.4 }
[data-fe-site] .copied { color: var(--accent); font-size: var(--step--1); align-self: center }

/* The azkar list — an inverse-ground row carrying Arabic, its Urdu, and a count. */
[data-fe-site] .zikr-list { display: grid; gap: 1px; background: var(--border-ink); border: 1px solid var(--border-ink); border-radius: var(--r-lg); overflow: hidden }
[data-fe-site] .zikr { background: var(--surface-ink); padding: 1.1rem 1.2rem; display: grid; grid-template-columns: 1fr auto; gap: .5rem 1.2rem; align-items: center }
[data-fe-site] .zikr .zar { font-family: var(--fe-font-arabic); direction: rtl; text-align: right; font-size: 1.4rem; line-height: 1.85; color: #F2F4F8 }
[data-fe-site] .zikr .zur { grid-column: 1 / -1; font-family: var(--fe-font-urdu); direction: rtl; text-align: right; font-size: .93rem; line-height: 2.3; color: rgba(232, 235, 242, .82) }
[data-fe-site] .zikr .zct { font-family: var(--font-mono); color: var(--accent); font-size: .9rem; white-space: nowrap; border: 1px solid var(--border-ink); border-radius: 999px; padding: .25rem .7rem }

/* The whiteboard mock on the App page — a still picture of a feature that does
   not exist yet, so nothing in it is interactive and .wb-play is decorative. */
[data-fe-site] .wb-mock { background: var(--surface-ink); border: 1px solid var(--border-ink); border-radius: var(--r-lg); overflow: hidden; color: var(--fg-on-ink); margin-top: 2rem }
[data-fe-site] .wb-bar { display: flex; align-items: center; gap: .6rem; padding: .7rem 1rem; border-bottom: 1px solid var(--border-ink); flex-wrap: wrap }
[data-fe-site] .wb-dot { width: 9px; height: 9px; border-radius: 50%; flex: none }
/* The three window dots. The mock draws them with per-element inline styles; these
   are the same three colours as classes, because InlineStyleGuardrailTests forbids
   the attribute that would carry them in .razor markup (L22). */
[data-fe-site] .wb-dot-a { background: var(--negative) }
[data-fe-site] .wb-dot-b { background: var(--accent-2) }
[data-fe-site] .wb-dot-c { background: var(--accent) }
[data-fe-site] .wb-title { font-family: var(--font-mono); font-size: .7rem; letter-spacing: .08em; color: var(--muted-on-ink); text-transform: uppercase }
[data-fe-site] .wb-title:lang(ur){ font-family: var(--fe-font-urdu); letter-spacing: 0; text-transform: none; font-size: .85rem }
[data-fe-site] .wb-canvas { padding: clamp(1.2rem, 3vw, 2rem); min-height: 250px; background-image: radial-gradient(circle, rgba(255, 255, 255, .06) 1px, transparent 1px); background-size: 24px 24px }
/* ISOLATED, NOT dir="ltr" ON THE CANVAS. Each line is algebra and has to READ
   left-to-right, but the block it sits in should sit on the reader's side: the mocks put no
   dir on .wb-canvas, so on the Urdu site the drawing right-aligns like everything around it.
   Forcing direction on the canvas pinned the whole drawing to the left instead.
   Isolation gives the equation its own bidi context, so it orders correctly either way. */
[data-fe-site] .wb-line { font-family: var(--font-mono); font-size: 1.02rem; margin-bottom: .85rem; color: #F2F4F8; unicode-bidi: isolate }
[data-fe-site] .wb-line.dim { opacity: .4 }
[data-fe-site] .wb-line .hl { color: var(--accent) }
[data-fe-site] .wb-ink { color: var(--accent-2); font-family: var(--fe-font-arabic); direction: rtl; font-size: 1.2rem }
[data-fe-site] .wb-foot { display: flex; align-items: center; gap: .9rem; padding: .8rem 1rem; border-top: 1px solid var(--border-ink); flex-wrap: wrap }
[data-fe-site] .wb-play { width: 34px; height: 34px; border-radius: 50%; background: var(--accent); color: var(--on-accent); border: 0; display: grid; place-items: center; flex: none; font-size: .8rem }
[data-fe-site] .wb-track { flex: 1 1 120px; height: 3px; background: rgba(255, 255, 255, .16); border-radius: 999px; overflow: hidden }
[data-fe-site] .wb-track i { display: block; height: 100%; width: 38%; background: var(--accent); border-radius: 999px }
[data-fe-site] .wb-time { font-family: var(--font-mono); font-size: .72rem; color: var(--muted-on-ink) }
[data-fe-site] .wb-lang { display: flex; gap: .3rem }
[data-fe-site] .wb-lang span { border: 1px solid var(--border-ink); border-radius: var(--r-sm); padding: .2rem .55rem; font-size: .7rem; font-family: var(--font-mono); color: var(--muted-on-ink) }
[data-fe-site] .wb-lang span.on { background: var(--accent-2); border-color: var(--accent-2); color: #14082E }

/* The roadmap on the App page. Same row grammar as .ch-row — a mono index, a
   title block, a status pill — because it is the same idea: a list of things in
   order, each with a state. */
[data-fe-site] .roadmap { display: grid; gap: 1px; background: var(--border); border: 1px solid var(--border); border-radius: var(--r-lg); overflow: hidden; margin-top: 2rem }
[data-fe-site] .rm-row { background: var(--surface); padding: 1.1rem 1.2rem; display: grid; grid-template-columns: auto minmax(0, 1fr) auto; gap: .5rem 1.1rem; align-items: center }
[data-fe-site] .rm-row .rm-n { font-family: var(--font-mono); color: var(--accent); font-size: .9rem; width: 2ch }
[data-fe-site] .rm-row h3 { font-family: var(--font-display); font-weight: 600; font-size: 1.02rem }
[data-fe-site] .rm-row h3:lang(ur){ font-family: var(--fe-font-urdu) }
[data-fe-site] .rm-row p { color: var(--muted); font-size: .94rem; margin-top: .15rem }

[data-fe-site] .faq-list { margin-top: 2.2rem; border-top: 1px solid var(--border) }
[data-fe-site] .faq-item { border-bottom: 1px solid var(--border); padding-block: 1.3rem }
[data-fe-site] .faq-q { font-family: var(--font-display); font-weight: 600; font-size: var(--step-1); line-height: 1.3 }
[data-fe-site] .faq-q:lang(ur){ font-family: var(--fe-font-urdu); line-height: 1.9 }
[data-fe-site] .faq-a { color: var(--muted); margin-top: .5rem; max-width: 70ch }

/* ═══════════════════════════════════════════════════════════════════════════
   Content pages — crumbs, page head, rails, chapter list, chapter sheet

   This block is the reason the file exists. Before it, the shared visual
   language lived in Home.razor.css, where Blazor scoped it to Home alone, so
   the Find flow, subject pages and chapter sheets each grew their own look.
   These are the classes that make a subject page and a chapter sheet read as
   the same application as the landing page.
   ═══════════════════════════════════════════════════════════════════════════ */

[data-fe-site] .crumbs { display: flex; flex-wrap: wrap; align-items: center; gap: .45rem; color: var(--muted); font-family: var(--font-mono); font-size: .72rem; letter-spacing: .06em; text-transform: uppercase; padding-block: 1.4rem 0 }
[data-fe-site] .crumbs:lang(ur){ font-family: var(--fe-font-urdu); letter-spacing: 0; text-transform: none; font-size: .88rem }
[data-fe-site] .crumbs a { text-decoration: none; transition: color var(--t) }
[data-fe-site] .crumbs a:hover { color: var(--accent) }
[data-fe-site] .crumbs .sep { opacity: .45 }
[data-fe-site] .crumbs [aria-current] { color: var(--fg) }

/* display AND margin ARE HERE TO WIN AN ARGUMENT, not because the design file states them.
   theme.css declares neither — a <header> is already a block and has no margin — but this app
   serves the portal from the same document, and ds/tokens/components.css carries an UNFENCED
   `.page-head { display: flex; align-items: flex-start; justify-content: space-between;
   gap: 16px; margin-bottom: 22px }` for the admin page header, which is a different component
   that happens to share the name.

   A PROPERTY THIS FENCE NEVER MENTIONS IS A PROPERTY THE PORTAL OWNS. Specificity decided
   every declaration the two rules shared, so the padding and the hairline below were always
   this file's — but nothing here said `display`, so the portal's flex was unopposed and the
   heading block laid its children out as COLUMNS. The chapter sheet showed it worst, having
   four: kicker, title, lede and meta row side by side across the page instead of stacked. The
   courses page hid it, having exactly one child (its .fe-wrap), which is why a bug affecting
   every .page-head on the site looked like it affected one screen.

   Restated rather than renamed: the name is the design file's, the markup is the design
   file's, and the portal's rule is the interloper. Fencing it the other way would mean
   renaming a class that appears in the design source, in six .razor files and in this
   stylesheet. */
[data-fe-site] .page-head { display: block; margin: 0; padding-block: clamp(1.8rem, 4vw, 2.8rem) clamp(1.6rem, 3vw, 2.2rem); border-bottom: 1px solid var(--border) }
[data-fe-site] .page-head h1 { font-size: var(--step-3); max-width: 22ch }
[data-fe-site] .page-head .kicker { margin-bottom: .9rem }
[data-fe-site] .page-head .lede { margin-top: 1rem }
[data-fe-site] .page-meta { display: flex; flex-wrap: wrap; gap: .6rem 1.4rem; margin-top: 1.3rem; align-items: center; color: var(--muted); font-size: var(--step--1) }
[data-fe-site] .page-meta .status { margin: 0 }

/* Two-rail reading layout. At 1120px the right rail drops under the sheet; at
   820px both rails unstick and stack, because a sticky rail on a phone eats
   the viewport the reader needs for the text. */
[data-fe-site] .rails { display: grid; grid-template-columns: 250px minmax(0, 1fr) 250px; gap: clamp(1.5rem, 3vw, 2.5rem); align-items: start; padding-block: clamp(2rem, 4vw, 3rem) }
@media (max-width: 1120px) {
  [data-fe-site] .rails { grid-template-columns: 230px minmax(0, 1fr) }
  [data-fe-site] .rail--right { grid-column: 1 / -1 }
}
@media (max-width: 820px) {
  [data-fe-site] .rails { grid-template-columns: 1fr }
  [data-fe-site] .rail { position: static !important }
}
[data-fe-site] .rail { position: sticky; top: 82px; max-height: calc(100vh - 100px); overflow: auto; overscroll-behavior: contain }
[data-fe-site] .rail::-webkit-scrollbar { width: 5px }
[data-fe-site] .rail::-webkit-scrollbar-thumb { background: var(--border-strong); border-radius: 999px }
[data-fe-site] .rail h2,
[data-fe-site] .rail h3 { font-family: var(--font-mono); font-size: .7rem; letter-spacing: .1em; text-transform: uppercase; color: var(--muted); font-weight: 400; margin: 0 0 .8rem }
[data-fe-site] .rail h2:lang(ur),
[data-fe-site] .rail h3:lang(ur) { font-family: var(--fe-font-urdu); letter-spacing: 0; text-transform: none; font-size: .88rem }

[data-fe-site] .toc-search { width: 100%; font: inherit; font-size: .9rem; background: var(--surface); color: var(--fg); border: 1px solid var(--border); border-radius: var(--r-sm); padding: .55rem .7rem; margin-bottom: .9rem; transition: border-color var(--t) }
[data-fe-site] .toc-search:focus { outline: none; border-color: var(--accent) }
[data-fe-site] .toc-group { margin-bottom: 1.3rem }
[data-fe-site] .toc-group > p { color: var(--accent); font-family: var(--font-mono); font-size: .66rem; letter-spacing: .09em; text-transform: uppercase; margin-bottom: .45rem }
[data-fe-site] .toc-group > p:lang(ur){ font-family: var(--fe-font-urdu); letter-spacing: 0; text-transform: none; font-size: .85rem }
[data-fe-site] .toc-link { display: flex; gap: .55rem; text-decoration: none; color: var(--muted); font-size: .89rem; line-height: 1.4; padding: .35rem .5rem; border-radius: var(--r-sm); border-inline-start: 2px solid transparent; transition: all var(--t) }
[data-fe-site] .toc-link .n { font-family: var(--font-mono); font-size: .75rem; opacity: .7; flex: none; padding-top: .12rem }
[data-fe-site] .toc-link:hover { color: var(--fg); background: var(--surface-2) }
[data-fe-site] .toc-link.active { color: var(--accent); border-inline-start-color: var(--accent); background: var(--surface-2) }
[data-fe-site] .toc-link[hidden] { display: none }

[data-fe-site] .side-list { display: grid; gap: 1px; background: var(--border); border: 1px solid var(--border); border-radius: var(--r); overflow: hidden }
[data-fe-site] .side-item { background: var(--surface); padding: .7rem .8rem; text-decoration: none; display: flex; justify-content: space-between; align-items: center; gap: .7rem; font-size: .9rem; transition: background var(--t) }
[data-fe-site] .side-item:hover { background: var(--surface-2) }
[data-fe-site] .side-item[aria-current="page"] { background: var(--surface-2); color: var(--accent); font-weight: 600 }
[data-fe-site] .side-item .status { font-size: .6rem }
[data-fe-site] .side-note { color: var(--muted); font-size: var(--step--1); margin-top: .7rem; line-height: 1.5 }

[data-fe-site] .ch-list { display: grid; gap: 1px; background: var(--border); border: 1px solid var(--border); border-radius: var(--r-lg); overflow: hidden }
[data-fe-site] .ch-row { background: var(--surface); padding: 1.1rem 1.2rem; display: grid; grid-template-columns: auto minmax(0, 1fr) auto; gap: .5rem 1.1rem; align-items: center; text-decoration: none; transition: background var(--t) }
[data-fe-site] .ch-row:hover { background: var(--surface-2) }
[data-fe-site] .ch-row .ch-n { font-family: var(--font-mono); font-size: 1.5rem; color: var(--accent); line-height: 1; width: 2.2ch; text-align: end }
[data-fe-site] .ch-row .ch-t { font-family: var(--font-display); font-weight: 600; font-size: 1.02rem; line-height: 1.3 }
[data-fe-site] .ch-row .ch-t:lang(ur){ font-family: var(--fe-font-urdu); line-height: 1.9 }
[data-fe-site] .ch-row .ch-sub { color: var(--muted); font-size: var(--step--1); margin-top: .15rem }
[data-fe-site] .ch-row .bar { grid-column: 2 / -1; margin-top: .3rem }
[data-fe-site] .ch-row[aria-disabled="true"] { opacity: .55; pointer-events: none }

/* The chapter sheet. scroll-margin-top on .q-card is what keeps a question
   clear of the sticky header when the TOC jumps to it. */
[data-fe-site] .q-section { margin-bottom: clamp(2.2rem, 5vw, 3.2rem) }
[data-fe-site] .q-section > h2 { font-size: var(--step-2); margin-bottom: .4rem }
[data-fe-site] .q-section > .hint { color: var(--muted); font-size: var(--step--1); margin-bottom: 1.4rem }
[data-fe-site] .q-card { background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-lg); overflow: hidden; margin-bottom: 1.1rem; scroll-margin-top: 90px }
[data-fe-site] .q-head { display: flex; flex-wrap: wrap; gap: .5rem 1rem; align-items: center; justify-content: space-between; padding: .75rem 1.1rem; border-bottom: 1px solid var(--border); background: var(--surface-2) }
[data-fe-site] .q-head .qn { font-family: var(--font-mono); font-size: .74rem; letter-spacing: .08em; color: var(--accent); text-transform: uppercase }
[data-fe-site] .q-head .qn:lang(ur){ font-family: var(--fe-font-urdu); letter-spacing: 0; text-transform: none; font-size: .88rem }
[data-fe-site] .q-body { padding: 1.2rem 1.1rem 1.3rem }
[data-fe-site] .q-text { font-weight: 600; font-size: 1.04rem; line-height: 1.5 }
[data-fe-site] .q-text-ur { font-family: var(--fe-font-urdu); direction: rtl; text-align: right; font-size: .98rem; line-height: 2.3; color: var(--muted); margin-top: .5rem }
[data-fe-site] .sol { margin-top: 1.1rem; padding-top: 1.1rem; border-top: 1px solid var(--border) }
[data-fe-site] .sol-label { font-family: var(--font-mono); font-size: .66rem; letter-spacing: .09em; text-transform: uppercase; color: var(--muted); margin-bottom: .7rem }
[data-fe-site] .sol-label:lang(ur){ font-family: var(--fe-font-urdu); letter-spacing: 0; text-transform: none; font-size: .85rem }
[data-fe-site] .sol p { margin-bottom: .7rem; line-height: 1.7 }
[data-fe-site] .sol p:last-child { margin-bottom: 0 }
[data-fe-site] .sol-ur { font-family: var(--fe-font-urdu); direction: rtl; text-align: right; line-height: 2.4; font-size: .97rem; margin-top: .9rem; padding-top: .9rem; border-top: 1px dashed var(--border) }
[data-fe-site] .steps { display: grid; gap: 0; margin-top: .3rem }
[data-fe-site] .step { display: grid; grid-template-columns: 8.5rem minmax(0, 1fr); gap: .9rem; padding-block: .55rem; border-top: 1px solid var(--border) }
[data-fe-site] .step:first-child { border-top: 0 }
@media (max-width: 560px) { [data-fe-site] .step { grid-template-columns: 1fr; gap: .15rem } }
[data-fe-site] .step .k { color: var(--accent); font-family: var(--font-mono); font-size: .68rem; letter-spacing: .08em; text-transform: uppercase; padding-top: .28rem }
[data-fe-site] .step .k:lang(ur){ font-family: var(--fe-font-urdu); letter-spacing: 0; text-transform: none; font-size: .85rem }
[data-fe-site] .step .v { font-family: var(--font-mono); font-size: .95rem }
[data-fe-site] .answer { margin-top: .9rem; padding: .7rem 1rem; background: var(--surface-2); border-radius: var(--r-sm); border-inline-start: 2px solid var(--accent); display: flex; justify-content: space-between; gap: 1rem; align-items: baseline; flex-wrap: wrap }
[data-fe-site] .answer .lbl { font-family: var(--font-mono); font-size: .68rem; letter-spacing: .08em; text-transform: uppercase; color: var(--muted) }
/* KEYED ON THE SHEET'S LANGUAGE — neither the site's nor the content's, and the one
   deliberate exception in this file. Everything else Urdu here is keyed :lang(ur) so that
   an Urdu-only chapter reaches an English reader in Nastaliq. This label is different: its
   text is "Answer" from FeStrings, which follows the CHROME, while the card around it
   carries lang="ur" for its CONTENT. Under :lang(ur) an English "Answer" inside an Urdu
   Mutala card would come out in Nastaliq.

   It used to say html[lang="ur"], which was right for that case and wrong for the other
   one: the chrome is NOT always the site's language. ChapterPage forces Urdu strings on an
   Urdu-only chapter and stamps that on .fe-wrap (SheetLangCode), so on an English site this
   label reads "جواب" — Urdu text that html[lang="ur"] could never match, left in mono. The
   wrapper is what the chrome language is actually written on, so that is what this reads. */
[data-fe-site] .fe-wrap[lang="ur"] .answer .lbl { font-family: var(--fe-font-urdu); letter-spacing: 0; text-transform: none; font-size: .85rem }
[data-fe-site] .answer strong { font-family: var(--font-mono); font-size: 1.1rem; color: var(--accent) }

/* THE MOCK'S ANSWER IS ALWAYS A QUANTITY — "100 m", "2.46 cm" — so it sets the value in
   mono and never has to think about a long one. This library has a second shape the mock
   never shows: a Mutala-e-Quran-e-Hakeem exercise answers in a paragraph of Urdu prose,
   and every one of the 1418 solution files does. Mono has no Nastaliq, so those would
   fall back to whatever the browser had and set a paragraph at 1.1rem on a single
   baseline.

   :lang(ur) rather than html[lang="ur"], and that distinction is load-bearing: the SOLUTION
   MEDIUM is not the site language. An English reader can open an Urdu-only chapter, and
   FeQuestionCard stamps lang on the <article> to say which one this card is actually in.
   :lang() resolves against that, so the answer is set in the script it is written in
   rather than in the script the chrome happens to be in. */
[data-fe-site] .answer strong:lang(ur) {
  font-family: var(--fe-font-urdu);
  font-size: 1rem;
  line-height: 2.3;
  text-align: start;
  /* Its own full-width line, rather than the label's right-hand column. .answer is a
     flex row built for a short quantity sitting opposite its label; a paragraph left
     to flex-wrap on its own would land on line two anyway, but only once it happened
     to be long enough, so a two-line Mutala answer and a ten-line one would sit in
     different places. flex-basis:100% makes the paragraph shape deliberate rather
     than emergent, and align-items:baseline then has nothing to fight over. */
  flex: 1 1 100%;
}

[data-fe-site] .pager { display: grid; grid-template-columns: 1fr 1fr; gap: 1px; background: var(--border); border: 1px solid var(--border); border-radius: var(--r-lg); overflow: hidden; margin-top: clamp(2rem, 4vw, 3rem) }
@media (max-width: 640px) { [data-fe-site] .pager { grid-template-columns: 1fr } }
[data-fe-site] .pager a { background: var(--surface); padding: 1.1rem 1.2rem; text-decoration: none; transition: background var(--t) }
[data-fe-site] .pager a:hover { background: var(--surface-2) }
[data-fe-site] .pager .dir { font-family: var(--font-mono); font-size: .66rem; letter-spacing: .09em; text-transform: uppercase; color: var(--muted) }
[data-fe-site] .pager .dir:lang(ur){ font-family: var(--fe-font-urdu); letter-spacing: 0; text-transform: none; font-size: .85rem }
[data-fe-site] .pager .ttl { font-family: var(--font-display); font-weight: 600; margin-top: .3rem; display: block }
[data-fe-site] .pager .ttl:lang(ur){ font-family: var(--fe-font-urdu) }
[data-fe-site] .pager .next { text-align: end }

[data-fe-site] .search-form { display: flex; gap: .6rem; margin-top: 1.5rem; flex-wrap: wrap }
[data-fe-site] .search-input { flex: 1 1 260px; font: inherit; font-size: 1.02rem; background: var(--surface); color: var(--fg); border: 1px solid var(--border-strong); border-radius: var(--r); padding: .85rem 1rem; transition: border-color var(--t) }
[data-fe-site] .search-input:focus { outline: none; border-color: var(--accent) }
[data-fe-site] .result { display: block; text-decoration: none; padding: 1.2rem 0; border-bottom: 1px solid var(--border) }
[data-fe-site] .result .crumb { color: var(--muted); font-family: var(--font-mono); font-size: .68rem; letter-spacing: .07em; text-transform: uppercase }
[data-fe-site] .result .crumb:lang(ur){ font-family: var(--fe-font-urdu); letter-spacing: 0; text-transform: none; font-size: .85rem }
[data-fe-site] .result h3 { font-family: var(--font-display); font-weight: 600; font-size: var(--step-1); margin-top: .35rem; color: var(--accent) }
[data-fe-site] .result p { color: var(--muted); margin-top: .3rem; max-width: 75ch }

[data-fe-site] .notfound { min-height: 58vh; display: flex; flex-direction: column; justify-content: center; padding-block: 4rem }
[data-fe-site] .notfound .code { font-family: var(--font-mono); font-size: clamp(3.5rem, 12vw, 7rem); line-height: 1; color: var(--accent) }
[data-fe-site] .notfound h1 { font-size: var(--step-3); margin-top: 1rem; max-width: 20ch }
[data-fe-site] .notfound .lede { margin-top: 1rem }
[data-fe-site] .notfound .hero-actions { margin-top: 2rem }

/* ═══════════════════════════════════════════════════════════════════════════
   COURSES · BOARDS · VIDEO · MCQs · THE TWO INTERRUPTIONS

   Everything below is new in docs/free-taleem-new-design/assets/theme.css and
   had no rule here before. Same two transpositions as the rest of the file:
   [data-fe-site] fences it off the portal, and every body.lang-ur becomes
   :lang(ur) so a card carrying its own lang wins over the site's.

   Font families go through the tokens — var(--font-mono), var(--font-display),
   var(--fe-font-urdu), var(--fe-font-arabic) — rather than the literal family
   names the mock writes, because fe-fonts.css is the one place the faces and
   their fallbacks are declared.
   ═══════════════════════════════════════════════════════════════════════════ */

/* -- video-included badge -------------------------------------------------
   Purple, not mint: mint already means "solutions are ready" on every .status
   pill beside it, and a video is a SECOND, independent fact about the same
   chapter. Sharing the colour would read as a stronger version of ready. */
[data-fe-site] .badge-video { display: inline-flex; align-items: center; gap: .4rem; color: var(--accent-2); border: 1px solid currentColor; border-radius: 999px; padding: .16rem .6rem; font-family: var(--font-mono); font-size: .62rem; letter-spacing: .07em; text-transform: uppercase; white-space: nowrap }
[data-fe-site] .badge-video:lang(ur) { font-family: var(--fe-font-urdu); letter-spacing: 0; text-transform: none; font-size: .8rem; padding: .2rem .65rem .3rem }
/* aria-hidden is not available on a pseudo-element, so the glyph must be one a
   screen reader skips rather than announces. The triangle is punctuation to
   every engine tested; the WORD is in the badge's own text beside it. */
[data-fe-site] .badge-video::before { content: "\25B6"; font-size: .5rem; line-height: 1 }

/* -- subject card, selectable --------------------------------------------
   The subject grid existed as a list of LINKS (the wizard's step 3). The
   courses page uses the same cell as a TOGGLE that opens a chapter list below
   it, so the card gains a pressed state and a button reset. Both shapes share
   every other rule, which is the point of putting this here rather than in
   Courses.razor.css. */
[data-fe-site] .subj-card .meta { display: flex; gap: .45rem .6rem; align-items: center; flex-wrap: wrap; margin-top: .55rem; color: var(--muted); font-size: var(--step--1) }
[data-fe-site] .subj-card[aria-pressed="true"] { background: var(--surface-ink); color: var(--fg-on-ink) }
[data-fe-site] .subj-card[aria-pressed="true"] .meta { color: var(--muted-on-ink) }
[data-fe-site] .subj-card[aria-pressed="true"] .bar { background: rgba(255, 255, 255, .16) }
[data-fe-site] button.subj-card { border: 0; font: inherit; text-align: start; cursor: pointer; width: 100%; color: inherit }

/* -- class card: the video badge and the pill under it ---------------------
   The design file writes both of these inline on the card
   (style="display:flex;margin-top:.55rem" and style="margin-top:.6rem"),
   because .class-card's children are otherwise bare spans with no spacing of
   their own. They are here rather than in Home.razor.css: the same cell is
   the courses page's class tab neighbour and the find flow's class grid, and
   a rule the design system owns cannot be scoped to one page's stylesheet. */
[data-fe-site] .class-card .meta { display: flex; margin-top: .55rem }
[data-fe-site] .class-card .status { margin-top: .6rem }
/* The card turns to ink on hover and the badge's purple has to come with it,
   or it is the one element left reading against the old ground. */
[data-fe-site] .class-card:hover .badge-video,
[data-fe-site] .class-card:focus-visible .badge-video { color: var(--accent-2) }

/* -- class tabs (courses page) -------------------------------------------- */
[data-fe-site] .class-tabs { display: flex; gap: .6rem; flex-wrap: wrap; margin-top: 1.6rem }
[data-fe-site] .class-tab { display: flex; align-items: center; gap: .65rem; background: var(--surface); border: 1px solid var(--border); border-radius: var(--r); padding: .55rem 1.1rem; cursor: pointer; font: inherit; font-weight: 600; transition: background var(--t), border-color var(--t), color var(--t) }
[data-fe-site] .class-tab .n { font-family: var(--font-mono); font-size: 1.25rem; color: var(--accent); font-weight: 500 }
[data-fe-site] .class-tab:hover { border-color: var(--accent) }
[data-fe-site] .class-tab[aria-pressed="true"] { background: var(--surface-ink); border-color: var(--surface-ink); color: var(--fg-on-ink) }

/* -- boards we cover (home, and step one of /notes) ------------------------
   NOT .board-chip. The chip is a FILTER — one of thirty, pressed to narrow a
   grid. This is a REGION card: one per province-level textbook authority, and
   nothing is pressed. Two components because they answer different questions,
   not one component with a size variant.

   A LINK ON /notes AND NOT ONE ON THE HOME PAGE, which is why the anchor
   reset below is on a.board-card rather than on the card itself. The home
   page's section states coverage and its hover is the card acknowledging the
   pointer; /notes draws the same six cards as its first step, where each one
   IS a destination — the region's classes.

   FIVE COLUMNS, SO THE SIXTH CARD SITS UNDER THE FIRST. That arrangement is
   the design file's own rendering and is the one asked for: PCTB · FBISE ·
   STBB · KPTBB · BTBB across the top, AJK BISE alone beneath PCTB.

   IT IS PINNED RATHER THAN LEFT TO auto-fit, and that is the whole fix. The
   file writes:

     grid-template-columns: repeat(auto-fit, minmax(200px, 1fr))

   auto-fit takes as many columns as FIT, so the count moves with the viewport
   and with the reader's zoom: five at around 1100-1200px, six a little wider,
   seven wider still. The file happens to be read at a width where that lands
   on five, which is what its screenshots show — but nothing holds it there,
   and the panel silently rearranges itself between one screen and the next.
   Pinning the count is what makes the arrangement the same everywhere.

   THE LADDER BELOW STEPS 5 · 3 · 2 · 1 and nothing else about the panel moves:
   same 1px hairlines, same border, same radius, same equal column widths the
   file has, and each card stays above the ~200px floor its minmax sets. The
   four cells beside AJK BISE are empty, and empty is not blank — the hairlines
   here are the GAPS letting the container's --border through, so that run
   carries the panel's own fill, exactly as the file renders it. */
[data-fe-site] .board-cards { display: grid; grid-template-columns: 1fr; gap: 1px; background: var(--border); border: 1px solid var(--border); border-radius: var(--r-lg); overflow: hidden }
@media (min-width: 460px) { [data-fe-site] .board-cards { grid-template-columns: repeat(2, 1fr) } }
@media (min-width: 720px) { [data-fe-site] .board-cards { grid-template-columns: repeat(3, 1fr) } }
@media (min-width: 1040px) { [data-fe-site] .board-cards { grid-template-columns: repeat(5, 1fr) } }
[data-fe-site] .board-card { background: var(--surface); padding: 1.3rem 1.2rem; transition: background var(--t) }
[data-fe-site] a.board-card { text-decoration: none; color: inherit; display: block }
[data-fe-site] a.board-card:focus-visible { background: var(--surface-2) }
[data-fe-site] .board-card .status { margin-top: .7rem }
[data-fe-site] .board-card:hover { background: var(--surface-2) }
[data-fe-site] .board-card .code { font-family: var(--font-mono); color: var(--accent); font-size: .76rem; letter-spacing: .07em }
[data-fe-site] .board-card h3 { font-family: var(--font-display); font-weight: 600; font-size: 1.04rem; margin-top: .45rem }
[data-fe-site] .board-card h3:lang(ur) { font-family: var(--fe-font-urdu) }
[data-fe-site] .board-card p { color: var(--muted); font-size: .9rem; margin-top: .25rem }

/* -- video frame (chapter sheet) ------------------------------------------
   The stage is an aspect-ratio box, so the poster area holds its shape before
   anything loads into it and the questions below never jump. */
[data-fe-site] .video-frame { background: var(--surface-ink); border: 1px solid var(--border-ink); border-radius: var(--r-lg); overflow: hidden; color: var(--fg-on-ink) }
[data-fe-site] .video-stage { position: relative; aspect-ratio: 16 / 9; display: grid; place-items: center; background: radial-gradient(circle at 30% 20%, rgba(167, 139, 250, .18), transparent 55%), radial-gradient(circle at 75% 80%, rgba(46, 212, 165, .14), transparent 50%), var(--surface-ink) }
[data-fe-site] .video-stage > iframe,
[data-fe-site] .video-stage > video { width: 100%; height: 100%; border: 0; display: block }
[data-fe-site] .video-stage .frame-note { position: absolute; inset-inline-start: 1rem; top: .9rem; font-family: var(--font-mono); font-size: .68rem; letter-spacing: .08em; text-transform: uppercase; color: var(--muted-on-ink) }
[data-fe-site] .video-stage .frame-note:lang(ur) { font-family: var(--fe-font-urdu); letter-spacing: 0; text-transform: none; font-size: .85rem }
[data-fe-site] .video-big-play { width: 66px; height: 66px; border-radius: 50%; background: var(--accent); color: var(--on-accent); border: 0; display: grid; place-items: center; font-size: 1.25rem; cursor: pointer; transition: transform var(--t) }
[data-fe-site] .video-big-play:hover { transform: scale(1.06) }
[data-fe-site] .video-caption { position: absolute; bottom: 1rem; inset-inline: 1rem; text-align: center; color: rgba(232, 235, 242, .75); font-size: .92rem }
[data-fe-site] .video-meta { display: flex; align-items: center; gap: .9rem; padding: .75rem 1rem; border-top: 1px solid var(--border-ink); flex-wrap: wrap }
[data-fe-site] .video-meta .wb-time { margin-inline-start: auto }

/* -- MCQs -----------------------------------------------------------------
   .is-right / .is-wrong carry !important because they must beat .mcq-opt:hover,
   which is a later rule of equal specificity and would repaint a just-answered
   option the moment the pointer stayed on it. The mock writes it the same way. */
[data-fe-site] .mcq { background: var(--surface); border: 1px solid var(--border); border-radius: var(--r-lg); overflow: hidden; margin-bottom: 1rem; scroll-margin-top: 90px }
[data-fe-site] .mcq-q { display: flex; gap: .7rem; align-items: baseline; padding: 1rem 1.1rem; border-bottom: 1px solid var(--border); background: var(--surface-2) }
[data-fe-site] .mcq-q .n { font-family: var(--font-mono); color: var(--accent); font-size: .8rem; flex: none }
[data-fe-site] .mcq-q .t { font-weight: 600 }
[data-fe-site] .mcq-q .t-ur { display: block; font-family: var(--fe-font-urdu); direction: rtl; text-align: right; font-weight: 400; font-size: .92rem; line-height: 2.2; color: var(--muted); margin-top: .3rem }
[data-fe-site] .mcq-opts { display: grid; grid-template-columns: 1fr 1fr; gap: 1px; background: var(--border) }
@media (max-width: 620px) { [data-fe-site] .mcq-opts { grid-template-columns: 1fr } }
[data-fe-site] .mcq-opt { background: var(--surface); border: 0; font: inherit; text-align: start; color: inherit; cursor: pointer; padding: .85rem 1.1rem; display: flex; gap: .65rem; align-items: baseline; transition: background var(--t) }
[data-fe-site] .mcq-opt .key { font-family: var(--font-mono); font-size: .72rem; color: var(--muted); flex: none }
[data-fe-site] .mcq-opt:hover { background: var(--surface-2) }
[data-fe-site] .mcq.answered .mcq-opt { cursor: default }
[data-fe-site] .mcq.answered .mcq-opt:hover { background: var(--surface) }
[data-fe-site] .mcq-opt.is-right { background: rgba(46, 212, 165, .14) !important; color: var(--accent); font-weight: 600 }
[data-fe-site] .mcq-opt.is-wrong { background: rgba(255, 107, 107, .13) !important; color: var(--negative) }
[data-fe-site] .mcq-exp { display: none; padding: .85rem 1.1rem; border-top: 1px solid var(--border); color: var(--muted); font-size: .94rem; line-height: 1.65 }
[data-fe-site] .mcq.answered .mcq-exp { display: block }
[data-fe-site] .mcq-exp .ur { font-family: var(--fe-font-urdu); direction: rtl; text-align: right; line-height: 2.2; margin-top: .4rem }
[data-fe-site] .mcq-score { display: flex; align-items: center; gap: 1rem; flex-wrap: wrap; margin-top: 1.2rem; padding: 1rem 1.1rem; background: var(--surface-2); border: 1px solid var(--border); border-radius: var(--r-lg) }
[data-fe-site] .mcq-score .num { font-size: 1.3rem; color: var(--accent) }

/* -- two-rail variant -----------------------------------------------------
   The chapter sheet has a left rail of questions and no right rail once the
   video frame carries what the right one used to. Overrides .rails' three
   columns; the 1120px breakpoint under .rails does not apply because this is
   already two columns, so only the 820px stack is repeated. */
[data-fe-site] .rails--two { grid-template-columns: 260px minmax(0, 1fr) }
@media (max-width: 820px) { [data-fe-site] .rails--two { grid-template-columns: 1fr } }

/* -- chapter-start strip — visible, never blocks --------------------------
   Fixed to the bottom and translated fully off-screen, NOT display:none, so
   the transform animates in both directions. pointer-events:none on the
   wrapper and auto on the card is what keeps the off-screen strip from
   swallowing clicks along the bottom edge of the page. */
[data-fe-site] .chapter-strip { position: fixed; inset-inline: 0; bottom: 0; z-index: 40; transform: translateY(105%); transition: transform .3s cubic-bezier(.22, .8, .3, 1); pointer-events: none }
[data-fe-site] .chapter-strip.show { transform: none }
[data-fe-site] .cs-in { pointer-events: auto; max-width: var(--max); margin-inline: auto; margin-bottom: clamp(.6rem, 2vw, 1.2rem); background: var(--surface-ink); border: 1px solid var(--border-ink); border-inline-start: 3px solid var(--accent); border-radius: var(--r-lg); color: var(--fg-on-ink); padding: 1rem 1.1rem; display: grid; grid-template-columns: 1fr auto; gap: 1rem; align-items: start }
@media (max-width: 860px) { [data-fe-site] .cs-in { margin-inline: .7rem } }
[data-fe-site] .cs-kicker { color: var(--accent); font-family: var(--font-mono); font-size: .67rem; letter-spacing: .09em; text-transform: uppercase }
[data-fe-site] .cs-kicker:lang(ur) { font-family: var(--fe-font-urdu); letter-spacing: 0; text-transform: none; font-size: .85rem }
[data-fe-site] .cs-ar { font-family: var(--fe-font-arabic); direction: rtl; text-align: right; font-size: 1.28rem; line-height: 1.9; color: #F2F4F8; margin-top: .4rem }
[data-fe-site] .cs-tr { color: rgba(232, 235, 242, .8); font-size: .9rem; margin-top: .35rem }
[data-fe-site] .cs-tr.ur { font-family: var(--fe-font-urdu); direction: rtl; text-align: right; line-height: 2.3 }
[data-fe-site] .cs-ref { color: var(--accent-2); font-family: var(--font-mono); font-size: .67rem; letter-spacing: .08em; margin-top: .5rem }
[data-fe-site] .cs-close { background: none; border: 1px solid var(--border-ink); color: var(--muted-on-ink); cursor: pointer; width: 30px; height: 30px; line-height: 1; border-radius: var(--r-sm); font-size: 1rem; flex: none; transition: border-color var(--t), color var(--t) }
[data-fe-site] .cs-close:hover { border-color: var(--accent); color: var(--accent) }
[data-fe-site] .cs-timer { grid-column: 1 / -1; height: 2px; background: rgba(255, 255, 255, .14); border-radius: 999px; margin-top: .7rem; overflow: hidden }
/* THE DRAIN, WHICH WAS NEVER PORTED. The design file paints this bar in script: it sets
   scaleX(1) with transitions off, then on the next frame turns on a 14s linear transition and
   sets scaleX(0). Only the static bar came across, so it sat full-width for fourteen seconds
   and vanished with the card — the one element on it whose whole job is to show time passing.

   A KEYFRAME, NOT A TRANSITION, because a transition needs a state change to fire and this
   element has none: Blazor inserts it when the strip opens and removes it when the strip
   closes. An animation runs on insertion, which is exactly the moment the C# timer starts.

   THE DURATION COMES FROM THE COMPONENT so the bar cannot drift from the dismissal it is
   counting down to — FeChapterStrip passes its own Milliseconds in as --cs-dur, which is the
   sanctioned inline form (a custom property, never a declaration). The 14s fallback is the
   design file's own value, for any caller that does not set it.

   Under prefers-reduced-motion the block above collapses this to .001ms and `forwards` holds
   it at scaleX(0) — an empty bar, immediately. That is what the design file does too: it sets
   transition:none and assigns scaleX(0), which snaps. The card still stays its full fourteen
   seconds, because the dismissal is a timer and not an animation end. */
@keyframes fe-cs-drain { from { transform: scaleX(1) } to { transform: scaleX(0) } }

[data-fe-site] .cs-timer i { display: block; height: 100%; background: var(--accent); width: 100%; transform-origin: left; animation: fe-cs-drain var(--cs-dur, 14s) linear forwards }
/* The bar drains toward the side the reader reads FROM, so in Urdu it must
   drain from the right. html[dir] is stamped by App.razor for FreeEdu paths. */
html[data-fe-site][dir="rtl"] .cs-timer i { transform-origin: right }

/* -- download wait — the one thing that blocks ----------------------------
   visibility, not display, alongside opacity: a display swap cannot transition,
   and opacity alone would leave an invisible overlay catching every click on
   the page underneath it. */
[data-fe-site] .dl-overlay { position: fixed; inset: 0; z-index: 60; background: rgba(11, 15, 30, .82); backdrop-filter: blur(6px); display: flex; align-items: center; justify-content: center; padding: 1.2rem; opacity: 0; visibility: hidden; transition: opacity var(--t), visibility var(--t) }
[data-fe-site] .dl-overlay.show { opacity: 1; visibility: visible }
[data-fe-site] .dl-card { background: var(--surface-ink); border: 1px solid var(--border-ink); border-radius: var(--r-lg); max-width: 620px; width: 100%; color: var(--fg-on-ink); padding: clamp(1.5rem, 4vw, 2.2rem); position: relative; max-height: 88vh; overflow: auto }
[data-fe-site] .dl-top { display: flex; justify-content: space-between; gap: 1rem; align-items: baseline; flex-wrap: wrap }
[data-fe-site] .dl-top .mono { color: var(--accent) }
[data-fe-site] .dl-file { color: var(--muted-on-ink); font-family: var(--font-mono); font-size: .78rem }
/* .dl-bar, .dl-fill and .dl-pct WERE HERE — the track, its fill and the "4 of 6 downloads
   today" line beneath. They drew the daily download allowance, which has been removed: every
   press produces a file now, so there is no quantity to picture. The rules go with the markup
   rather than waiting here for a caller, and --bar-pct is still live on .bar i, which is the
   coverage meter and has nothing to do with downloads. */
[data-fe-site] .dl-scripture { margin-top: 1.7rem; padding-top: 1.5rem; border-top: 1px solid var(--border-ink) }
/* The dialog's two INLINE styles, transposed. The design file writes the label's purple
   and the ayah's top margin as style="" attributes on the markup; a hardcoded style
   attribute is exactly what the re-skin doctrine forbids (README "Re-skin point"), and
   the .dl-* family already lives here, so they land here with the rest of it. */
[data-fe-site] .dl-scripture .mono { color: var(--accent-2) }
[data-fe-site] .dl-scripture .ayah { font-size: clamp(1.4rem, 3.4vw, 1.9rem); margin-top: .8rem }
[data-fe-site] .dl-actions { margin-top: 1.7rem; display: flex; gap: .7rem; flex-wrap: wrap; align-items: center }
/* THE SAME BOX AS .btn, WHICH IT STANDS BESIDE. The design file gives this .75rem/1.25rem
   and .95rem against .btn's .8rem/1.4rem and .98rem, so Save came out a little taller and
   wider than Cancel with slightly larger type — two buttons in one row that do not agree
   about how big a button is. The metrics are taken from .btn and only the TREATMENT stays
   its own: transparent ground, hairline border, ink-surface foreground.
   inline-flex + align-items:center for the same reason — .btn centres its label that way,
   and a default inline-block button centres text on a different rule, so without it the two
   labels sit a pixel apart on a row that aligns them. */
[data-fe-site] .dl-ghost { display: inline-flex; align-items: center; background: transparent; border: 1px solid var(--border-ink); color: var(--fg-on-ink); padding: .8rem 1.4rem; border-radius: var(--r); cursor: pointer; font-family: var(--font-sans); font-weight: 600; font-size: .98rem; transition: border-color var(--t), color var(--t) }
[data-fe-site] .dl-ghost:lang(ur) { font-family: var(--fe-font-urdu) }
[data-fe-site] .dl-ghost:hover { border-color: var(--accent); color: var(--accent) }
[data-fe-site] .dl-hint { color: var(--muted-on-ink); font-size: var(--step--1) }
