/* ==========================================================================
   Ramadan Strivers v8 — app.css (foundation)
   "Pine" design system (see DESIGN.md): soft light pages, one glowing dark pine hero object per screen,
   mint/emerald accent used sparingly, Manrope with tabular figures, thin line icons.
   Sections: 1 tokens · 2 base · 3 layout & shell · 4 topbar · 5 bottom nav · 6 hero object · 7 cards & lists ·
             8 metrics · 9 ring · 10 buttons & CTA · 11 controls (toggle, seg, chips, fields, check) ·
             12 feedback (empty, bar, grade, ref) · 13 charts · 14 sheet, dialog, toast · 15 utilities and bidi
             for shared text · 16 styleguide · 17 motion · 18 focus (component overrides)
   Rules: logical properties only (RTL-safe), 44px touch targets, no emoji/gold/gradient text, no shadows on
   ordinary cards. Module CSS (tracker/learn/prep/cloud.css) builds on these classes and tokens.
   ========================================================================== */

/* 1. TOKENS --------------------------------------------------------------- */
:root {
  color-scheme: light;
  --paper: #F2F5F3;
  --card: #FFFFFF;
  --card-2: #F7F9F8;
  --raise: #FFFFFF;                 /* selected segment, raised chips */
  --ink: #101915;
  --ink-2: #45524C;
  --ink-3: #5F6C66;
  --hairline: rgba(16, 25, 21, .09);
  --hairline-2: rgba(16, 25, 21, .16);  /* inputs, secondary buttons */
  --card-edge: transparent;         /* hairline border on cards only in dark mode */
  --accent: #047857;
  --accent-soft: rgba(4, 120, 87, .10);
  --accent-ink: #03684C;            /* accent TEXT on an --accent-soft tint (chips): >= 5.4:1 on every light surface */
  --on-accent: #FFFFFF;
  --danger: #B42318;
  --danger-soft: rgba(180, 35, 24, .08);
  --focus: rgba(4, 120, 87, .35);
  --track: rgba(4, 120, 87, .12);
  --ring-a: #2BA47A;
  --ring-b: #047857;
  --chart-soft: rgba(4, 120, 87, .26);
  --control-line: #7E8C85;          /* toggle-off track, check outline (>= 3:1 on card) */
  --btn-bg: linear-gradient(180deg, #16422F, #0B2219);
  --btn-ink: #FFFFFF;
  --btn-shadow: 0 6px 14px -10px rgba(6, 40, 30, .45);
  --scrim: rgba(7, 18, 13, .44);
  --topbar-bg: rgba(242, 245, 243, .86);

  /* Hero object: identical in both themes */
  --hero-bg: radial-gradient(circle at 88% 0%, rgba(52, 211, 153, .24), transparent 55%),
             linear-gradient(200deg, #143A2D 0%, #0B2219 46%, #06130F 100%);
  --hero-edge: rgba(167, 243, 208, .28);
  --hero-shadow: inset 0 1px 0 rgba(236, 253, 245, .14), 0 24px 48px -24px rgba(6, 95, 70, .55), 0 2px 6px rgba(6, 40, 30, .18);
  --hero-ink: #EEF8F2;
  --hero-ink-2: #B6CEC3;
  --hero-ink-3: #8FB0A2;
  --hero-accent: #6EE7B7;
  --hero-hairline: rgba(167, 243, 208, .20);
  --hero-track: rgba(167, 243, 208, .16);
  --mint: #A7F3D0;
  --mint-ink: #052E22;
  --nav-bg: linear-gradient(180deg, #0E2A20, #0A1F17);
  --nav-ink: #B6CEC3;

  /* Shape, space, type, motion */
  --r-hero: 28px;
  --r-card: 22px;
  --r-block: 16px;
  --r-input: 12px;
  --r-pill: 999px;
  --s1: 4px; --s2: 8px; --s3: 12px; --s4: 16px; --s5: 20px; --s6: 24px; --s7: 32px;
  --gutter: 16px;
  --col: 560px;
  --nav-h: 60px;
  --nav-gap: 12px;
  --font: 'Manrope', 'RS Honorific', ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
  --font-quran: 'Amiri', 'Noto Naskh Arabic', 'Noto Sans Arabic', 'Geeza Pro', serif;
  --track-tight: -.02em;
  --track-wide: .04em;
  /* line-height for text clamped with overflow: hidden (CTA text, an over-long topbar title): the line box must hold
     the script's tallest ink or accents, Arabic dots and Devanagari matras are cut. Measured: Latin with accents 1.29,
     Devanagari 1.31, Bengali 1.29, Urdu 1.57, Arabic 1.71 (set per language below). */
  --lh-clamp: 1.32;
  --ease: cubic-bezier(.2, .8, .2, 1);
  --dur: 200ms;
}

/* Dark tokens: explicit choice, or "system" (no data-theme / data-theme="system") with a dark OS preference */
:root[data-theme="dark"] {
  color-scheme: dark;
  --paper: #070D0A;
  --card: #0F1A15;
  --card-2: #13211B;
  --raise: #1F3329;
  --ink: #EEF8F2;
  --ink-2: #C2D4CB;
  --ink-3: #93A69D;
  --hairline: rgba(238, 248, 242, .09);
  --hairline-2: rgba(238, 248, 242, .17);
  --card-edge: rgba(238, 248, 242, .07);
  --accent: #6EE7B7;
  --accent-soft: rgba(110, 231, 183, .12);
  --accent-ink: #6EE7B7;
  --on-accent: #052E22;
  --danger: #FDA29B;
  --danger-soft: rgba(253, 162, 155, .10);
  --focus: rgba(110, 231, 183, .40);
  --track: rgba(110, 231, 183, .14);
  --ring-a: #ECFDF5;
  --ring-b: #6EE7B7;
  --chart-soft: rgba(110, 231, 183, .28);
  --control-line: #6E8379;
  --btn-bg: #A7F3D0;
  --btn-ink: #052E22;
  --btn-shadow: 0 0 0 0 transparent;
  --scrim: rgba(0, 0, 0, .62);
  --topbar-bg: rgba(7, 13, 10, .84);
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;
    --paper: #070D0A;
    --card: #0F1A15;
    --card-2: #13211B;
    --raise: #1F3329;
    --ink: #EEF8F2;
    --ink-2: #C2D4CB;
    --ink-3: #93A69D;
    --hairline: rgba(238, 248, 242, .09);
    --hairline-2: rgba(238, 248, 242, .17);
    --card-edge: rgba(238, 248, 242, .07);
    --accent: #6EE7B7;
    --accent-soft: rgba(110, 231, 183, .12);
    --accent-ink: #6EE7B7;
    --on-accent: #052E22;
    --danger: #FDA29B;
    --danger-soft: rgba(253, 162, 155, .10);
    --focus: rgba(110, 231, 183, .40);
    --track: rgba(110, 231, 183, .14);
    --ring-a: #ECFDF5;
    --ring-b: #6EE7B7;
    --chart-soft: rgba(110, 231, 183, .28);
    --control-line: #6E8379;
    --btn-bg: #A7F3D0;
    --btn-ink: #052E22;
    --btn-shadow: 0 0 0 0 transparent;   /* never 'none': focus styles append to it */
    --scrim: rgba(0, 0, 0, .62);
    --topbar-bg: rgba(7, 13, 10, .84);
  }
}

/* Honorifics ﷺ (U+FDFA), ﷻ (U+FDFB) and ﷲ (U+FDF2) appear in English and translated text; Manrope and most system
   fonts lack them (some devices draw a bitmap blob). 'RS Honorific' is a 3-glyph subset of Noto Naskh Arabic
   (OFL 1.1, vendor/honorific-OFL.txt), downloaded only on pages that contain one of these characters. One face
   covers every weight (no faux bold on the calligraphy); size-adjust matches it to Manrope's cap height. */
@font-face {
  font-family: 'RS Honorific';
  src: url(../vendor/honorific.woff2) format('woff2');
  unicode-range: U+FDF2, U+FDFA, U+FDFB;
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
  size-adjust: 120%;
}

/* Script fallbacks (Manrope first so Latin digits stay tabular Manrope) */
html:lang(ar), html:lang(ur) { --font: 'Manrope', 'RS Honorific', 'Noto Sans Arabic', 'Geeza Pro', 'Segoe UI', system-ui, sans-serif; --lh-clamp: 1.75; }
html:lang(bn) { --font: 'Manrope', 'RS Honorific', 'Noto Sans Bengali', 'Vrinda', system-ui, sans-serif; --lh-clamp: 1.35; }
html:lang(hi) { --font: 'Manrope', 'RS Honorific', 'Noto Sans Devanagari', 'Mangal', system-ui, sans-serif; --lh-clamp: 1.35; }
html:lang(zh) { --font: 'Manrope', 'RS Honorific', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'Noto Sans SC', 'Noto Sans CJK SC', system-ui, sans-serif; }
/* Tracking breaks cursive joining (Arabic) and conjuncts/CJK rhythm: keep letter-spacing only for Latin/Cyrillic */
html:lang(ar), html:lang(ur), html:lang(bn), html:lang(hi), html:lang(zh) { --track-tight: 0; --track-wide: 0; }
html:lang(ar) *, html:lang(ur) *, html:lang(bn) *, html:lang(hi) *, html:lang(zh) * { letter-spacing: 0 !important; }
/* … except the display numerals, which are always Latin digits (RS.fmt): same tight figure in every language */
:is(html:lang(ar), html:lang(ur), html:lang(bn), html:lang(hi), html:lang(zh)) :is(.hero-num .num, .display) { letter-spacing: -.04em !important; }

/* 2. BASE ----------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }
html {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  background: var(--paper);
  /* Keep focused controls clear of the sticky topbar and the floating nav when the browser scrolls them into view
     (WCAG 2.4.11). main.js/core.js put .no-nav on <html> on screens without the nav. --topbar-pad is the measured
     topbar height + 12px (core.js; the title may wrap to two lines); the fallback fits a one-line title. */
  scroll-padding-top: var(--topbar-pad, calc(72px + env(safe-area-inset-top)));
  scroll-padding-bottom: calc(var(--nav-h) + var(--nav-gap) + 24px + env(safe-area-inset-bottom));
}
html.no-nav { scroll-padding-bottom: calc(24px + env(safe-area-inset-bottom)); }
body {
  margin: 0;
  min-height: 100vh;
  min-height: 100dvh;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font);
  font-size: 16px;
  font-weight: 400;
  line-height: 1.5;
  font-variant-numeric: tabular-nums;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  -webkit-tap-highlight-color: transparent;
  /* clip, not hidden: hidden would turn <body> into a scroll container whenever <html> is not overflow: visible
     (the scroll lock below), and the sticky topbar would then stick to <body> and scroll away with the page */
  overflow-x: clip;
}
@supports not (overflow-x: clip) {
  body { overflow-x: hidden; }
  html.is-locked body { overflow: visible; }      /* older engines: keep <body> from becoming the scroller while locked */
}
h1, h2, h3, h4, p, dl, dd, figure, blockquote { margin: 0; }
h1, h2, h3, h4 { font-weight: 700; letter-spacing: var(--track-tight); line-height: 1.25; }
ul, ol { margin: 0; padding: 0; list-style: none; }
button, input, select, textarea { font: inherit; color: inherit; letter-spacing: inherit; }
button { margin: 0; padding: 0; border: 0; background: none; cursor: pointer; text-align: inherit; }
button:disabled { cursor: not-allowed; }
a { color: var(--accent); text-decoration-thickness: 1px; text-underline-offset: 3px; }
img, video { max-width: 100%; height: auto; display: block; }
svg { overflow: visible; }
[hidden] { display: none !important; }
::selection { background: var(--accent-soft); }

