/* Ilm House Qur'an Academy — core styles (mobile-first)
   Tokens: docs/DESIGN-SYSTEM.md */

@font-face {
  font-family: Inter;
  src: url('../assets/fonts/inter-normal-latin.woff2') format('woff2');
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: Inter;
  src: url('../assets/fonts/inter-normal-latin-ext.woff2') format('woff2');
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: Inter;
  src: url('../assets/fonts/inter-italic-latin.woff2') format('woff2');
  font-weight: 100 900;
  font-style: italic;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: Inter;
  src: url('../assets/fonts/inter-italic-latin-ext.woff2') format('woff2');
  font-weight: 100 900;
  font-style: italic;
  font-display: swap;
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Noto Sans Bengali';
  src: url('../assets/fonts/noto-sans-bengali-var.woff2') format('woff2');
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0951-0952, U+0964-0965, U+0980-09FE, U+1CD0, U+1CD2, U+1CD5-1CD6, U+1CD8, U+1CE1, U+1CEA, U+1CED, U+1CF2, U+1CF5-1CF7, U+200C-200D, U+20B9, U+25CC, U+A8F1, U+11DF0-11DF1;
}
@font-face {
  font-family: 'Noto Serif Bengali';
  src: url('../assets/fonts/noto-serif-bengali-var.woff2') format('woff2');
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0951-0952, U+0964-0965, U+0980-09FE, U+1CD0, U+1CD2, U+1CD5-1CD6, U+1CD8, U+1CE1, U+1CEA, U+1CED, U+1CF2, U+1CF5-1CF7, U+200C-200D, U+20B9, U+25CC, U+A8F1, U+11DF0-11DF1;
}
@font-face {
  font-family: 'Amiri Quran';
  src: url('../assets/fonts/amiri-quran-400-arabic.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
  unicode-range: U+0600-06FF, U+0750-077F, U+0870-0891, U+0897-08E1, U+08E3-08FF, U+200C-200E, U+2010-2011, U+204F, U+2E41, U+FB50-FDFF, U+FE70-FE74, U+FE76-FEFC;
}

:root {
  /* ---------- recovered backup palette ----------
     The values below are the ones the November 2025 backup ships and the ones
     the Free Trial Form is built from. TASK 16 locked that form (owner brief §1C),
     so every token a rule inside `.trial-card` reads keeps its authored value;
     only `--color-background` - which no rule inside the locked card reads -
     moves to the new ivory. `tests/form-lock.test.mjs` proves it. */
  --color-background: #F8F6EE;
  --color-surface: #FFFFFF;
  --color-foreground: #5A4848;
  --color-foreground-strong: #3B2F2F;
  --color-primary: #2AA721;
  --color-primary-soft: #ABEBC6;
  --color-primary-pale: #EDF9F2;
  --color-gold: #7A6231;
  --color-gold-decorative: #987D43;
  --color-cta: #2CCF6F;
  --color-whatsapp: #126E44;
  --color-border: #E7DFCF;
  --color-muted: #6B5D5D;
  --color-destructive: #B3261E;
  --color-focus-ring: #2AA721;

  /* ---------- TASK 16 theme layer: emerald ink + ivory + antique gold ----------
     One system for the whole page outside the locked form: a deep emerald ink for
     headings, navigation, the footer and every non-form CTA; ivory and white
     surfaces; and an antique-gold hairline for the ornamental rules. Ratified by
     the owner on 2026-11-06, superseding the brown-cream direction of
     docs/DESIGN-SYSTEM.md §2 for everything except the form.
     Contrast (WCAG 2.2 AA, computed, see docs/TEST-REPORT.md TASK 16 §):
       ink #0E3A2C      14.7:1 on ivory, 15.9:1 on white, 13.9:1 on the band
       text #3C4B44      9.9:1 on ivory, 10.7:1 on white
       text-soft #5D6E66 5.5:1 on ivory, 5.9:1 on white
       link #1B7A3E      6.2:1 on white, 5.7:1 on ivory  (--color-primary 3.5:1 is
       kept only for the focus ring and non-text UI, where 3:1 is the bar)
       on-ink #FFFFFF   15.9:1 · on-ink-soft #AFC2B9 8.3:1 · gold-on-ink #D9BE7A 9.0:1 */
  --color-ink: #0E3A2C;
  --color-ink-hover: #14483A;
  --color-ink-deep: #092A20;
  --color-text: #3C4B44;
  --color-text-soft: #5D6E66;
  --color-link: #1B7A3E;
  --color-on-ink: #FFFFFF;
  --color-on-ink-soft: #AFC2B9;
  --color-gold-on-ink: #D9BE7A;
  --color-ivory: #F8F6EE;
  --color-band: #EEF2E6;
  --color-panel: #FFFFFF;
  --color-hairline: #E4D9B8;
  --color-hairline-strong: #D8C795;

  /* How much height the sticky phone bar takes at the foot of the viewport. The
     floating bubbles and the body's own bottom space both read this, and it stays
     0px for every band where the bar is off - so tablet and desktop keep exactly
     the authored bubble positions. css/responsive.css sets the real measured
     value inside the phone band. */
  --phone-nav-h: 0px;

  --font-ui: Inter, 'Noto Sans Bengali', sans-serif;
  --font-bn: 'Noto Sans Bengali', Inter, sans-serif;
  --font-heading: Inter, 'Noto Serif Bengali', serif;
  --font-quran: 'Amiri Quran', 'Noto Naskh Arabic', serif;

  --space-1: 8px;
  --space-2: 16px;
  --space-3: 24px;
  --space-4: 32px;
  --space-5: 40px;
  --space-6: 48px;
  --space-7: 56px;
  --space-8: 64px;
  --space-12: 96px;

  --container: 1200px;
  --radius-sm: 6px;
  --radius-md: 10px;
  --shadow-card: 0 8px 24px rgba(90, 72, 72, .08);
  /* Elevation for the new system: one low ambient layer and one raised layer,
     both tinted with the ink rather than neutral black, so cards read as paper
     on the ivory instead of slabs. `--shadow-card` stays for the locked card. */
  --shadow-soft: 0 1px 2px rgba(14, 58, 44, .05), 0 6px 16px rgba(14, 58, 44, .06);
  --shadow-raised: 0 2px 4px rgba(14, 58, 44, .06), 0 14px 32px rgba(14, 58, 44, .10);
  --transition-fast: 180ms ease;
  --transition-reveal: 350ms cubic-bezier(.22, .61, .36, 1);
}

*, *::before, *::after { box-sizing: border-box; }

html { scroll-behavior: smooth; }

/* Sticky header must not cover anchored section headings. */
[id] { scroll-margin-top: 88px; }

body {
  margin: 0;
  background: var(--color-background);
  color: var(--color-text);
  font-family: var(--font-ui);
  font-size: 1rem;
  line-height: 1.65;
  -webkit-text-size-adjust: 100%;
}

[lang="bn"] { font-family: var(--font-bn); line-height: 1.9; }
[lang="ar"], .quran {
  font-family: var(--font-quran);
  line-height: 2.1;
  unicode-bidi: isolate;
}

h1, h2, h3, h4 {
  font-family: var(--font-heading);
  color: var(--color-ink);
  line-height: 1.25;
  margin: 0 0 .5em;
  text-wrap: balance;
}
h1 { font-size: clamp(1.9rem, 4.5vw, 2.75rem); font-weight: 700; }
h2 { font-size: clamp(1.5rem, 3.2vw, 2rem); font-weight: 700; }
h3 { font-size: 1.25rem; font-weight: 600; }
p { margin: 0 0 1em; }

img { max-width: 100%; height: auto; display: block; }

a { color: var(--color-link); }
a:hover { color: var(--color-gold); }

:focus-visible {
  outline: 2px solid var(--color-focus-ring);
  outline-offset: 2px;
  border-radius: 2px;
}

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  background: var(--color-panel);
  color: var(--color-ink);
  padding: 12px 20px;
  z-index: 100;
  border-radius: 0 0 var(--radius-sm) 0;
  box-shadow: var(--shadow-raised);
}
.skip-link:focus { left: 0; }