/* Focus: a 1px accent line plus a 3px halo (accent at 35%, DESIGN §6). The halo is an outline, so a component's
   own box-shadow can never remove it; components with a shadow re-add the 1px line in section 18. */
:focus { outline: none; }
:focus-visible { outline: 3px solid var(--focus); outline-offset: 1px; box-shadow: 0 0 0 1px var(--accent); }
.hero, .nav, .toast-root { --focus: rgba(110, 231, 183, .55); }
.nav, .toast-root { --accent: var(--hero-accent); }

/* Icons (sprite symbols, see js/icons.js) */
.ic { display: inline-block; flex: none; vertical-align: middle; fill: none; stroke: currentColor; stroke-width: 1.75; stroke-linecap: round; stroke-linejoin: round; }
[dir="rtl"] .ic.flip-rtl { transform: scaleX(-1); }
.sprite { position: absolute; width: 0; height: 0; overflow: hidden; }

/* Quranic and dua text */
.ar-text { font-family: var(--font-quran); font-size: 1.45em; line-height: 2; direction: rtl; text-align: right; font-weight: 400; letter-spacing: 0 !important; }

/* 3. LAYOUT & SHELL --------------------------------------------------------- */
.skip-link { position: absolute; inset-inline-start: 12px; top: -60px; z-index: 100; padding: 10px 16px; border-radius: var(--r-pill); background: var(--card); color: var(--ink); font-weight: 600; text-decoration: none; }
.skip-link:focus-visible { top: calc(8px + env(safe-area-inset-top)); }
.view {
  display: block;
  max-width: var(--col);
  margin-inline: auto;
  padding-top: var(--s1);
  padding-bottom: calc(var(--nav-h) + var(--nav-gap) + 44px + env(safe-area-inset-bottom));
  padding-left: max(var(--gutter), env(safe-area-inset-left));
  padding-right: max(var(--gutter), env(safe-area-inset-right));
  min-height: 60vh;
}
.no-nav .view { padding-bottom: calc(32px + env(safe-area-inset-bottom)); }
.view > * + * { margin-top: var(--s4); }
.view > .sec-hd { margin-top: var(--s6); }
.view > .sec-hd + * { margin-top: var(--s2); }
.boot-msg { padding: 64px 8px; text-align: center; color: var(--ink-3); font-size: 15px; }
/* sheet or dialog open: only the root stops scrolling (see body above); the sticky topbar stays where it was */
html.is-locked { overflow: hidden; }

/* 4. TOPBAR --------------------------------------------------------------- */
.topbar {
  position: sticky;
  top: 0;
  z-index: 30;
  padding-top: env(safe-area-inset-top);
  background: var(--paper);
  background: var(--topbar-bg);
  -webkit-backdrop-filter: saturate(1.4) blur(16px);
  backdrop-filter: saturate(1.4) blur(16px);
  transition: box-shadow var(--dur) var(--ease);
}
.topbar.is-scrolled { box-shadow: 0 1px 0 var(--hairline); }
.topbar-in {
  display: flex;
  align-items: center;
  gap: var(--s1);
  max-width: var(--col);
  min-height: 60px;
  margin-inline: auto;
  padding-block: var(--s2);
  padding-left: max(8px, env(safe-area-inset-left));
  padding-right: max(8px, env(safe-area-inset-right));
}
.topbar-titles { flex: 1 1 auto; min-width: 0; padding-inline: 8px; }
/* Translated titles are often longer than the English ones ("Preparación para el Ramadán" at 320px): title and sub
   wrap instead of being cut, and RS.topbar marks a long title .is-long (a little smaller on narrow screens). A title
   that would need more than two lines (a long competition name) is clamped to two: RS.topbar measures it and adds
   .is-clamped. Only then is it overflow: hidden, with a line box tall enough for its script (--lh-clamp). */
.topbar-sub { display: block; font-size: 12px; font-weight: 600; letter-spacing: var(--track-wide); text-transform: uppercase; color: var(--ink-3); line-height: 1.3; overflow-wrap: anywhere; }
.topbar-title { font-size: 22px; font-weight: 700; letter-spacing: var(--track-tight); line-height: 1.2; overflow-wrap: anywhere; }
.topbar-title.is-long { font-size: clamp(18px, 5.6vw, 22px); line-height: 1.18; }
.topbar-title.is-clamped { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden; line-height: var(--lh-clamp); }
.topbar-title:focus, .topbar-title:focus-visible, .view:focus-visible { outline: none; box-shadow: none; }
.topbar-actions { display: flex; align-items: center; flex: none; }
.icon-btn {
  position: relative;
  flex: none;
  display: inline-grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  color: var(--ink);
  text-decoration: none;
  transition: background-color var(--dur) var(--ease);
}
.icon-btn:active { background: var(--hairline); }
@media (hover: hover) { .icon-btn:hover { background: var(--hairline); } }

/* 5. BOTTOM NAV (floating pine bar, mint active pill) ------------------------ */
.nav {
  position: fixed;
  z-index: 40;
  inset-inline: 0;
  bottom: calc(var(--nav-gap) + env(safe-area-inset-bottom));
  display: flex;
  justify-content: center;
  padding-inline: 12px;
  pointer-events: none;
  transition: transform .25s var(--ease), opacity .2s;
}
.no-nav .nav { transform: translateY(calc(100% + 40px)); opacity: 0; visibility: hidden; }
.nav-bar {
  pointer-events: auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s1);
  width: 100%;
  max-width: 420px;
  min-height: var(--nav-h);
  padding: 6px;
  border-radius: var(--r-pill);
  background: var(--nav-bg);
  border: 1px solid rgba(167, 243, 208, .14);
  box-shadow: inset 0 1px 0 rgba(236, 253, 245, .08), 0 18px 40px -16px rgba(4, 24, 17, .55), 0 2px 8px rgba(4, 24, 17, .18);
}
.nav-item {
  position: relative;
  flex: 1 1 0;
  min-width: 44px;
  height: 48px;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--s2);
  border-radius: var(--r-pill);
  color: var(--nav-ink);
  text-decoration: none;
  font-size: 13.5px;
  font-weight: 700;
  letter-spacing: -.005em;
  transition: background-color var(--dur) var(--ease), color var(--dur) var(--ease);
}
.nav-item .ic { width: 22px; height: 22px; }
/* The active tab is a mint pill with icon + label. The label is never cut with an ellipsis: main.js measures
   every label (per language and width) and marks a tab whose label does not fit .is-iconly (icon only; the link
   keeps its aria-label). */
.nav-label { display: none; white-space: nowrap; overflow: hidden; }
.nav-item.is-active { flex: 0 1 auto; padding-inline: 14px 16px; background: var(--mint); color: var(--mint-ink); }
.nav-item.is-active .nav-label { display: block; min-width: 0; }
.nav-item.is-active.is-iconly { padding-inline: var(--s4); }
.nav-item.is-active.is-iconly .nav-label { display: none; }
.nav.is-measuring .nav-item { transition: none !important; }
@media (hover: hover) { .nav-item:not(.is-active):hover { color: #EEF8F2; background: rgba(236, 253, 245, .06); } }
@media (max-width: 360px) {
  /* 320px: four 44px tabs, and the active pill takes all the remaining width */
  .nav { padding-inline: var(--s2); }
  .nav-bar { padding: var(--s1); gap: 0; }
  .nav-item:not(.is-active) { flex: 0 0 44px; }
  .nav-item.is-active { flex: 1 1 auto; gap: var(--s1); padding-inline: 10px 12px; font-size: 12.5px; }
  .nav-bar:has(> .is-active.is-iconly) > .nav-item { flex: 1 1 0; padding-inline: 0; }   /* icon-only pill: five equal tabs */
}

/* 6. HERO OBJECT ------------------------------------------------------------- */
.hero {
  position: relative;
  isolation: isolate;
  padding: var(--s5);
  border-radius: var(--r-hero);
  background: var(--hero-bg);
  border: 1px solid var(--hero-edge);
  box-shadow: var(--hero-shadow);
  color: var(--hero-ink);
  --accent: var(--hero-accent);
  --accent-soft: rgba(110, 231, 183, .14);
  --accent-ink: var(--hero-accent);
  --hairline: var(--hero-hairline);
  --ink: var(--hero-ink);
  --ink-2: var(--hero-ink-2);
  --ink-3: var(--hero-ink-3);
  --control-line: var(--hero-ink-3);
}
.hero .kicker { color: var(--hero-ink-2); }
.hero .kicker .ic { color: var(--hero-accent); }
.hero-main { display: flex; align-items: center; justify-content: space-between; gap: var(--s4); margin-top: var(--s4); }
.hero-figure { flex: 1 1 auto; min-width: 0; }
/* Long figures (ui.hero: 5+ characters, 4+ with a unit, e.g. 2,140 pts) are set smaller so they stay beside the
   ring at 320px. Last resort: a figure that still does not fit (1,234,567) moves the ring below it. */
.hero-num.is-long .num { font-size: clamp(40px, 12vw, 56px); }
.hero-main.is-long { flex-wrap: wrap; }
.hero-main.is-long > .hero-figure { flex: 1 1 0; min-width: min-content; }
.hero-main.is-long :is(.hero-label, .hero-text) { overflow-wrap: anywhere; }    /* only the figure sets the width */
.hero-num { display: flex; align-items: baseline; flex-wrap: wrap; gap: 2px var(--s2); }
.hero-num.unit-tight { column-gap: 2px; }                       /* 37% · 3/5 read as one figure */
[dir="rtl"] .hero-num.unit-tight { flex-direction: row-reverse; justify-content: flex-end; }   /* still "37%" */
.hero-num .num {
  font-size: clamp(56px, 17vw, 72px);
  font-weight: 300;
  line-height: 1;
  letter-spacing: -.04em;
  color: var(--hero-ink);
  font-variant-numeric: tabular-nums;
  unicode-bidi: plaintext;          /* '+2' / '-3' keep their sign in front in the RTL UI (no strong letter: LTR) */
}
.hero-num .unit { font-size: 20px; font-weight: 400; color: var(--hero-ink-2); letter-spacing: -.01em; }
.hero-label { margin-top: 8px; font-size: 14.5px; font-weight: 500; color: var(--hero-ink-2); line-height: 1.4; }
.hero-text { margin-top: var(--s3); font-size: 15px; color: var(--hero-ink-2); }
.hero .metrics { margin-top: var(--s5); padding-top: var(--s4); border-top: 1px solid var(--hero-hairline); }
.hero-extra { margin-top: var(--s4); }
.hero a:not(.cta) { color: var(--hero-accent); }

/* 7. CARDS, SECTIONS, LISTS --------------------------------------------------- */
.card {
  position: relative;
  padding: var(--s5);
  border-radius: var(--r-card);
  background: var(--card);
  border: 1px solid var(--card-edge);
}
.card-hd { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--s3); margin-bottom: var(--s3); }
.card-hd-txt { min-width: 0; flex: 1 1 auto; }
.card-hd .kicker + .card-title { margin-top: var(--s2); }
.card-title { font-size: 20px; font-weight: 700; letter-spacing: var(--track-tight); line-height: 1.3; color: var(--ink); }
.card-hd > .link-btn { flex: none; margin-block: -14px; margin-inline-end: -8px; }   /* centred on the kicker line */
.card-hd:has(> .card-hd-txt > .card-title:first-child) > .link-btn { margin-block: -9px; }   /* … or on the title line */
.card-bd { font-size: 15px; color: var(--ink-2); }
.card-bd > p + p { margin-top: var(--s2); }
.card.is-flat { background: transparent; border-color: var(--hairline); }
.card.is-tight { padding: 8px 20px; }
.inset { padding: var(--s3) var(--s4); border-radius: var(--r-block); background: var(--card-2); }

.kicker {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: var(--track-wide);
  text-transform: uppercase;
  color: var(--ink-3);
  line-height: 1.3;
}
.kicker .ic { flex: none; color: var(--accent); width: 16px; height: 16px; }
.kicker span { min-width: 0; overflow-wrap: break-word; }

.sec-hd { display: flex; align-items: center; justify-content: space-between; gap: var(--s3); min-height: 44px; padding-inline: 4px; }
.sec-title { font-size: 13px; font-weight: 600; letter-spacing: var(--track-wide); text-transform: uppercase; color: var(--ink-3); }

.link-btn {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  min-height: 44px;
  padding-inline: 8px;
  border-radius: var(--r-input);
  color: var(--accent);
  font-size: 14px;
  font-weight: 650;
  text-decoration: none;
  white-space: nowrap;
}
.link-btn .ic { width: 16px; height: 16px; }
@media (hover: hover) { .link-btn:hover { background: var(--accent-soft); } }

.list { margin: 0; padding: 0; }
.li + .li { border-top: 1px solid var(--hairline); }
.card-bd > .list:first-child { margin-top: -6px; }
.card-bd > .list:last-child { margin-bottom: -8px; }
.row {
  display: flex;
  align-items: center;
  gap: var(--s3);
  width: 100%;
  min-height: 56px;
  padding-block: var(--s3);
  color: var(--ink);
  text-align: start;
  text-decoration: none;
  font-size: 15px;
}
button.row, a.row, .row-main {
  width: calc(100% + 20px);
  margin-inline: -10px;
  padding-inline: 10px;
  border-radius: var(--r-input);
  transition: background-color var(--dur) var(--ease);
}
button.row:active, a.row:active, .row-main:active { background: var(--card-2); }
@media (hover: hover) { button.row:hover, a.row:hover, .row-main:hover { background: var(--card-2); } }
.row-wrap { display: block; padding-block: 0; }
.row-wrap > .row-main { min-height: 56px; }
.row-extra { padding-block: 0 12px; padding-inline-start: 48px; font-size: 13px; color: var(--ink-3); }
.row-wrap.no-lead > .row-extra { padding-inline-start: 0; }
.row-wrap.lead-check > .row-extra { padding-inline-start: 40px; }
.row-extra .link-btn { min-height: 44px; margin-block: -12px; vertical-align: middle; }
.row-extra .ref { vertical-align: middle; }
.row-ic {
  flex: none;
  display: grid;
  place-items: center;
  width: 36px;
  height: 36px;
  border-radius: 12px;
  background: var(--accent-soft);
  color: var(--accent);
}
.row-ic .ic { width: 19px; height: 19px; }
.row-lead { flex: none; display: flex; align-items: center; }
.row-txt { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; }
.row-title { font-size: 15px; font-weight: 600; color: var(--ink); line-height: 1.35; overflow-wrap: break-word; }
.row-sub { margin-top: 2px; font-size: 13px; font-weight: 500; color: var(--ink-3); line-height: 1.4; overflow-wrap: break-word; }
/* plaintext orders a value by its own script; the alignment is physical because plaintext would resolve 'end'
   against the value's direction (an English value in the Arabic UI would then hug the wrong edge when it wraps) */
.row-val { flex: none; max-width: 45%; font-size: 14px; font-weight: 600; color: var(--ink-2); text-align: right; overflow-wrap: break-word; unicode-bidi: plaintext; }
[dir="rtl"] .row-val { text-align: left; }
.row-chev { flex: none; color: var(--ink-3); width: 18px; height: 18px; }
.row.is-done .row-title { color: var(--ink-2); }
.row.is-disabled, .row[aria-disabled="true"] { opacity: .5; }

/* 8. METRICS (label above value, hairline separators) ---------------------------- */
.metrics { display: grid; grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr); margin: 0; }
.metric { display: flex; flex-direction: column; justify-content: space-between; min-width: 0; padding-inline: 12px; border-inline-start: 1px solid var(--hairline); }   /* values share a line when a label wraps */
.metric:first-child { padding-inline-start: 0; border-inline-start: 0; }
.metric:last-child { padding-inline-end: 0; }
.metric dt { font-size: 12px; font-weight: 500; color: var(--ink-3); line-height: 1.3; letter-spacing: .01em; overflow-wrap: break-word; -webkit-hyphens: auto; hyphens: auto; }
/* Values are never clipped or cut with an ellipsis: a value that does not fit wraps (numbers have no break
   opportunity, so they stay on one line unless they would spill into the next column). Words ("English",
   "Year-round", "30 days") are marked .is-text by ui.metrics and set a little smaller than figures. */