.container {
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: clamp(16px, 5vw, 32px);
}

.visually-hidden {
  position: absolute !important;
  width: 1px; height: 1px;
  margin: -1px; padding: 0; border: 0;
  clip: rect(0 0 0 0); clip-path: inset(50%);
  overflow: hidden; white-space: nowrap;
}

/* ---------- header ---------- */
/* TASK 16: the strip is the page's signature, so it carries the ink-on-ivory
   system: white panel, antique-gold hairline instead of the beige border, and a
   single low ambient shadow. Every metric (min-height 72px, padding-block 10px,
   the 176px brand, the toggle's box) is what tests/mobile-hero.test.mjs measures
   at 640/768/1024/1440, so only colour, hairline and elevation move here. */
.site-header {
  position: sticky;
  top: 0;
  z-index: 40;
  /* TASK 29: viewport-fit=cover lets edge-to-edge phones hand the page the notch
     and home-indicator areas; the sticky header keeps its row below the status
     bar while its own panel paints behind it. 0px wherever insets are absent. */
  padding-top: env(safe-area-inset-top, 0px);
  background: var(--color-panel);
  border-bottom: 1px solid var(--color-hairline);
  box-shadow: var(--shadow-soft);
}
.site-header .container {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  min-height: 72px;
  padding-block: 10px;
}
.brand img { width: 176px; height: auto; }
.menu-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-width: 44px;
  min-height: 44px;
  padding: 8px 12px;
  background: var(--color-panel);
  border: 1px solid var(--color-hairline-strong);
  border-radius: var(--radius-sm);
  cursor: pointer;
  color: var(--color-ink);
  font: 600 .9375rem/1 var(--font-ui);
}
.menu-toggle svg { width: 20px; height: 20px; flex: none; }
.menu-toggle[aria-expanded="true"] .menu-icon-open { display: none; }
.menu-toggle[aria-expanded="false"] .menu-icon-close { display: none; }
.menu-toggle:hover { background: var(--color-band); border-color: var(--color-ink); }
.site-nav ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: none;
  flex-direction: column;
  gap: 4px;
  position: absolute;
  inset: 72px 0 auto 0;
  background: var(--color-panel);
  border-bottom: 1px solid var(--color-hairline);
  box-shadow: var(--shadow-raised);
  padding-block: var(--space-2);
}
.site-nav.open ul { display: flex; }
.site-nav a {
  display: block;
  padding: 12px clamp(16px, 5vw, 32px);
  min-height: 44px;
  text-decoration: none;
  font-weight: 600;
  color: var(--color-ink);
}
/* The hover and current marks are inset shadows, not borders: a border would add
   to the link box and move the header height the responsive suite pins. */
.site-nav a:hover { background: var(--color-band); color: var(--color-ink-hover); }
.site-nav a[aria-current="page"] {
  color: var(--color-ink);
  box-shadow: inset 0 -2px 0 var(--color-gold-decorative);
}

/* ---------- phone navigation (TASK 16) ----------
   Audit finding BUG-01: TASK 09 hid the header outright on a phone, so below
   640px the page had no navigation at all - the only way to another section was
   to scroll. The owner chose a sticky bottom bar with five cells (four existing
   section links plus the existing trial-class call to action) over re-showing the
   header. It lives outside .site-header, so the header the responsive suite
   counts and measures stays exactly as it is, and it is display:none until the
   phone band turns it on, so tablet and desktop never see the box.
   Every label is a string the page already ships; the icons are inline SVG in
   the page's own outline family, and the bar obeys the iOS home-indicator area
   through env(safe-area-inset-bottom).
   TASK 19 reorders the row to Home / Courses / Free Trial Class / Reviews /
   Contact Us and gives the action the middle cell at roughly 28% of the row while
   the four section links take 18% each. The fr ratios keep those proportions at
   every width and `minmax(0, ...)` stops a long label from widening its own track;
   the 2px gap keeps the cells separate without eating the centre cell. The label
   size tracks the viewport so "Contact Us" (60.1px at 11px, the widest of the four
   English labels) still holds one line at 360px and at 320px, while the Bengali
   action keeps its own 12px ceiling. */
.mobile-nav {
  position: fixed;
  inset: auto 0 0 0;
  z-index: 46;
  display: none;
  padding: 6px 10px calc(6px + env(safe-area-inset-bottom, 0px));
  background: var(--color-ink-deep);
  border-top: 1px solid rgba(217, 190, 122, .34);
  box-shadow: 0 -6px 18px rgba(9, 42, 32, .22);
}
.mobile-nav-list {
  display: grid;
  grid-template-columns: minmax(0, 18fr) minmax(0, 18fr) minmax(0, 28fr) minmax(0, 18fr) minmax(0, 18fr);
  gap: 2px;
  list-style: none;
  margin: 0;
  padding: 0;
}
/* The cells are the list items, so the anchors have to be told to fill them -
   otherwise the label sits in a shrink-to-fit box and the current-page mark
   stops at the end of the text instead of the end of the cell. */