.metric dd { margin: 4px 0 0; font-size: clamp(16px, 4.8vw, 20px); font-weight: 600; letter-spacing: var(--track-tight); color: var(--ink); line-height: 1.25; overflow-wrap: anywhere; font-variant-numeric: tabular-nums; }
.metric.is-text dd { font-size: clamp(15px, 4.1vw, 16px); line-height: 1.3; letter-spacing: 0; }
/* plaintext: a value without letters ('+3', '-12%') runs left to right, so its sign stays in front in the RTL UI;
   words keep their own direction. The alignment is physical (see .row-val), so labels and values stay on the UI's side. */
.metric dt, .metric dd { text-align: left; unicode-bidi: plaintext; }
[dir="rtl"] .metric dt, [dir="rtl"] .metric dd { text-align: right; }
.metrics.on-dark .metric { border-color: var(--hero-hairline); }
.metrics.on-dark dt { color: var(--hero-ink-3); }
.metrics.on-dark dd { color: var(--hero-ink); }
@media (max-width: 360px) {
  .metric { padding-inline: 6px; }
  .metrics[data-n="4"] { grid-auto-flow: row; grid-template-columns: repeat(2, minmax(0, 1fr)); row-gap: var(--s3); }
  .metrics[data-n="4"] .metric:nth-child(odd) { padding-inline-start: 0; border-inline-start: 0; }
  .metrics[data-n="4"] .metric:nth-child(even) { padding-inline-end: 0; }
}

/* 9. RING (SVG, gradient stroke, glow halo) ------------------------------------- */
.ring {
  --ring-size: 72px;
  position: relative;
  flex: none;
  display: inline-grid;
  place-items: center;
  width: var(--ring-size);
  height: var(--ring-size);
}
.hero .ring { --ring-size: 108px; }
@media (max-width: 360px) { .hero .ring { --ring-size: 88px; } }
.ring-svg { grid-area: 1 / 1; width: 100%; height: 100%; transform: rotate(-90deg); }
.ring-track { fill: none; stroke: var(--track); }
.ring-bar { fill: none; stroke-linecap: round; transition: stroke-dashoffset .25s var(--ease), stroke-dasharray .25s var(--ease); }
.ring .stop-a { stop-color: var(--ring-a); }
.ring .stop-b { stop-color: var(--ring-b); }
.ring.on-dark .ring-track { stroke: var(--hero-track); }
.ring.on-dark .stop-a { stop-color: #ECFDF5; }
.ring.on-dark .stop-b { stop-color: #6EE7B7; }
.ring.on-dark::before {
  content: '';
  position: absolute;
  inset: 12%;
  z-index: 0;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(110, 231, 183, .35), rgba(110, 231, 183, 0) 70%);
  filter: blur(14px);
  pointer-events: none;
}
.ring.on-dark .ring-svg { filter: drop-shadow(0 0 6px rgba(110, 231, 183, .35)); }
.ring.is-empty::before { opacity: .35; }
.ring-txt { grid-area: 1 / 1; z-index: 1; display: flex; flex-direction: column; align-items: center; text-align: center; line-height: 1.05; max-width: 78%; }
.ring-val { font-size: calc(var(--ring-size) * .22); font-weight: 600; letter-spacing: -.03em; color: var(--ink); unicode-bidi: plaintext; }
/* The sub-label is never cut: it wraps (translations such as "Добрые дела" take two short lines in the 88px ring at
   320px), and ui.ring marks one longer than 9 characters .is-long (a little smaller). No line clamp: a clamp needs
   overflow: hidden, which cut Arabic and Urdu dots in this small line box. Keep ring subs to a word or two. */
.ring-sub {
  max-width: 100%;
  margin-top: 2px;
  overflow-wrap: anywhere;
  -webkit-hyphens: auto;
  hyphens: auto;
  unicode-bidi: plaintext;
  font-size: max(12px, calc(var(--ring-size) * .1));
  font-weight: 600;
  line-height: 1.1;
  letter-spacing: .02em;
  color: var(--ink-3);
}
.ring-sub.is-long { font-size: max(11px, calc(var(--ring-size) * .09)); letter-spacing: 0; }
html:lang(ar) .ring-sub, html:lang(ur) .ring-sub { line-height: 1.35; }   /* two lines: room for dots and hamza */
html:lang(hi) .ring-sub, html:lang(bn) .ring-sub { line-height: 1.25; }
.ring.on-dark .ring-val { color: var(--hero-ink); }
.ring.on-dark .ring-sub { color: var(--hero-ink); }

/* 10. BUTTONS & GLASS CTA ------------------------------------------------------- */
.btn {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: 48px;
  padding: var(--s3) var(--s6);
  border-radius: var(--r-pill);
  border: 1px solid transparent;
  font-size: 15px;
  font-weight: 650;
  line-height: 1.2;
  letter-spacing: -.005em;
  text-align: center;
  text-decoration: none;
  transition: transform .15s var(--ease), background-color var(--dur) var(--ease), border-color var(--dur), opacity var(--dur);
}
.btn .ic { width: 18px; height: 18px; }
.btn:active:not(:disabled):not(.is-disabled) { transform: scale(.98); }
.btn-primary { background: var(--btn-bg); color: var(--btn-ink); box-shadow: var(--btn-shadow); }
.btn-secondary { background: transparent; border-color: var(--hairline-2); color: var(--ink); }
.btn-ghost { background: transparent; color: var(--accent); }
.btn-danger { background: transparent; border-color: var(--hairline-2); color: var(--danger); }
@media (hover: hover) {
  .btn-secondary:hover:not(:disabled):not(.is-disabled), .btn-ghost:hover:not(:disabled):not(.is-disabled) { background: var(--accent-soft); }
  .btn-danger:hover:not(:disabled):not(.is-disabled) { background: var(--danger-soft); }
}
.btn-block { display: flex; width: 100%; }
.btn-sm { min-height: 40px; padding: 8px 16px; font-size: 14px; }
.btn-sm::after { content: ''; position: absolute; inset: -2px 0; }
.btn-row { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s2); }
.btn-row > .btn { flex: 1 1 auto; }
/* Inside the hero the primary pill is mint in both themes */
.hero .btn-primary { background: var(--mint); color: var(--mint-ink); box-shadow: none; }
.hero .btn-secondary { border-color: var(--hero-hairline); color: var(--hero-ink); }
/* Disabled: one neutral style for every variant instead of a faded fill (a faded mint or pine pill reads as a
   mid-green slab, DESIGN §7). Declared after the variants so it wins at equal specificity. */
.btn:disabled, .btn.is-disabled { opacity: 1; background: var(--card-2); border-color: var(--hairline); color: var(--ink-3); box-shadow: none; cursor: not-allowed; }
.hero .btn:disabled, .hero .btn.is-disabled { background: rgba(236, 253, 245, .06); }

.cta {
  display: flex;
  align-items: center;
  gap: var(--s3);
  width: 100%;
  min-height: 62px;
  margin-top: var(--s4);
  padding-block: 9px;
  padding-inline: 18px 9px;
  border-radius: 31px;              /* half the 62px height: a pill on one line, a soft rectangle when the text wraps */
  background: rgba(236, 253, 245, .08);
  border: 1px solid rgba(167, 243, 208, .22);
  -webkit-backdrop-filter: blur(14px);
  backdrop-filter: blur(14px);
  color: var(--hero-ink);
  text-align: start;
  text-decoration: none;
  transition: background-color var(--dur) var(--ease);
}
.cta:active { background: rgba(236, 253, 245, .12); }
@media (hover: hover) { a.cta:hover, button.cta:hover { background: rgba(236, 253, 245, .12); } }
.cta-txt { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.cta-eyebrow { font-size: 12px; font-weight: 600; letter-spacing: var(--track-wide); text-transform: uppercase; color: var(--hero-ink-3); line-height: 1.3; overflow-wrap: break-word; }
/* The screen's primary action: never cut to one line. Up to 3 lines; plaintext gives user text (a competition
   name in another script) its own direction. */
.cta-text {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 3;
  overflow: hidden;
  overflow-wrap: break-word;
  unicode-bidi: plaintext;
  font-size: 15.5px;
  font-weight: 650;
  color: var(--hero-ink);
  line-height: var(--lh-clamp);     /* clamped: the line box holds the script's tallest ink (see --lh-clamp) */
}
/* Hero text sits on the UI's side, under the eyebrow, whatever its script. The alignment is physical because
   unicode-bidi: plaintext (here, and in module CSS for mixed-script text) resolves start/end/match-parent against
   the text's OWN direction: a Latin competition name in the Arabic UI would otherwise sit on the left. */
.hero-label, .hero-text, .cta-eyebrow, .cta-text { text-align: left; unicode-bidi: plaintext; }
[dir="rtl"] .hero-label, [dir="rtl"] .hero-text, [dir="rtl"] .cta-eyebrow, [dir="rtl"] .cta-text { text-align: right; }
.cta-arrow { flex: none; display: grid; place-items: center; width: 42px; height: 42px; border-radius: 50%; background: var(--mint); color: var(--mint-ink); transition: transform var(--dur) var(--ease); }
.cta-arrow .ic { width: 20px; height: 20px; stroke-width: 2; }
.cta:active .cta-arrow { transform: translateX(2px); }
[dir="rtl"] .cta:active .cta-arrow { transform: translateX(-2px); }
/* without an action there is nothing to tap: plain text, no glass pill */
.cta.is-static { min-height: 0; padding: 0; border: 0; border-radius: 0; background: none; -webkit-backdrop-filter: none; backdrop-filter: none; }
.cta.is-static .cta-text { font-weight: 600; color: var(--hero-ink-2); }

/* 11. CONTROLS ------------------------------------------------------------- */
/* Toggle (role=switch) */
.tgl {
  position: relative;
  flex: none;
  display: inline-block;
  width: 50px;
  height: 30px;
  border-radius: var(--r-pill);
  background: var(--control-line);
  transition: background-color var(--dur) var(--ease);
}
button.tgl::after { content: ''; position: absolute; inset: -7px -3px; }
.tgl-knob { position: absolute; top: 3px; inset-inline-start: 3px; width: 24px; height: 24px; border-radius: 50%; background: #FFFFFF; box-shadow: 0 1px 3px rgba(0, 0, 0, .28); transition: transform var(--dur) var(--ease); }
.tgl.is-on, .tgl[aria-checked="true"], [aria-checked="true"] > .tgl { background: var(--accent); }
.tgl.is-on .tgl-knob, .tgl[aria-checked="true"] .tgl-knob, [aria-checked="true"] > .tgl .tgl-knob { transform: translateX(20px); }
[dir="rtl"] .tgl.is-on .tgl-knob, [dir="rtl"] .tgl[aria-checked="true"] .tgl-knob, [dir="rtl"] [aria-checked="true"] > .tgl .tgl-knob { transform: translateX(-20px); }

/* Segmented control */
.seg { display: flex; gap: 4px; padding: 4px; border-radius: var(--r-pill); background: var(--card-2); border: 1px solid var(--hairline); }
.seg-btn {
  position: relative;
  flex: 1 1 0;
  min-width: 0;
  min-height: 40px;
  padding: var(--s2) var(--s3);
  border-radius: var(--r-pill);
  font-size: 14px;
  font-weight: 650;
  color: var(--ink-2);
  text-align: center;
  line-height: 1.2;
  transition: background-color var(--dur) var(--ease), color var(--dur);
}
.seg-btn::after { content: ''; position: absolute; inset: -2px 0; }
.seg-btn[aria-pressed="true"] { background: var(--raise); color: var(--ink); box-shadow: inset 0 0 0 1.5px var(--control-line), 0 1px 2px rgba(16, 25, 21, .10); }
.hero .seg { background: rgba(236, 253, 245, .06); border-color: var(--hero-hairline); }
.hero .seg-btn[aria-pressed="true"] { background: rgba(236, 253, 245, .14); }

/* Chips */
.chips { display: flex; flex-wrap: wrap; gap: 8px; }
.chip {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  justify-content: center;
  min-width: 44px;
  min-height: 36px;
  padding: var(--s1) var(--s3);
  border-radius: var(--r-pill);
  background: var(--card-2);
  border: 1px solid var(--hairline);
  color: var(--ink-2);
  font-size: 13.5px;
  font-weight: 600;
  line-height: 1.2;
  white-space: nowrap;
}
.chip .ic { width: 15px; height: 15px; }
.chip > span { unicode-bidi: plaintext; }    /* '+5' keeps its sign in front in the RTL UI; words keep their own direction */
button.chip::after { content: ''; position: absolute; inset: -4px 0; }
.chip.is-active { background: var(--accent-soft); border-color: var(--accent); color: var(--accent-ink); }   /* state edge >= 3:1 */

/* Fields */
.field { display: flex; flex-direction: column; gap: var(--s2); min-width: 0; }
.field + .field { margin-top: var(--s3); }
.field-lbl { font-size: 13px; font-weight: 600; color: var(--ink-2); }
.field-hint { font-size: 12.5px; color: var(--ink-3); }
.input, .textarea, .select {
  display: block;
  width: 100%;
  min-height: 48px;
  padding: 11px var(--s4);
  border-radius: var(--r-input);
  border: 1px solid var(--control-line);       /* >= 3:1 against the card (WCAG 1.4.11) */
  background: var(--card-2);
  color: var(--ink);
  font-size: 16px;
  line-height: 1.4;
  transition: border-color var(--dur), box-shadow var(--dur);
}
/* free text takes the direction of what is typed; an empty field keeps the UI direction (better than dir=auto,
   which makes an empty field LTR in the Arabic UI) */
.input[type="text"], .input[type="search"], .textarea { unicode-bidi: plaintext; }   /* numbers, dates: UI direction */
.input::placeholder, .textarea::placeholder { color: var(--ink-3); opacity: 1; }
.input:focus, .textarea:focus, .select:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--focus); }
.input[aria-invalid="true"], .textarea[aria-invalid="true"] { border-color: var(--danger); }
.textarea { min-height: 112px; resize: vertical; }
.select-wrap { position: relative; }
.select { -webkit-appearance: none; appearance: none; padding-inline-end: 42px; cursor: pointer; }
.select-wrap > .ic { position: absolute; inset-inline-end: 14px; top: 50%; margin-top: -9px; width: 18px; height: 18px; color: var(--ink-3); pointer-events: none; }
.input[type="number"] { -moz-appearance: textfield; appearance: textfield; }