.mobile-nav-list li { display: flex; }
.mobile-nav-item {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
  min-height: 48px;
  padding: 6px 0;
  border-radius: var(--radius-sm);
  color: var(--color-on-ink-soft);
  font-family: var(--font-ui);
  font-size: clamp(9.5px, 2.95vw, 11px);
  font-weight: 600;
  line-height: 1.25;
  letter-spacing: 0;
  text-align: center;
  text-decoration: none;
}
.mobile-nav-item svg { width: 22px; height: 22px; flex: none; }
.mobile-nav-item:hover, .mobile-nav-item:focus-visible { color: var(--color-on-ink); }
.mobile-nav-item[aria-current="page"] {
  color: var(--color-on-ink);
  box-shadow: inset 0 -2px 0 var(--color-gold-on-ink);
}
/* The action cell is the bar's only bright object, and it is deliberately the
   system's gold rather than the form's brand green: brand green stays inside the
   locked card and in links/focus. Ink on #D9BE7A measures 9.0:1. Its label is a
   Bengali phrase, so it keeps a 10.5px floor and reaches the authored 12px by
   353px; the 28% cell leaves it room to stay on one line at 280px as well. */
.mobile-nav-cta {
  background: var(--color-gold-on-ink);
  color: var(--color-ink-deep);
  font-family: var(--font-bn);
  font-size: clamp(10.5px, 3.4vw, .75rem);
  font-weight: 700;
  line-height: 1.3;
}
.mobile-nav-cta:hover, .mobile-nav-cta:focus-visible { background: #E5CE93; color: var(--color-ink-deep); }

/* ---------- hero ---------- */
/* One block, two frames: the artwork column and the form card are grid items of
   the same row, so they always end at the same desktop height. The artwork is
   absolutely filled at >=1024px, which means the card drives the height and the
   image can never stop above the form.
   Radius: the brief's 14-18px band (16px); the backup authored 20px on the image
   and 24px on the card -> DECISIONS D33. */
.hero {
  /* TASK 17 owner request: the section behind both columns is pure white, while
     the page keeps its ivory. A literal, not a token, so no other section and no
     locked form surface can follow this value by accident. */
  background: #FFFFFF;
  padding: clamp(24px, 5vw, 64px) 0;
}
.hero-frame {
  --radius-hero: 16px;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--space-3);
  align-items: stretch;
  background: var(--color-surface);
  border-radius: var(--radius-hero);
  /* TASK 22: `--shadow-raised` is a green-grey elevation; on the hero's pure
     white ground it painted a grey-green band into the 19.5px phone gutters and
     around the frame. The white block needs no elevation, so the frame carries
     none. Scoped here only - the token and every other section keep theirs, and
     the form card keeps its own locked `--shadow-card`. */
}
.hero-visual {
  --hero-corner-blend: 120px;
  position: relative;
  margin: 0;
  min-height: 240px;
  /* TASK 19: the frame behind the artwork is the section's own pure white, not
     the mint token, so the image's loading fade and the two rounded corners can
     never show a cream patch against the white hero. */
  background: #FFFFFF;
  border-radius: var(--radius-hero);
  overflow: hidden;
}
.hero-visual img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center 30%;
  opacity: 0;
  transition: opacity var(--transition-reveal);
}
.hero-visual img.is-loaded { opacity: 1; }
/* The artwork's own background is paper-white at the lower corners but several
   of the ten hero files carry a cream or green wash in the two top corners. The
   asset files must not be edited, so a soft radial white blend over each top
   corner carries the image-side background into the section white instead. It is
   painted above the image and ignores the pointer. */
.hero-visual::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background:
    radial-gradient(circle var(--hero-corner-blend) at 0 0, #FFFFFF 0, #FFFFFF 20%, rgba(255, 255, 255, 0) 100%),
    radial-gradient(circle var(--hero-corner-blend) at 100% 0, #FFFFFF 0, #FFFFFF 20%, rgba(255, 255, 255, 0) 100%);
}

.hero-frame h1 {
  font-size: 22px;
  font-weight: 500;
  line-height: 1.35;
  text-align: center;
  margin: 0;
}
.lead {
  font-size: 16px;
  font-weight: 500;
  line-height: 1.6;
  text-align: center;
  margin: 0;
}
/* Task 05 round 4 §2: one thin brand-green box owns the whole form block —
   heading, fields and Send — while the intro paragraph, special note and dua
   stay outside it. Kept compact so it adds no new vertical air. */
.trial-box {
  display: grid;
  gap: 10px;
  align-content: start;
  border: 1px solid var(--color-primary);
  border-radius: 12px;
  padding: 14px;
}
.trial-title {
  font-size: 20px;
  font-weight: 500;
  line-height: 1.4;
  text-align: center;
  margin: 0;
}
.highlight {
  background: #E9F8EF;
  color: #117A45;
  font-weight: 600;
  padding: 1px 5px;
  border-radius: 4px;
}
.special-note {
  margin: 0;
  text-align: center;
  color: var(--color-muted);
  font-size: .8125rem;
  line-height: 1.7;
}
.dua {
  margin: 0;
  text-align: center;
  font-family: var(--font-bn);
  color: var(--color-foreground-strong);
  font-size: .875rem;
  font-weight: 500;
  line-height: 1.6;
}
.section-figure { margin: 0; }
/* box-sizing is border-box globally, so the hairline is drawn inside the image's
   own measure: the artwork gets a frame without the column gaining a pixel. */
.section-figure img {
  border-radius: var(--radius-md);
  border: 1px solid var(--color-hairline);
  box-shadow: var(--shadow-soft);
  width: 100%;
  height: auto;
}
.figure-caption {
  font-family: var(--font-bn);
  color: var(--color-gold);
  text-align: center;
  margin: var(--space-2) 0 0;
  line-height: 1.9;
}
.prose p { margin: 0 0 1em; }
.prose ul { margin: 0 0 1em; padding-left: 0; list-style: none; display: grid; gap: 8px; }
.subheading { font-weight: 700; color: var(--color-ink); margin: 0 0 .5em; }

.trial-card {
  display: grid;
  gap: 8px;
  align-content: start;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-hero);
  box-shadow: var(--shadow-card);
  padding: clamp(18px, 3vw, 26px);
}
.eyebrow {
  color: var(--color-gold);
  font-size: .8125rem;
  font-weight: 700;
  letter-spacing: .12em;
  text-transform: uppercase;
  margin: 0 0 var(--space-1);
}