/* Round check */
.check {
  position: relative;
  flex: none;
  display: inline-grid;
  place-items: center;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  border: 1.5px solid var(--control-line);
  background: transparent;
  color: var(--on-accent);
  transition: background-color .15s var(--ease), border-color .15s var(--ease);
}
button.check::after { content: ''; position: absolute; inset: -8px; }
.check .ic { width: 16px; height: 16px; stroke-width: 2.6; opacity: 0; transform: scale(.6); transition: opacity .15s, transform .2s var(--ease); }
.check.is-done { background: var(--accent); border-color: var(--accent); }
.check.is-done .ic { opacity: 1; transform: none; }
.check.is-off { border-style: dashed; opacity: .55; }

/* 12. FEEDBACK: empty state, bar, grade chip, reference line ----------------------- */
.empty { display: flex; flex-direction: column; align-items: center; gap: var(--s2); padding: var(--s7) var(--s3) var(--s5); text-align: center; }
.empty-ic { display: grid; place-items: center; width: 56px; height: 56px; margin-bottom: var(--s1); border-radius: 50%; background: var(--accent-soft); color: var(--accent); }
.empty-ic .ic { width: 26px; height: 26px; }
.empty-title { font-size: 20px; font-weight: 700; color: var(--ink); letter-spacing: var(--track-tight); }
.empty-body { max-width: 34ch; font-size: 14.5px; color: var(--ink-3); }
.empty .btn { margin-top: var(--s2); }

.bar { position: relative; display: block; height: 6px; border-radius: var(--r-pill); background: var(--track); overflow: hidden; }
.bar-fill { display: block; height: 100%; border-radius: inherit; background: linear-gradient(90deg, var(--ring-a), var(--ring-b)); transition: width .25s var(--ease); }
[dir="rtl"] .bar-fill { background: linear-gradient(270deg, var(--ring-a), var(--ring-b)); }
.bar.on-dark { background: var(--hero-track); }
.bar.on-dark .bar-fill { background: linear-gradient(90deg, #ECFDF5, #6EE7B7); }
[dir="rtl"] .bar.on-dark .bar-fill { background: linear-gradient(270deg, #ECFDF5, #6EE7B7); }

.grade {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  min-height: 22px;
  padding: 2px var(--s2);
  border-radius: var(--r-pill);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: .02em;
  line-height: 1.2;
  white-space: nowrap;
  border: 1px solid transparent;
  vertical-align: middle;
}
.grade-sahih { background: var(--accent-soft); color: var(--accent-ink); }      /* >= 5.4:1 on card, card-2 and paper */
.grade-hasan { background: var(--card-2); border-color: var(--hairline-2); color: var(--ink-2); }
.grade-daif { background: var(--danger-soft); color: var(--danger); }
.grade-quran { background: transparent; border-color: var(--accent); color: var(--accent-ink); }
.grade-other { background: var(--card-2); border-color: var(--hairline); color: var(--ink-3); }

.ref { display: inline-flex; align-items: center; flex-wrap: wrap; gap: 4px 8px; font-size: 13px; font-weight: 600; color: var(--ink-3); line-height: 1.4; }
.ref > .ic { width: 15px; height: 15px; color: var(--accent); }
.ref a { position: relative; display: inline-flex; align-items: center; gap: 3px; min-height: 28px; border-radius: var(--r-input); color: var(--accent); text-decoration: none; }
.ref a::after { content: ''; position: absolute; inset: -8px -4px; }      /* 44px tall tap target, text stays 13px */
.ref a .ic { width: 13px; height: 13px; }
@media (hover: hover) { .ref a:hover { text-decoration: underline; } }

.quote { font-size: 16.5px; line-height: 1.55; color: var(--ink); font-weight: 500; }

/* Display numbers outside the hero (huge, thin, tabular) */
.display-row { display: flex; align-items: baseline; flex-wrap: wrap; gap: 2px 8px; }
.display { font-size: clamp(56px, 17vw, 72px); font-weight: 300; line-height: 1; letter-spacing: -.04em; color: var(--ink); font-variant-numeric: tabular-nums; unicode-bidi: plaintext; }
.display-unit { font-size: 18px; font-weight: 500; color: var(--ink-2); }
.quote + .ref { margin-top: 10px; }

/* Stepper (‹ Day 17 ›), inline note, loading */
.stepper { display: flex; align-items: center; justify-content: space-between; gap: var(--s2); }
.stepper > .icon-btn { background: var(--card); border: 1px solid var(--card-edge); }
.stepper > .icon-btn:disabled, .stepper > .icon-btn[aria-disabled="true"] { opacity: .35; cursor: default; }
.stepper-gap { flex: none; width: 44px; height: 44px; }
.stepper-label { flex: 1 1 auto; min-width: 0; text-align: center; }
.stepper-title { display: block; font-size: 20px; font-weight: 700; letter-spacing: var(--track-tight); color: var(--ink); line-height: 1.25; }
.stepper-sub { display: block; margin-top: 1px; font-size: 12.5px; font-weight: 600; color: var(--ink-3); }
.note { display: flex; align-items: flex-start; gap: var(--s3); padding: var(--s3) var(--s4); border-radius: var(--r-block); background: var(--accent-soft); color: var(--ink); font-size: 14px; line-height: 1.45; }
.note > .ic { flex: none; margin-top: 1px; color: var(--accent); }
.note-plain { background: var(--card-2); color: var(--ink-2); }
.note-danger { background: var(--danger-soft); }
.note-danger > .ic { color: var(--danger); }
.hero .note { background: rgba(236, 253, 245, .07); color: var(--hero-ink-2); }
.loading { display: flex; align-items: center; justify-content: center; gap: var(--s3); padding: var(--s6) var(--s3); color: var(--ink-3); font-size: 14px; font-weight: 500; }
.loading > span:last-child { unicode-bidi: plaintext; }   /* "Loading…" keeps its ellipsis at the end of its own text */
.spinner { flex: none; width: 18px; height: 18px; border-radius: 50%; border: 2px solid var(--track); border-top-color: var(--accent); animation: rs-spin .8s linear infinite; }
@keyframes rs-spin { to { transform: rotate(360deg); } }

/* 13. CHARTS (SVG) --------------------------------------------------------------- */
.chart { display: block; width: 100%; height: auto; }
.bars-b { fill: var(--chart-soft); }
.bars-b.is-hi { fill: var(--accent); }
.bars-b.is-zero { fill: var(--hairline-2); }
.bars-wrap { position: relative; }
.bars-axis { position: relative; height: 16px; margin-top: var(--s1); direction: ltr; }
.bars-lbl { position: absolute; top: 0; transform: translateX(-50%); font-size: 12px; font-weight: 600; line-height: 16px; color: var(--ink-3); white-space: nowrap; font-variant-numeric: tabular-nums; }
.bars-lbl.is-hi { color: var(--accent); }
.chart.on-dark .bars-b { fill: rgba(110, 231, 183, .30); }
.chart.on-dark .bars-b.is-hi { fill: #6EE7B7; }
.bars-wrap.on-dark .bars-lbl { color: var(--hero-ink-3); }
.bars-wrap.on-dark .bars-lbl.is-hi { color: #6EE7B7; }
.spark-line { fill: none; stroke: var(--accent); stroke-width: 2.25; stroke-linecap: round; stroke-linejoin: round; vector-effect: non-scaling-stroke; }
.spark-area { stroke: none; }
.spark .stop-a { stop-color: var(--accent); stop-opacity: .22; }
.spark .stop-b { stop-color: var(--accent); stop-opacity: 0; }
.spark-dot { fill: var(--card); stroke: var(--accent); stroke-width: 2.25; }
.spark-base { stroke: var(--hairline); stroke-width: 1; }
.chart.on-dark .spark-line { stroke: #6EE7B7; }
.chart.on-dark .spark-dot { fill: #0B2219; stroke: #6EE7B7; }

/* 14. OVERLAYS: bottom sheet, confirm dialog, toast --------------------------------- */
.sheet-root, .dialog-root { position: fixed; inset: 0; z-index: 60; display: none; }
.dialog-root { z-index: 70; }
.sheet-root.is-open, .dialog-root.is-open { display: block; }
.scrim { position: absolute; inset: 0; background: var(--scrim); opacity: 0; transition: opacity .22s var(--ease); }
.is-shown > .scrim { opacity: 1; }
.sheet {
  position: absolute;
  inset-inline: 0;
  bottom: 0;
  display: flex;
  flex-direction: column;
  max-width: var(--col);
  max-height: 88vh;
  max-height: 88dvh;
  margin-inline: auto;
  border-radius: var(--r-block) var(--r-block) 0 0;
  background: var(--card);
  border: 1px solid var(--card-edge);
  border-bottom: 0;
  box-shadow: 0 -12px 40px -12px rgba(4, 24, 17, .25);
  transform: translateY(100%);
  transition: transform .24s var(--ease);
}
.is-shown > .sheet { transform: none; }
.sheet:focus { outline: none; }
.sheet.is-dragging { transition: none; }
/* drag the grip or the header down to close (core.js); touch-action keeps the gesture from scrolling the page */
.sheet-grip { width: 38px; height: 4px; margin: 8px auto 0; border-radius: 2px; background: var(--hairline-2); flex: none; cursor: grab; touch-action: none; }
.sheet-hd { display: flex; align-items: center; gap: var(--s2); padding-block: var(--s1) 0; padding-inline: 20px 8px; flex: none; touch-action: none; }
.sheet-title { flex: 1 1 auto; min-width: 0; font-size: 20px; font-weight: 700; letter-spacing: var(--track-tight); color: var(--ink); }
.sheet-bd { flex: 1 1 auto; overflow-y: auto; overscroll-behavior: contain; padding: 8px 20px 20px; color: var(--ink-2); font-size: 15px; }
.sheet-ft { display: flex; flex-wrap: wrap; gap: var(--s3); flex: none; padding-block: var(--s3) calc(var(--s4) + env(safe-area-inset-bottom)); padding-inline: var(--s5); border-top: 1px solid var(--hairline); }
.sheet-ft .btn { flex: 1 1 120px; }        /* two side by side at 320px */
.sheet-bd:last-child { padding-bottom: calc(24px + env(safe-area-inset-bottom)); }

.dialog-root.is-open { display: flex; align-items: center; justify-content: center; padding: 24px 20px; }
.dialog {
  position: relative;
  width: 100%;
  max-width: 380px;
  padding: var(--s6) var(--s5) var(--s5);
  border-radius: var(--r-card);
  background: var(--card);
  border: 1px solid var(--card-edge);
  box-shadow: 0 30px 60px -24px rgba(0, 0, 0, .45);
  opacity: 0;
  transform: scale(.97);
  transition: opacity .2s var(--ease), transform .2s var(--ease);
}
.is-shown > .dialog { opacity: 1; transform: none; }
.dialog:focus { outline: none; }
.dialog-title { font-size: 20px; font-weight: 700; letter-spacing: var(--track-tight); color: var(--ink); }
.dialog-body { margin-top: 8px; font-size: 15px; color: var(--ink-2); white-space: pre-line; }
.dialog-ft { display: flex; flex-wrap: wrap; gap: var(--s3); margin-top: var(--s6); }
.dialog-ft .btn { flex: 1 1 120px; }

.toast-root {
  position: fixed;
  z-index: 80;
  inset-inline: 0;
  bottom: calc(var(--nav-h) + var(--nav-gap) + 16px + env(safe-area-inset-bottom));
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  padding-inline: 16px;
  pointer-events: none;
}
.no-nav .toast-root { bottom: calc(20px + env(safe-area-inset-bottom)); }
/* while a sheet or dialog is open, toasts move to the top so they never cover its buttons */
html.is-locked .toast-root { top: calc(12px + env(safe-area-inset-top)); bottom: auto; }
.toast {
  pointer-events: auto;
  display: flex;
  align-items: center;
  gap: var(--s3);
  max-width: min(440px, 100%);
  min-height: 48px;
  padding: var(--s3) var(--s4);
  border-radius: var(--r-block);
  background: #0E2A20;
  color: #EEF8F2;
  border: 1px solid rgba(167, 243, 208, .18);
  box-shadow: 0 16px 34px -14px rgba(4, 24, 17, .6);
  font-size: 14.5px;
  font-weight: 550;
  line-height: 1.35;
  animation: rs-toast-in .22s var(--ease);
}
.toast > .ic { color: #6EE7B7; width: 20px; height: 20px; }
.toast-error > .ic { color: #FDA29B; }
/* Messages may be English server/API text inside a translated UI: ordered by their own script, aligned to the UI side */
.toast-msg { flex: 1 1 auto; min-width: 0; overflow-wrap: break-word; unicode-bidi: plaintext; text-align: left; }
[dir="rtl"] .toast-msg { text-align: right; }
.toast.has-x { padding-inline-end: var(--s1); }
.toast-x { flex: none; display: grid; place-items: center; width: 44px; height: 44px; margin-block: -8px; border-radius: 50%; color: #B6CEC3; transition: background-color var(--dur) var(--ease), color var(--dur); }
.toast-x .ic { width: 18px; height: 18px; }
@media (hover: hover) { .toast-x:hover { background: rgba(236, 253, 245, .08); color: #EEF8F2; } }
.toast.is-leaving { opacity: 0; transform: translateY(6px); transition: opacity .2s var(--ease), transform .2s var(--ease); }
@keyframes rs-toast-in { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }
@keyframes rs-fade-in { from { opacity: 0; } to { opacity: 1; } }

/* 15. UTILITIES ------------------------------------------------------------------ */
.sr-only { position: absolute !important; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0; }
.stack { display: flex; flex-direction: column; gap: var(--s4); }
.stack-sm { display: flex; flex-direction: column; gap: var(--s2); }
.hstack { display: flex; align-items: center; flex-wrap: wrap; gap: var(--s2); }
.spread { display: flex; align-items: center; justify-content: space-between; gap: var(--s3); }
.grow { flex: 1 1 auto; min-width: 0; }
.muted { color: var(--ink-3); }
.ink-2 { color: var(--ink-2); }
.accent { color: var(--accent); }
.danger { color: var(--danger); }
.small { font-size: 13px; }
.caption { font-size: 12.5px; font-weight: 500; color: var(--ink-3); }
.strong { font-weight: 650; color: var(--ink); }
.t-center { text-align: center; }
.t-end { text-align: end; }
.nowrap { white-space: nowrap; }
.num { font-variant-numeric: tabular-nums; }
.divider { height: 1px; background: var(--hairline); border: 0; margin: var(--s4) 0; }
.mt-0 { margin-top: 0 !important; }
.mt-2 { margin-top: var(--s2); }
.mt-3 { margin-top: var(--s3); }
.mt-4 { margin-top: var(--s4); }
.mt-6 { margin-top: var(--s6); }
.ltr { direction: ltr; unicode-bidi: isolate; }
/* ui.meta: items separated by small dots drawn in the gap. The row is shifted back by one gap and clipped there,
   so the dot before an item that starts a new line is hidden: no dot is ever left dangling. */
.meta { display: flex; flex-wrap: wrap; align-items: center; row-gap: 2px; margin-inline-start: -13px; clip-path: inset(-16px -16px -16px 9px); }
[dir="rtl"] .meta { clip-path: inset(-16px 9px -16px -16px); }
.meta-i { position: relative; display: inline-flex; align-items: center; min-width: 0; margin-inline-start: 13px; }
.meta-i::before { content: ''; position: absolute; inset-inline-start: -8px; top: 50%; width: 3px; height: 3px; margin-top: -1.5px; border-radius: 50%; background: var(--ink-3); opacity: .7; }
.meta .link-btn { margin-block: -12px; }
/* Bidi for shared text. A string may be an English fallback (a key not translated yet) or user text (a name, a
   journal entry) inside a translated UI. plaintext orders each paragraph by its own first strong letter, so in the
   Arabic UI "Reset all data?" keeps its "?" at the end and "29 Jumada al-Ula" its 29 in front. The alignment stays
   on the UI's side and is physical (plaintext would resolve start/end against the text's own direction; see
   .row-val, .toast-msg, .cta-text). Zero specificity: any class that aligns text (.t-center, module classes) wins,
   and an element with its own dir attribute keeps it. Centred text only gets the ordering. Deliberately not done
   in RS.t with isolate characters: the same strings feed attributes and the jsPDF report. */
:where(.topbar-title, .topbar-sub, .sheet-title, .dialog-title, .dialog-body, .card-title, .card-bd > p, .sheet-bd > p, .row-title, .row-sub,
       .note > span, .kicker > span, .sec-title, .field-lbl, .field-hint):where(:not([dir])) { unicode-bidi: plaintext; text-align: left; }
:where([dir="rtl"]) :where(.topbar-title, .topbar-sub, .sheet-title, .dialog-title, .dialog-body, .card-title, .card-bd > p, .sheet-bd > p, .row-title, .row-sub,
       .note > span, .kicker > span, .sec-title, .field-lbl, .field-hint):where(:not([dir])) { text-align: right; }
:where(.empty-title, .empty-body, .stepper-title, .stepper-sub, .btn > span):where(:not([dir])) { unicode-bidi: plaintext; }

/* 16. STYLEGUIDE (hidden #/styleguide route) ------------------------------------------- */
.sg-label { margin: 0 0 8px; font-size: 12px; font-weight: 600; letter-spacing: var(--track-wide); text-transform: uppercase; color: var(--ink-3); }
.sg-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); gap: var(--s3); align-items: center; }
.sg-swatch { display: flex; align-items: center; gap: 10px; font-size: 12.5px; color: var(--ink-2); min-width: 0; }
.sg-swatch .ltr { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: 12px; font-variant-ligatures: none; overflow: hidden; text-overflow: ellipsis; }
.sg-swatch i { flex: none; width: 28px; height: 28px; border-radius: var(--r-input); border: 1px solid var(--hairline-2); }
.sg-icons { display: grid; grid-template-columns: repeat(auto-fill, minmax(44px, 1fr)); gap: 6px; color: var(--ink-2); }
.sg-rings { display: grid; grid-template-columns: repeat(2, max-content); justify-content: space-around; align-items: center; gap: var(--s4) var(--s6); }
@media (min-width: 480px) { .sg-rings { grid-template-columns: repeat(4, max-content); justify-content: space-between; } }
.sg-checks { gap: var(--s4); }   /* 28px checks with 44px hit areas (::after inset -8px): 16px apart, so they never overlap */
.sg-icons > span { display: grid; place-items: center; height: 40px; border-radius: var(--r-input); background: var(--card-2); }
.sg-c-paper { background: var(--paper); } .sg-c-card { background: var(--card); } .sg-c-card2 { background: var(--card-2); }
.sg-c-ink { background: var(--ink); } .sg-c-ink2 { background: var(--ink-2); } .sg-c-ink3 { background: var(--ink-3); }
.sg-c-accent { background: var(--accent); } .sg-c-soft { background: var(--accent-soft); } .sg-c-danger { background: var(--danger); }
.sg-c-hero { background: var(--hero-bg); } .sg-c-mint { background: var(--mint); } .sg-c-nav { background: var(--nav-bg); }

/* 17. MOTION ------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation-duration: .01ms !important; animation-iteration-count: 1 !important; }
  /* crossfade only: no movement. A sheet being dragged still follows the finger (direct manipulation, not an
     animation); core.js keeps it where it was let go while it closes. */
  .sheet:not(.is-dragging), .is-shown > .sheet:not(.is-dragging), .dialog, .is-shown > .dialog { transform: none !important; }
  .sheet { opacity: 0; transition: opacity .2s linear; }
  .is-shown > .sheet { opacity: 1; }
  .sheet.is-dragging { transition: opacity .2s linear; }     /* let go to close: it fades out where it was dropped */
  /* overlays and toasts fade in AND out (core.js waits 200ms before removing them) */
  .toast { animation-name: rs-fade-in; animation-duration: .2s !important; animation-timing-function: linear; }
  .btn:active:not(:disabled), .cta:active .cta-arrow, .toast.is-leaving { transform: none !important; }
  .tgl-knob, .check .ic, .ring-bar, .bar-fill, .nav { transition-duration: .01ms !important; }
  .no-nav .nav { transform: none; }
  .spinner { border-color: var(--accent); animation: rs-pulse 1.6s ease-in-out infinite !important; }
}
@keyframes rs-pulse { 0%, 100% { opacity: .3; } 50% { opacity: 1; } }

/* 18. FOCUS, continued: components with their own box-shadow keep the 1px accent line (the halo is an outline) */
.btn-primary:focus-visible { box-shadow: var(--btn-shadow), 0 0 0 1px var(--accent); }
.hero .btn-primary:focus-visible { box-shadow: 0 0 0 1px var(--accent); }
.seg-btn[aria-pressed="true"]:focus-visible { box-shadow: inset 0 0 0 1.5px var(--control-line), 0 0 0 1px var(--accent); }