/* ---------- buttons ---------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  min-height: 48px;
  padding: 12px 22px;
  border: 0;
  border-radius: var(--radius-sm);
  font: 600 1rem/1 var(--font-ui);
  text-decoration: none;
  cursor: pointer;
  transition: background-color var(--transition-fast), transform var(--transition-fast);
}
.btn:active { transform: translateY(1px); }
.btn-cta { background: var(--color-cta); color: #000; }
.btn-cta:hover { background: #25b862; color: #000; }
.btn-whatsapp { background: var(--color-whatsapp); color: #fff; }
.btn-whatsapp:hover { background: #0e5a37; color: #fff; }
/* The header CTA is an <a> inside .site-nav, so the generic link rules above
   out-specify this button (0,1,1 beats 0,1,0) and painted ink on the dark green
   field - measured 2.01:1, and pale-on-hover on top of that. Re-assert the
   button's own colours in the nav context instead of loosening the link rule. */
.site-nav a.btn-whatsapp { background: var(--color-whatsapp); color: #fff; }
.site-nav a.btn-whatsapp:hover, .site-nav a.btn-whatsapp:focus-visible { background: #0e5a37; color: #fff; }
.btn[disabled] { opacity: .6; cursor: progress; }
.btn svg { width: 20px; height: 20px; flex: none; }
.btn-row { display: flex; flex-direction: column; gap: 12px; align-items: stretch; }
.btn-row--center { justify-content: center; }
.turnstile { min-height: 0; }
.turnstile.is-active { min-height: 68px; }
.btn-row .btn { width: 100%; }
.nav-cta { display: none; }

/* ---------- sections ---------- */
/* TASK 16: one rhythm for the whole page. Alternating bands are the soft
   emerald-ivory instead of the pale green, the head block gets one extra step of
   air before its content, and the rule under every heading becomes the system's
   signature ornament - a gold hairline with a centre diamond, drawn with
   pseudo-elements so it adds no markup and no box to the text column. */
.section { padding-block: clamp(48px, 8vw, 96px); }
.section--tint { background: var(--color-band); }
.section--surface { background: var(--color-panel); }
.section-head { max-width: 720px; margin-inline: auto; text-align: center; margin-bottom: var(--space-5); }
.section-head .rule {
  position: relative;
  width: 56px; height: 3px;
  background: var(--color-gold-decorative);
  border: 0;
  margin: var(--space-2) auto 0;
}
.section-head .rule::before,
.section-head .rule::after {
  content: "";
  position: absolute;
  top: 50%;
  width: 26px; height: 1px;
  background: var(--color-hairline-strong);
}
.section-head .rule::before { right: calc(100% + 8px); }
.section-head .rule::after { left: calc(100% + 8px); }

/* Task 06 §2/§5: the two columns start at the same vertical level, and the
   media column owns the figure plus the section's concluding group so the
   image side is never left underfilled while the text column runs long. */
.split {
  display: grid;
  gap: var(--space-4);
  align-items: start;
}
.split img {
  border-radius: var(--radius-md);
  border: 1px solid var(--color-hairline);
  box-shadow: var(--shadow-soft);
  width: 100%;
}
.split-media { display: grid; gap: var(--space-3); align-content: start; }
.split-media .readmore-toggle { justify-self: start; }

.bullet-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 12px; }
.bullet-list li {
  position: relative;
  padding-left: 32px;
}
.bullet-list li::before {
  content: "";
  position: absolute;
  left: 0; top: .35em;
  width: 18px; height: 18px;
  background: var(--color-ink);
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E") center / contain no-repeat;
}

/* ---------- courses ---------- */
/* TASK 28: the three cards are rebuilt on the owner's reference design (the Hifz +
   Translation banners and the full Tajweed card). One family for all three: an
   ivory card with a gold rule and a generous radius, the course's own banner
   artwork full-bleed at the top, a left-aligned green/gold title stack, a gold
   pill heading for "কোর্স অন্তর্ভুক্ত:" between two tapering gold rules, a
   green circle-check feature list and a green pill CTA wearing the reference's
   gold ring, graduation cap and gold arrow disc.
   The banners are crops of the owner's reference artwork at a shared 3.12 ratio
   (crop inside the gold frame, floor cut just above the baked title - the TASK 20
   precedent), so no artwork was generated, substituted or stretched.
   Colours are sampled from those references: ivory #FBF7EE, border gold #B99259,
   Bengali title green #053C24, English gold #835B13, rule/pill gold #C9A24B,
   check green #1F7A44, CTA body #023422 and CTA ring #DBA947.
   The old five-row subgrid is gone: the reference stacks each card's own banner
   over its own body, so the cards are flex columns again and the CTA is pinned to
   the foot of every card by margin-top:auto. */
.section--courses { background: var(--color-band); }
.course-grid { display: grid; gap: var(--space-3); }
.course-card {
  display: flex;
  flex-direction: column;
  background: #FBF7EE;
  border: 2px solid #B99259;
  border-radius: 22px;
  box-shadow: var(--shadow-soft);
  overflow: hidden;
  transition: box-shadow var(--transition-fast), transform var(--transition-fast),
              border-color var(--transition-fast);
}
.course-card:hover {
  box-shadow: var(--shadow-raised);
  border-color: #C9A24B;
  transform: translateY(-2px);
}

.course-header {
  margin: 0;
  background: #FBF7EE;
}
.course-header__art {
  display: block;
  width: 100%;
  height: auto;
}
.course-body {
  display: flex;
  flex: 1;
  flex-direction: column;
  padding: clamp(16px, 4.5%, 26px) clamp(16px, 5%, 28px) clamp(18px, 5%, 26px);
}

.course-title {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  justify-items: start;
  gap: 2px;
  margin: 0 0 14px;
  text-align: left;
  font-size: clamp(1.1875rem, .55vw + 17px, 1.375rem);
  line-height: 1.45;
  font-weight: 700;
  color: #053C24;
}
.course-title-bn { font-family: var(--font-bn); color: #053C24; }
.course-title-en {
  font-family: var(--font-ui);
  color: #835B13;
  font-size: .82em;
  font-weight: 600;
}

.course-desc {
  margin: 0 0 18px;
  font-family: var(--font-bn);
  color: var(--color-text);
  line-height: 1.8;
  text-align: left;
}

/* The reference sets "কোর্স অন্তর্ভুক্ত:" in a gold pill between two rules that
   fade out towards the card edges. */
.course-includes {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 0 0 16px;
}
.course-includes::before,
.course-includes::after {
  content: "";
  flex: 1;
  height: 2px;
  border-radius: 2px;
}
.course-includes::before {
  background: linear-gradient(90deg, rgba(201, 162, 76, 0), #C9A24B);
  /* The reference keeps the pill left of centre: a short rule on the left, the
     rest of the line on the right. */
  flex: 0 0 clamp(28px, 12%, 56px);
}
.course-includes::after { background: linear-gradient(90deg, #C9A24B, rgba(201, 162, 76, 0)); }
.course-includes__pill {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 7px 18px;
  border: 1px solid #C9A24B;
  border-radius: 999px;
  background: linear-gradient(180deg, #F6E7BC, #E2BE79);
  color: #053C24;
  font-family: var(--font-bn);
  font-weight: 700;
  white-space: nowrap;
}
.course-includes__pill::before {
  content: "";
  flex: none;
  width: 14px;
  height: 14px;
  background: #053C24;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 2 22 12 12 22 2 12Z' fill='none' stroke='white' stroke-width='2.4'/%3E%3Cpath d='M12 8.2 15.8 12 12 15.8 8.2 12Z'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 2 22 12 12 22 2 12Z' fill='none' stroke='white' stroke-width='2.4'/%3E%3Cpath d='M12 8.2 15.8 12 12 15.8 8.2 12Z'/%3E%3C/svg%3E") center / contain no-repeat;
}

#Courses .bullet-list { gap: 10px; margin-bottom: 20px; }
#Courses .bullet-list li {
  padding-left: 34px;
  line-height: 1.7;
  font-family: var(--font-bn);
  color: var(--color-text);
}
/* Green ring with a green tick inside it, as in the reference: the ::before draws
   the ring and the ::after the glyph, so the shared .bullet-list mask is unset. */
#Courses .bullet-list li::before {
  top: .1em;
  width: 22px;
  height: 22px;
  border: 2px solid #1F7A44;
  border-radius: 50%;
  background: none;
  -webkit-mask: none;
  mask: none;
}
#Courses .bullet-list li::after {
  content: "";
  position: absolute;
  left: 5px;
  top: calc(.1em + 5px);
  width: 12px;
  height: 12px;
  background: #1F7A44;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='3.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='3.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E") center / contain no-repeat;
}

/* Premium CTA: deep green pill, gold border, ivory halo, white label, gold cap on
   the left and a gold disc with a dark green arrow on the right. Full width so it
   reads as the card's foot action. */
.course-cta {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  min-height: 52px;
  margin-top: auto;
  padding: 10px 12px 10px 20px;
  border: 2px solid #D8B465;
  border-radius: 999px;
  background: linear-gradient(180deg, #10543A, #023422);
  color: #FFFFFF;
  box-shadow: 0 0 0 3px #FBF7EE, 0 0 0 4px #C9A24B, 0 8px 18px rgba(2, 52, 34, .28);
  font: 700 1.0625rem/1.2 var(--font-bn);
  text-align: center;
}
.course-cta:hover { background: linear-gradient(180deg, #14613F, #04412A); color: #FFFFFF; }
.course-cta .course-cta__cap {
  width: 26px;
  height: 26px;
  flex: none;
  color: #F4E3B2;
}
.course-cta__label { flex: 1; min-width: 0; }
.course-cta__arrow {
  display: grid;
  place-items: center;
  flex: none;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  background: linear-gradient(180deg, #F6E7BC, #D8B465);
}
.course-cta__arrow svg { width: 18px; height: 18px; color: #023422; }

/* ---------- forms ---------- */
.form-grid { display: grid; gap: 10px; }
/* One elastic column per field: without minmax(0,1fr) the implicit auto track is
   sized to the content's min-content width, so a long country name in the
   combobox trigger pushed the field outside its grid cell and over the
   neighbouring phone input. */
.field { display: grid; grid-template-columns: minmax(0, 1fr); gap: 4px; }
.field label { font-weight: 600; font-size: .9375rem; color: var(--color-foreground-strong); }
.field .hint { font-size: .8125rem; color: var(--color-muted); }
.field input, .field select, .field textarea {
  width: 100%;
  min-height: 46px;
  padding: 11px 13px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  background: var(--color-surface);
  color: var(--color-foreground);
  font: inherit;
}
.field textarea { min-height: 76px; resize: vertical; }
.field input:focus, .field select:focus, .field textarea:focus {
  border-color: var(--color-primary);
}
.field [aria-invalid="true"] { border-color: var(--color-destructive); }
.field-error {
  color: var(--color-destructive);
  font-size: .875rem;
  font-weight: 600;
  margin: 0;
}
.phone-row { display: grid; grid-template-columns: 116px 1fr; gap: 8px; }
.field--full { grid-column: 1 / -1; }
.form-actions { display: flex; flex-direction: column; gap: 10px; }
.form-actions .btn { width: 100%; }
/* The WhatsApp handoff is not a form button: it only exists inside the status
   region, after a submission attempt, and is hidden until form.js fills its href. */
.btn-wa-handoff {
  width: 100%;
  margin-top: 10px;
  background: transparent;
  color: var(--color-whatsapp);
  border: 1px solid var(--color-whatsapp);
  font-size: .9375rem;
}
.btn-wa-handoff:hover { background: var(--color-whatsapp); color: #fff; }
.btn-wa-handoff[hidden] { display: none; }
.btn-wa-handoff svg { width: 20px; height: 20px; flex: none; }
.hp-field { position: absolute !important; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

/* ---------- country selector ---------- */
/* The native <select> stays the value carrier for the Apps Script payload; the
   combobox only exists once js/combobox.js has enhanced the field. */
.field--country { position: relative; }
.field--country:not(.is-enhanced) .country-select { display: none; }
.field--country.is-enhanced > select {
  position: absolute !important;
  width: 1px;
  height: 1px;
  border: 0;
  opacity: 0;
  pointer-events: none;
  clip-path: inset(50%);
}
.country-select { position: relative; }
.country-trigger {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  min-height: 46px;
  padding: 10px 12px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  background: var(--color-surface);
  color: var(--color-foreground);
  font: inherit;
  text-align: left;
  cursor: pointer;
}
.country-trigger:hover { border-color: var(--color-primary); }
.country-trigger[aria-invalid="true"] { border-color: var(--color-destructive); }
.country-trigger [data-country-flag] { flex: none; }
.country-trigger [data-country-label] {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.country-trigger [data-country-dial] {
  flex: none;
  color: var(--color-muted);
  font-variant-numeric: tabular-nums;
}
.country-trigger-arrow {
  flex: none;
  width: 16px;
  height: 16px;
  color: var(--color-muted);
}
.country-panel {
  position: absolute;
  z-index: 30;
  top: calc(100% + 6px);
  left: 0;
  right: 0;
  padding: 8px;
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-card);
}
.country-panel[hidden] { display: none; }
.country-search {
  width: 100%;
  min-height: 44px;
  padding: 10px 12px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  background: var(--color-surface);
  color: var(--color-foreground);
  font: inherit;
}
.country-search:focus { border-color: var(--color-primary); }
.country-list {
  list-style: none;
  margin: 8px 0 0;
  padding: 0;
  max-height: 260px;
  overflow-y: auto;
  overscroll-behavior: contain;
}
.country-option {
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: 40px;
  padding: 8px 10px;
  border-radius: var(--radius-sm);
  cursor: pointer;
}
.country-option:hover { background: var(--color-primary-pale); }
.country-option.is-active {
  background: var(--color-primary-pale);
  outline: 2px solid var(--color-primary);
  outline-offset: -2px;
}
.country-option.is-selected { font-weight: 600; color: var(--color-foreground-strong); }
.country-option-name { flex: 1 1 auto; min-width: 0; }
.country-option-dial {
  flex: none;
  color: var(--color-muted);
  font-variant-numeric: tabular-nums;
}
.country-empty {
  margin: 8px 0 0;
  padding: 10px;
  text-align: center;
  color: var(--color-muted);
  font-size: .9375rem;
}

.form-status {
  border-radius: var(--radius-sm);
  padding: 12px 16px;
  font-weight: 600;
  font-size: .9375rem;
}
.form-status-text { margin: 0; }
.form-status-note { margin: 6px 0 0; font-weight: 500; }
.form-status-note[hidden] { display: none; }
.form-status[hidden] { display: none; }
.form-status--error { background: #FDECEA; color: var(--color-destructive); }
.form-status--success { background: var(--color-primary-pale); color: #14532d; }
.error-summary {
  background: #FDECEA;
  border: 1px solid var(--color-destructive);
  border-radius: var(--radius-sm);
  padding: var(--space-2);
  margin-bottom: var(--space-2);
}
.error-summary h2 { font-size: 1.0625rem; color: var(--color-destructive); margin: 0 0 8px; }
.error-summary ul { margin: 0; padding-left: 20px; }
.error-summary a { color: var(--color-destructive); }

/* ---------- faq ---------- */
#FAQ .section-head h2 { font-size: clamp(1.9rem, 3.4vw, 2.4rem); }
.faq-columns { display: grid; gap: 20px; max-width: 1200px; margin-inline: auto; }
.faq-list { display: grid; gap: 15px; align-content: start; }
.faq-item { background: transparent; border: 0; }
.faq-item summary {
  list-style: none;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  min-height: 68px;
  padding: 20px;
  border: 1px solid var(--color-hairline);
  border-radius: 10px;
  background: var(--color-panel);
  color: var(--color-ink);
  font-family: var(--font-ui);
  font-weight: 600;
  font-size: 18px;
  line-height: 1.35;
  box-shadow: var(--shadow-soft);
  transition: background var(--transition-fast), color var(--transition-fast), border-color var(--transition-fast);
}
.faq-item summary::-webkit-details-marker { display: none; }
/* TASK 16 fixes audit finding A11Y-02 here. The recovered state was white on
   #FF0000 - 3.99:1 at 18px/600, which is normal text for WCAG and therefore
   under AA's 4.5:1. The open/hover question is now white on the system's own
   ink: 15.89:1, and it reads as "this one is open" instead of as an error. */
.faq-item summary:hover { background: var(--color-band); border-color: var(--color-hairline-strong); }
.faq-item[open] summary,
.faq-item[open] summary:hover {
  background: var(--color-ink);
  color: var(--color-on-ink);
  border-color: var(--color-ink);
}
.faq-item summary::after {
  content: "";
  width: 18px; height: 18px;
  flex: none;
  background: currentColor;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.5' stroke-linecap='round'%3E%3Cpath d='M12 5v14M5 12h14'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.5' stroke-linecap='round'%3E%3Cpath d='M12 5v14M5 12h14'/%3E%3C/svg%3E") center / contain no-repeat;
  transition: background var(--transition-fast);
}
.faq-item[open] summary::after {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.5' stroke-linecap='round'%3E%3Cpath d='M5 12h14'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.5' stroke-linecap='round'%3E%3Cpath d='M5 12h14'/%3E%3C/svg%3E");
}
.faq-item .faq-body {
  margin-top: 10px;
  padding: 20px;
  background: var(--color-panel);
  border: 1px solid var(--color-hairline);
  border-radius: 10px;
  color: var(--color-text);
  font-family: var(--font-bn);
  font-size: 18px;
  line-height: 1.75;
}
.faq-item .faq-body p { margin: 0; }

/* ---------- faq answer animation ----------
   A closed <details> hides everything after the summary, so the answer used to
   appear and vanish in one frame. ::details-content is the box the UA puts that
   answer in, so sizing it is what animates: 0 -> auto with `interpolate-size`
   lands on each answer's own measured height, which keeps every length correct
   without a fixed max-height, and `overflow: clip` is what makes the answer
   slide behind the summary instead of pushing the rest of the page around.
   `content-visibility` must be transitioned too, or the closed state skips the
   collapse: hidden -> visible applies for the whole opening, visible -> hidden
   only at the end of the closing. Engines without ::details-content ignore all
   of this and keep the instant toggle. */
.faq-item { interpolate-size: allow-keywords; }
/* The transition that runs while CLOSING is the one declared on the closed
   state, and it must not decelerate into zero: the reveal curve's long tail
   spent the last third of the duration crawling through the final pixels -
   the hesitation seen at the end of every close. The close curve stays near
   linear and finishes at speed, so the collapse keeps moving until it shuts;
   the open state keeps the authored decelerate settle. Same 350ms both ways. */
.faq-item::details-content {
  block-size: 0;
  overflow: clip;
  transition: block-size 350ms cubic-bezier(.4, .3, .75, .9),
              content-visibility 350ms cubic-bezier(.4, .3, .75, .9) allow-discrete;
}
.faq-item[open]::details-content {
  block-size: auto;
  transition: block-size var(--transition-reveal),
              content-visibility var(--transition-reveal) allow-discrete;
}

/* The global reduced-motion rule below only reaches *, ::before and ::after, so
   the answer states their own instant form - both directions. */
@media (prefers-reduced-motion: reduce) {
  .faq-item::details-content,
  .faq-item[open]::details-content { transition: none; }
}

/* ---------- contact / footer ---------- */
.contact-grid { display: grid; gap: var(--space-3); }
.contact-card {
  background: var(--color-panel);
  border: 1px solid var(--color-hairline);
  border-radius: var(--radius-md);
  padding: var(--space-3);
  box-shadow: var(--shadow-soft);
}
.contact-card h3 { display: flex; gap: 10px; align-items: center; }
.contact-card h3 svg { width: 22px; height: 22px; color: var(--color-gold-decorative); }
.contact-card address { font-style: normal; }

/* TASK 16: the footer becomes the dark end of the page's own ink instead of an
   unrelated grey slab, with the gold hairline as its only ornament. Audit
   finding A11Y-04 is fixed in the same pass: the link rows become real 44px
   targets instead of 20px-tall text lines with a 6px gap. */
.site-footer {
  background: var(--color-ink-deep);
  color: #DCE7E1;
  /* TASK 29: on phones the fixed bottom bar overlaps the end of the document, so
     the bar's clearance is footer padding - the same ink as the bar - instead of
     body padding, which showed as an ivory strip above the bar. --phone-nav-h is
     0px above the phone band, where the footer keeps its authored 48px. */
  padding-block: var(--space-6) calc(var(--space-6) + var(--phone-nav-h));
  border-top: 1px solid var(--color-gold-on-ink);
}
.site-footer h2 {
  color: var(--color-on-ink);
  font-size: 1.0625rem;
  letter-spacing: .02em;
  padding-bottom: 10px;
  margin: 0 0 var(--space-3);
  border-bottom: 1px solid rgba(217, 190, 122, .34);
}
.site-footer p { margin: 0 0 var(--space-3); line-height: 1.6; }
.site-footer a { color: #E7EFE9; text-decoration: none; }
.site-footer a:hover, .site-footer a:focus-visible { color: var(--color-gold-on-ink); text-decoration: underline; }
/* A11Y-04: the contact anchors are the footer's only interactive targets and the
   audit measured them at 20px tall. 24px is WCAG 2.2's minimum (2.5.8); the
   vertical padding is what adds it without disturbing the address rows. */
.site-footer address a {
  display: inline-flex;
  align-items: center;
  min-height: 24px;
  padding-block: 4px;
}
.footer-grid { display: grid; gap: var(--space-5); }
.footer-col { min-width: 0; }
.footer-partners { min-height: 1px; }

.site-footer address { font-style: normal; }
.site-footer address p { display: grid; grid-template-columns: 20px 1fr; gap: 8px; align-items: start; margin: 0 0 12px; }
.site-footer address svg { width: 18px; height: 18px; color: var(--color-gold-on-ink); margin-top: 3px; }

.social-row { display: flex; flex-wrap: wrap; gap: 10px; list-style: none; margin: 0 0 var(--space-3); padding: 0; }
.social-icon {
  display: inline-grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border-radius: 10px;
  background: rgba(255, 255, 255, .07);
  border: 1px solid rgba(217, 190, 122, .34);
  color: #EDEAE5;
}
.social-icon svg { width: 20px; height: 20px; }
.social-icon:hover, .social-icon:focus-visible { background: rgba(255, 255, 255, .16); color: #fff; }
.footer-note { font-size: .8125rem; color: var(--color-on-ink-soft); }

.copyright {
  border-top: 1px solid rgba(217, 190, 122, .28);
  margin-top: var(--space-5);
  padding-top: var(--space-3);
  font-size: .875rem;
  text-align: center;
  color: var(--color-on-ink-soft);
}

/* ---------- floating + misc ---------- */
.floating-whatsapp {
  position: fixed;
  right: 16px;
  bottom: calc(16px + var(--phone-nav-h));
  z-index: 45;
  width: 56px;
  height: 56px;
  border-radius: 50%;
  background: var(--color-whatsapp);
  color: #fff;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px solid rgba(255, 255, 255, .22);
  box-shadow: var(--shadow-raised);
}
.floating-whatsapp:hover { background: #0e5a37; color: #fff; }
.floating-whatsapp svg { width: 28px; height: 28px; }

.back-to-top {
  position: fixed;
  right: 16px;
  bottom: calc(84px + var(--phone-nav-h));
  z-index: 45;
  width: 48px;
  height: 48px;
  border-radius: 50%;
  border: 1px solid var(--color-hairline-strong);
  background: var(--color-panel);
  color: var(--color-ink);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  opacity: 0;
  visibility: hidden;
  box-shadow: var(--shadow-soft);
  transition: opacity var(--transition-fast), visibility var(--transition-fast),
              background-color var(--transition-fast);
}
.back-to-top.is-visible { opacity: 1; visibility: visible; }
.back-to-top:hover { background: var(--color-band); }
.back-to-top svg { width: 20px; height: 20px; }

/* ---------- read more control ----------
   The recovered jQuery expander clipped its block with a fixed max-height and a
   gradient fade, so the last visible line was always half-written. TASK 15 §B
   forbids that, and both sections now hide their continuation in the disclosure
   below; this rule styles only the control. The box is what
   tests/purpose-readmore.test.mjs measures, so only the ink changes here: the
   brand green at 3.5:1 becomes the link green at 6.2:1 (audit A11Y-03). */
.readmore-toggle {
  display: none;
  background: none;
  border: 0;
  padding: 8px 0;
  min-height: 44px;
  font: 600 .9375rem/1 var(--font-ui);
  color: var(--color-link);
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 3px;
}
.readmore-toggle:hover { color: var(--color-gold); }
.js .readmore-toggle { display: inline-flex; align-items: center; }

/* ---------- disclosure (Task 07 §3: grid-row height, no fixed max-height) ----------
   Collapsed = a 0fr row clipping one measured child, expanded = 1fr, so the
   transition always lands exactly on the content height. `visibility` keeps the
   hidden group out of the accessibility tree and is delayed on collapse so the
   text stays readable while the row shrinks. Without JS the block is open. */
.disclosure { display: grid; }
.js .disclosure {
  grid-template-rows: 0fr;
  transition: grid-template-rows var(--transition-reveal);
}
.js .disclosure-inner {
  min-height: 0;
  overflow: hidden;
  visibility: hidden;
  transition: visibility 0s linear 350ms;
}
.js .disclosure.is-open { grid-template-rows: 1fr; }
.js .disclosure.is-open .disclosure-inner {
  visibility: visible;
  transition-delay: 0s;
}
/* The global reduced-motion rule zeroes durations but not the visibility delay
   above, so the disclosure states its own instant form. */
@media (prefers-reduced-motion: reduce) {
  .js .disclosure, .js .disclosure-inner { transition: none; }
}

/* ---------- task 15: purpose alignment + why excerpt ----------
   A commitment list that continues inside the disclosure keeps the list's own
   8px item gap across the boundary instead of the 1em it would otherwise trail.
   The Why lead is the same sentence continued below it, so it trails nothing. */
#purpose-commitments .bullet-list { margin-bottom: 0; }
.prose .bullet-list--tail { margin-top: 8px; }
.prose .readmore-lead { margin-bottom: 0; }
/* TASK 23: the Why excerpt ends mid-sentence at "... জন্য রাখা" and the rest of
   that sentence is the same paragraph's inline tail, so the expanded text reads
   continuously with no block break. Closed, the tail leaves layout and the
   accessibility tree; the disclosure still owns the paragraphs that follow.
   Without JS (no `.js`) the tail stays visible, like the open disclosure. */
.js .readmore-lead:not(.is-open) .readmore-tail { display: none; }

/* The collapsed text column closes level with the artwork: the column stretches
   to the row and the control takes whatever free space sits above it. Where the
   text is taller than the image there is no free space, `auto` resolves to 0 and
   the control keeps its reading-order place — so phones and tablets are unchanged
   and nothing can ever overlap. */
#Purpose .split { align-items: stretch; }
#Purpose .split-main { display: flex; flex-direction: column; }
#Purpose .split-main .readmore-toggle { margin-top: auto; }

/* ---------- ayah carousel (recovered testimonial-carousel widget) ---------- */
/* ayah-bg.webp is 1366x607 and `contain` keeps it whole at every width, so the
   artwork is never cropped or stretched. From 1024px the panel locks to that
   same ratio and the image fills it edge to edge; below it the card grows with
   its content and #EEF0E2 — the cream sampled from the artwork itself — shows
   above and below. Pixel map of the artwork leaves the middle columns and
   everything above y=405/607 free of ornament, which the padding honours. */
.ayah-carousel {
  width: 100%;
  max-width: 1200px;
  margin-inline: auto;
  display: grid;
  justify-items: center;
  align-content: center;
  text-align: center;
  padding: clamp(28px, 4%, 64px) clamp(20px, 8%, 96px) clamp(56px, 10%, 160px);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background-color: #EEF0E2;
  background-image: url('../assets/images/ayah-bg.webp');
  background-position: center;
  background-repeat: no-repeat;
  background-size: contain;
}
.ayah-track { position: relative; min-height: 272px; }
.ayah-slide {
  position: absolute;
  inset: 0;
  opacity: 0;
  visibility: hidden;
  transition: opacity 600ms ease;
  display: grid;
  gap: var(--space-2);
  align-content: center;
}
.ayah-slide.is-active { position: relative; opacity: 1; visibility: visible; }
.ayah-arabic {
  font-family: var(--font-quran);
  font-size: clamp(1.5rem, 4.4vw, 2.375rem);
  line-height: 2.1;
  color: var(--color-ink);
  unicode-bidi: isolate;
  margin: 0;
}
.ayah-bangla { color: var(--color-text); font-family: var(--font-bn); line-height: 1.9; margin: 0; }
/* Stays on the authored green, not the theme gold: the reference line sits on the
   artwork itself below 640px (TASK 13), where #7A6231 measured 4.21-4.39:1 and so
   is under AA for this 12.6-15.4px text. tests/ayah-panel.test.mjs re-measures it. */
.ayah-ref { color: var(--color-whatsapp); font-weight: 600; font-size: .9375rem; margin: 0; }
.ayah-controls {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  margin-top: var(--space-3);
}
.ayah-btn {
  width: 48px;
  height: 48px;
  border-radius: 50%;
  border: 1px solid rgba(14, 58, 44, .22);
  background: rgba(255, 255, 255, .86);
  color: var(--color-ink);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  box-shadow: var(--shadow-soft);
}
.ayah-btn:hover { background: #fff; border-color: var(--color-ink); }
.ayah-btn svg { width: 20px; height: 20px; }
.ayah-count { color: var(--color-ink); font-size: .875rem; min-width: 4ch; font-variant-numeric: tabular-nums; }

/* reveal (JS-gated: content visible without JS) */
.js .reveal { opacity: 0; transform: translateY(10px); }
.js .reveal.is-revealed {
  opacity: 1;
  transform: none;
  transition: opacity var(--transition-reveal), transform var(--transition-reveal);
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
  }
  .js .reveal { opacity: 1; transform: none; }
}

/* ---------- FREE TRIAL FORM - VISUAL LOCK (TASK 16 §1C) ----------
   The theme refactor moves `body` to --color-text and every heading to
   --color-ink. Both reach the recovered form block by inheritance, and because
   most of that subtree declares no colour of its own - and its container borders
   default to currentColor - the whole block would silently drift with it.
   TASK 16 §1C freezes the form's appearance, so the inherited values are pinned
   back here to exactly what the November 2025 markup computed, through the legacy
   tokens whose values are themselves unchanged. tests/form-lock.test.mjs proves
   it: it fingerprints getComputedStyle() over 42 selectors x 36 properties at
   390/1024/1440 against a golden taken before any of this work and requires zero
   drift. The only selectors allowed to move are the two lines of hero prose above
   the green box, #hero-heading and .lead, which follow the new type system.
   Placed last so the id and class selectors outrank the element-level rules
   above without needing !important. */
.trial-card { color: var(--color-foreground); }
.trial-title { color: var(--color-foreground-strong); }
#hero-heading { color: var(--color-ink); }
.lead { color: var(--color-text); }
