/* =========================================================================
   LEADS Academy — leadsacademy.org
   One stylesheet. Tokens first, then primitives, then components.

   Design language: THE ASCENT. The logo's chevron is an upward arrow, and the
   program is a 25-week climb. So the site climbs: it starts in the dark at
   week 1 and the brand gradient rises through it. The chevron recurs at four
   scales — the logo's "A", section markers, the route rail, and list bullets.

   Colour rules that are NOT negotiable (verified with a contrast checker):
     - Raw brand magenta #FC0084 on white is 3.84:1 → FAILS AA for text.
       It may be used for large display text, graphics and fills only.
     - White on #FC0084 is 3.84:1 → FAILS. Buttons use --magenta-600 #D6006F
       (5.14:1), which is the deepest magenta that still reads as brand.
     - On dark, the raw brand colours pass (magenta 5.02:1), which is why the
       site is dark-first.
   ========================================================================= */

/* ---------- tokens ---------- */

:root {
  /* Brand primitives, sampled from academy-bright.png */
  --magenta: #fc0084;
  --violet: #8400cc;
  --blue: #0018f0;

  /* Accessible ramps derived from those primitives */
  --magenta-200: #ffa6ce;
  --magenta-300: #ff7ab8;
  --magenta-600: #d6006f;
  --magenta-700: #b8005f;
  --violet-300: #c79bff;
  --violet-600: #6d00a8;
  --violet-700: #6a00a3;
  --blue-200: #b3c4ff;
  --blue-300: #8aa4ff;
  --blue-700: #0014c4;

  /* Neutrals — the logo's graphite, extended into a full ramp */
  --ink-950: #070a12;
  --ink-900: #0a0e1a;
  --ink-850: #0d121f;
  --ink-800: #111726;
  --ink-700: #1a2233;
  --ink-600: #263048;
  --slate-400: #7a8aa6;
  --slate-300: #9aa7bf;
  --slate-200: #c7d0e0;
  --slate-100: #e6eaf2;
  --paper: #f7f8fa;
  --white: #fff;

  /* Semantic — dark is the default theme */
  --bg: var(--ink-900);
  --bg-raised: var(--ink-850);
  --surface: var(--ink-800);
  --surface-2: var(--ink-700);
  --border: #202a3d;
  --border-strong: #2c3852;
  --text: #eef1f7;
  --text-muted: var(--slate-300);
  --text-dim: var(--slate-400);
  --accent: var(--magenta-300);
  --accent-2: var(--violet-300);
  --accent-3: var(--blue-300);
  --focus: #ffd23f;

  --grad: linear-gradient(100deg, var(--magenta) 0%, var(--violet) 52%, var(--blue) 100%);
  --grad-btn: linear-gradient(100deg, var(--magenta-600) 0%, var(--violet-600) 55%, var(--blue) 100%);
  --grad-text: linear-gradient(100deg, var(--magenta-300) 0%, var(--violet-300) 50%, var(--blue-300) 100%);

  /* Type — system stacks only. No webfont, no CDN, no render-blocking. */
  --font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue",
    Arial, "Noto Sans", sans-serif;
  --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas,
    "Liberation Mono", monospace;

  /* Bangla. Shipping a webfont would cost ~200KB+ and break the no-external-asset
     rule, so this is a system stack: Noto Sans Bengali (Android/Linux/Chrome OS),
     Nirmala UI (Windows), Kohinoor Bangla / Bangla Sangam MN (macOS, iOS).
     The Latin faces lead so that English words inside Bangla prose — DevOps, AWS,
     Kubernetes — keep the same shapes they have on the English pages. */
  --font-bn: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
    "Noto Sans Bengali", "Nirmala UI", "Kohinoor Bangla", "Bangla Sangam MN",
    "Shonar Bangla", Vrinda, "Mukti Narrow", sans-serif;

  /* Fluid scale, 1.25 ratio at the top end */
  --t-xs: 0.75rem;
  --t-sm: 0.875rem;
  --t-base: 1rem;
  --t-lg: 1.125rem;
  --t-xl: clamp(1.25rem, 1.1rem + 0.5vw, 1.4rem);
  --t-2xl: clamp(1.5rem, 1.3rem + 0.9vw, 1.9rem);
  --t-3xl: clamp(1.9rem, 1.5rem + 1.7vw, 2.6rem);
  --t-4xl: clamp(2.1rem, 1.5rem + 2.6vw, 3.1rem);
  --t-5xl: clamp(2.3rem, 1.6rem + 2.9vw, 3.4rem);

  --sp-1: 0.25rem;
  --sp-2: 0.5rem;
  --sp-3: 0.75rem;
  --sp-4: 1rem;
  --sp-5: 1.5rem;
  --sp-6: 2rem;
  --sp-7: 3rem;
  --sp-8: 4rem;
  --sp-9: 6rem;
  --sp-10: 8rem;

  --r-sm: 4px;
  --r: 8px;
  --r-lg: 14px;
  --r-xl: 22px;
  --r-full: 999px;

  --shadow: 0 1px 2px rgb(0 0 0 / 0.3), 0 8px 24px -8px rgb(0 0 0 / 0.5);
  --shadow-lg: 0 2px 4px rgb(0 0 0 / 0.3), 0 24px 60px -12px rgb(0 0 0 / 0.65);
  --glow: 0 0 0 1px rgb(252 0 132 / 0.25), 0 12px 40px -12px rgb(252 0 132 / 0.45);

  --wrap: 1140px;
  --wrap-narrow: 720px;
  --ease: cubic-bezier(0.22, 1, 0.36, 1);
}

/* Light theme. The logo lives on near-white paper, so this is the "brochure"
   face of the brand — used when the visitor's OS asks for it. */
@media (prefers-color-scheme: light) {
  :root:not([data-theme="dark"]) {
    --bg: var(--white);
    --bg-raised: var(--paper);
    --surface: var(--paper);
    --surface-2: #eef1f6;
    --border: #dfe4ec;
    --border-strong: #c9d1de;
    --text: #0f172a;
    --text-muted: #475569;
    --text-dim: #586478;
    --accent: var(--magenta-700);
    --accent-2: var(--violet-700);
    --accent-3: var(--blue-700);
    --focus: #7a4b00;
    --grad-text: linear-gradient(100deg, var(--magenta-700) 0%, var(--violet-700) 50%, var(--blue-700) 100%);
    --shadow: 0 1px 2px rgb(15 23 42 / 0.06), 0 8px 24px -8px rgb(15 23 42 / 0.12);
    --shadow-lg: 0 2px 4px rgb(15 23 42 / 0.06), 0 24px 60px -12px rgb(15 23 42 / 0.18);
    --glow: 0 0 0 1px rgb(214 0 111 / 0.2), 0 12px 40px -12px rgb(214 0 111 / 0.3);
  }
}

/* Explicit override wins over the OS in both directions. */
:root[data-theme="light"] {
  --bg: var(--white);
  --bg-raised: var(--paper);
  --surface: var(--paper);
  --surface-2: #eef1f6;
  --border: #dfe4ec;
  --border-strong: #c9d1de;
  --text: #0f172a;
  --text-muted: #475569;
  /* #64748b lands at 4.48:1 on the paper surface (--bg-raised) the footer uses
     — just under AA. Darkened to clear it on both white and paper. */
  --text-dim: #586478;
  --accent: var(--magenta-700);
  --accent-2: var(--violet-700);
  --accent-3: var(--blue-700);
  --focus: #7a4b00;
  --grad-text: linear-gradient(100deg, var(--magenta-700) 0%, var(--violet-700) 50%, var(--blue-700) 100%);
  --shadow: 0 1px 2px rgb(15 23 42 / 0.06), 0 8px 24px -8px rgb(15 23 42 / 0.12);
  --shadow-lg: 0 2px 4px rgb(15 23 42 / 0.06), 0 24px 60px -12px rgb(15 23 42 / 0.18);
  --glow: 0 0 0 1px rgb(214 0 111 / 0.2), 0 12px 40px -12px rgb(214 0 111 / 0.3);
}

:root[data-theme="dark"] {
  color-scheme: dark;
}

:root[data-theme="light"] {
  color-scheme: light;
}

/* ---------- reset ---------- */

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

* {
  margin: 0;
}

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: 5.5rem; /* clears the sticky header on anchor jumps */
}

body {
  font-family: var(--font);
  font-size: var(--t-base);
  line-height: 1.65;
  color: var(--text);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
}

img,
svg,
video {
  display: block;
  max-width: 100%;
}

img {
  height: auto;
}

input,
button,
textarea,
select {
  font: inherit;
  color: inherit;
}

button {
  cursor: pointer;
  background: none;
  border: 0;
}

h1,
h2,
h3,
h4 {
  line-height: 1.12;
  font-weight: 780;
  letter-spacing: -0.022em;
  text-wrap: balance;
}

p {
  text-wrap: pretty;
}

a {
  color: var(--accent);
  text-decoration-color: color-mix(in srgb, currentColor 40%, transparent);
  text-underline-offset: 0.2em;
}

a:hover {
  text-decoration-color: currentColor;
}

:focus-visible {
  outline: 3px solid var(--focus);
  outline-offset: 3px;
  border-radius: var(--r-sm);
}

::selection {
  background: var(--magenta);
  color: #fff;
}

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

/* ---------- layout primitives ---------- */

/* Grid and flex children default to min-width:auto, so any child holding
   wide unwrappable content (the terminal blocks use white-space:pre) grows
   its track past the viewport. On mobile that clipped the hero and pushed the
   nav toggle off-screen. min-width:0 lets the track shrink and hands the
   overflow to the element that knows how to scroll it. */
.hero__grid > *,
.grid-2 > *,
.card-grid > *,
.stats > *,
.footer__grid > * {
  min-width: 0;
}

.wrap {
  width: min(100% - 2.5rem, var(--wrap));
  margin-inline: auto;
}

.wrap-narrow {
  width: min(100% - 2.5rem, var(--wrap-narrow));
  margin-inline: auto;
}

/* Two adjacent sections each contribute padding, so the gap between them is
   double this. Keep it modest or the page reads as empty rather than airy. */
.section {
  padding-block: clamp(var(--sp-7), 4.5vw, var(--sp-8));
}

.section-tight {
  padding-block: clamp(var(--sp-6), 3vw, var(--sp-7));
}

.skip {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 200;
  padding: var(--sp-3) var(--sp-5);
  background: var(--surface);
  color: var(--text);
  border: 2px solid var(--accent);
  border-radius: 0 0 var(--r) 0;
  font-weight: 600;
}

.skip:focus {
  left: 0;
}

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

/* ---------- the chevron system ----------
   Application 1 of 4: the logo lockup, where the chevron IS the letter A. */

.logo {
  display: inline-flex;
  align-items: center;
  color: var(--text);
  text-decoration: none;
  flex: none;
}

.logo:hover {
  text-decoration: none;
}

.logo__lock {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
}

/* Flex row so the chevron sits *inside* the wordmark as the letter A.
   The global reset makes svg display:block, which would otherwise break
   LE / DS onto separate lines. */
.logo__word {
  display: flex;
  align-items: center;
  gap: 0.06em;
  font-weight: 800;
  font-size: 1.3rem;
  letter-spacing: 0.07em;
  line-height: 1;
  white-space: nowrap;
}

.logo__mark {
  width: 0.8em;
  height: 0.92em;
  flex: none;
}

.logo__sub {
  font-size: 0.46rem;
  font-weight: 700;
  letter-spacing: 0.4em;
  color: var(--text-dim);
  margin-top: 0.42em;
  line-height: 1;
  white-space: nowrap;
}

/* Application 2: section eyebrow markers. */
.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  font-size: var(--t-xs);
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--text-dim);
  margin-bottom: var(--sp-4);
}

.eyebrow::before {
  content: "";
  width: 0.7em;
  height: 0.8em;
  background: var(--grad);
  clip-path: polygon(50% 0%, 100% 100%, 50% 66%, 0% 100%);
  flex: none;
}

/* Application 3: gradient rule, the logo's swoosh flattened into a divider. */
.rule {
  height: 2px;
  border: 0;
  background: var(--grad);
  opacity: 0.5;
  margin-block: var(--sp-7);
}

/* Application 4: list bullets. */
.chev-list {
  list-style: none;
  padding: 0;
  display: grid;
  gap: var(--sp-3);
}

.chev-list li {
  position: relative;
  padding-left: 1.6rem;
  color: var(--text-muted);
}

.chev-list li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.55em;
  width: 0.62rem;
  height: 0.7rem;
  background: var(--grad);
  clip-path: polygon(50% 0%, 100% 100%, 50% 66%, 0% 100%);
}

/* ---------- buttons ---------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  padding: 0.82rem 1.45rem;
  border-radius: var(--r-full);
  font-weight: 680;
  font-size: var(--t-base);
  letter-spacing: -0.01em;
  text-decoration: none;
  border: 1px solid transparent;
  transition: transform 0.18s var(--ease), box-shadow 0.18s var(--ease),
    background-color 0.18s var(--ease), border-color 0.18s var(--ease);
  white-space: nowrap;
}

.btn:hover {
  text-decoration: none;
  transform: translateY(-2px);
}

.btn:active {
  transform: translateY(0);
}

/* White on --grad-btn is 5.14:1 at its lightest stop. Do not lighten it. */
.btn-primary {
  background: var(--grad-btn);
  color: #fff;
  box-shadow: var(--glow);
}

.btn-primary:hover {
  box-shadow: 0 0 0 1px rgb(252 0 132 / 0.4), 0 18px 50px -12px rgb(252 0 132 / 0.6);
}

.btn-secondary {
  background: var(--surface);
  color: var(--text);
  border-color: var(--border-strong);
}

.btn-secondary:hover {
  border-color: var(--accent);
  background: var(--surface-2);
}

.btn-ghost {
  background: transparent;
  color: var(--text-muted);
  border-color: var(--border);
  padding: 0.6rem 1.1rem;
}

.btn-ghost:hover {
  color: var(--text);
  border-color: var(--border-strong);
}

.btn-lg {
  padding: 1rem 1.9rem;
  font-size: var(--t-lg);
}

.btn-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-3);
}

/* ---------- header ---------- */

.site-header {
  position: sticky;
  top: 0;
  z-index: 100;
  background: color-mix(in srgb, var(--bg) 82%, transparent);
  backdrop-filter: saturate(1.5) blur(14px);
  border-bottom: 1px solid transparent;
  transition: border-color 0.25s var(--ease), background-color 0.25s var(--ease);
}

.site-header[data-scrolled="true"] {
  border-bottom-color: var(--border);
  background: color-mix(in srgb, var(--bg) 94%, transparent);
}

.site-header__inner {
  display: flex;
  align-items: center;
  gap: var(--sp-5);
  min-height: 4.5rem;
}

.nav {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  margin-left: auto;
  order: 2;
}

.nav a:not(.btn) {
  position: relative;
  padding: 0.5rem 0.75rem;
  border-radius: var(--r);
  font-size: var(--t-sm);
  font-weight: 560;
  color: var(--text-muted);
  text-decoration: none;
}

.nav a:not(.btn):hover {
  color: var(--text);
  background: var(--surface);
}

.nav a[aria-current="page"] {
  color: var(--text);
}

.nav a[aria-current="page"]::after {
  content: "";
  position: absolute;
  left: 0.75rem;
  right: 0.75rem;
  bottom: 0.15rem;
  height: 2px;
  background: var(--grad);
  border-radius: 2px;
}

.nav__cta {
  margin-left: var(--sp-3);
}

/* ---------- language switcher ----------
   Real links to the equivalent page, not JS state: each language has its own
   URL, so this works with JS off, can be shared, and can carry hreflang. */

.lang {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  padding: 2px;
  border: 1px solid var(--border);
  border-radius: var(--r-full);
  background: var(--surface);
  flex: none;
  order: 3;
}

.lang__opt {
  display: inline-flex;
  align-items: center;
  padding: 0.28rem 0.62rem;
  border-radius: var(--r-full);
  font-size: var(--t-xs);
  font-weight: 640;
  line-height: 1.5;
  color: var(--text-dim);
  text-decoration: none;
  white-space: nowrap;
  transition: color 0.15s var(--ease), background-color 0.15s var(--ease);
}

.lang__opt:hover {
  color: var(--text);
  text-decoration: none;
}

/* The current language is marked with aria-current, so the style follows the
   semantics rather than a duplicate class. */
.lang__opt[aria-current="true"] {
  background: var(--grad-btn);
  color: #fff;
}

.lang__opt[lang="bn"] {
  font-family: var(--font-bn);
  font-size: 0.8rem;
}

/* The theme toggle lives in the header bar, not inside #primary-nav: the nav
   collapses behind the hamburger under 900px, which made the toggle
   unreachable on a phone. On desktop the nav takes the auto margin; on mobile
   the toggle does, so it sits next to the hamburger. */
.theme-toggle {
  order: 4;
}

.nav-toggle {
  display: none;
  order: 4;
  padding: 0.5rem;
  border-radius: var(--r);
  border: 1px solid var(--border-strong);
  color: var(--text);
}

.nav-toggle svg {
  width: 1.4rem;
  height: 1.4rem;
}

@media (max-width: 900px) {
  .nav-toggle {
    display: inline-flex;
  }

  /* Nav is hidden behind the hamburger here, so the toggle claims the space
     and stays on screen. */
  .theme-toggle {
    margin-left: auto;
  }

  .nav {
    position: fixed;
    inset: 4.5rem 0 auto;
    flex-direction: column;
    align-items: stretch;
    gap: var(--sp-1);
    padding: var(--sp-4) 1.25rem var(--sp-6);
    background: var(--bg-raised);
    border-bottom: 1px solid var(--border);
    box-shadow: var(--shadow-lg);
    margin-left: 0;
    display: none;
  }

  .nav[data-open="true"] {
    display: flex;
  }

  .nav a:not(.btn) {
    padding: 0.85rem 0.75rem;
    font-size: var(--t-lg);
    border-bottom: 1px solid var(--border);
    border-radius: 0;
  }

  .nav a[aria-current="page"]::after {
    display: none;
  }

  .nav a[aria-current="page"] {
    color: var(--accent);
  }

  .nav__cta {
    margin-left: 0;
    margin-top: var(--sp-3);
  }

  .btn {
    justify-content: center;
  }
}

/* ---------- language hint ----------
   English is the default and we never auto-redirect. But if the browser asks for
   Bangla, offer it once, quietly, and let it be dismissed for good. JS-only
   enhancement: hidden until script decides to show it, so no-JS visitors and
   crawlers never see it. */

.lang-hint {
  display: none;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4);
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  font-family: var(--font-bn);
  font-size: var(--t-sm);
}

.lang-hint[data-show="true"] {
  display: flex;
}

.lang-hint__inner {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  flex-wrap: wrap;
  width: min(100% - 2.5rem, var(--wrap));
  margin-inline: auto;
}

.lang-hint__cta {
  font-weight: 700;
  color: var(--accent);
}

.lang-hint__close {
  margin-left: auto;
  padding: 0.2rem 0.5rem;
  border-radius: var(--r);
  color: var(--text-dim);
  font-size: var(--t-xs);
  border: 1px solid var(--border);
  flex: none;
}

.lang-hint__close:hover {
  color: var(--text);
  border-color: var(--border-strong);
}

/* ---------- hero ---------- */

.hero {
  position: relative;
  padding-block: clamp(var(--sp-7), 6vw, var(--sp-9)) clamp(var(--sp-6), 4vw, var(--sp-7));
  overflow: hidden;
}

/* The ascent: light rising from the bottom of the climb. */
.hero::before {
  content: "";
  position: absolute;
  inset: -30% -10% auto;
  height: 120%;
  background: radial-gradient(
      60% 55% at 50% 88%,
      color-mix(in srgb, var(--violet) 26%, transparent) 0%,
      transparent 70%
    ),
    radial-gradient(
      42% 40% at 76% 30%,
      color-mix(in srgb, var(--blue) 18%, transparent) 0%,
      transparent 72%
    ),
    radial-gradient(
      38% 38% at 22% 26%,
      color-mix(in srgb, var(--magenta) 15%, transparent) 0%,
      transparent 70%
    );
  pointer-events: none;
  z-index: -1;
}

.hero__grid {
  display: grid;
  gap: clamp(var(--sp-6), 5vw, var(--sp-8));
  align-items: center;
  grid-template-columns: 1fr;
}

@media (min-width: 960px) {
  .hero__grid {
    grid-template-columns: 1.05fr 0.95fr;
  }
}

.hero h1 {
  font-size: var(--t-5xl);
  letter-spacing: -0.035em;
  font-weight: 800;
}

.hero__lede {
  font-size: var(--t-xl);
  color: var(--text-muted);
  margin-top: var(--sp-5);
  max-width: 46ch;
}

.grad-text {
  background: var(--grad-text);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

/* Windows High Contrast / forced colours strips background-clip text to
   nothing. Give it back a real colour. */
@media (forced-colors: active) {
  .grad-text {
    -webkit-text-fill-color: currentColor;
    color: CanvasText;
    background: none;
  }
}

.hero__note {
  margin-top: var(--sp-4);
  font-size: var(--t-sm);
  color: var(--text-dim);
}

/* ---------- stat strip ---------- */

.stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
  gap: 1px;
  background: var(--border);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  overflow: hidden;
}

.stat {
  background: var(--bg);
  padding: var(--sp-5) var(--sp-4);
  text-align: center;
}

.stat__n {
  font-size: var(--t-3xl);
  font-weight: 800;
  letter-spacing: -0.04em;
  font-variant-numeric: tabular-nums;
  background: var(--grad-text);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  line-height: 1;
}

@media (forced-colors: active) {
  .stat__n {
    -webkit-text-fill-color: currentColor;
    color: CanvasText;
    background: none;
  }
}

.stat__l {
  display: block;
  margin-top: var(--sp-2);
  font-size: var(--t-xs);
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-dim);
}

/* ---------- cards ---------- */

.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  padding: var(--sp-5);
  transition: border-color 0.2s var(--ease), transform 0.2s var(--ease);
}

.card h3 {
  font-size: var(--t-lg);
  margin-bottom: var(--sp-2);
}

.card p {
  color: var(--text-muted);
  font-size: var(--t-sm);
}

/* 20rem keeps six cards on a tidy 3x2 at desktop rather than a ragged 4+2. */
.card-grid {
  display: grid;
  gap: var(--sp-4);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 20rem), 1fr));
}

/* Four-item groups: auto-fit would leave a 3+1 orphan, so go 4-up on wide
   screens and 2x2 on mid — never a lone card on its own row. */
.card-grid--4 {
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 13.5rem), 1fr));
}

@media (min-width: 600px) and (max-width: 1000px) {
  .card-grid--4 {
    grid-template-columns: 1fr 1fr;
  }
}

/* Card-as-link: the whole card is the hit target, but only the title should
   carry the link affordance. Without this the <a> underlines the body copy too. */
.card--link {
  display: block;
  text-decoration: none;
  color: inherit;
}

.card--link h3 {
  color: var(--accent);
}

.card--link p {
  color: var(--text-muted);
}

.card--link:hover {
  border-color: var(--border-strong);
  transform: translateY(-3px);
}

.card--link:hover h3 {
  text-decoration: underline;
  text-underline-offset: 0.2em;
}

/* ---------- terminal ---------- */

/* Every artifact gets a plain-English caption directly above it. The reader is
   someone whose only stated prerequisite is basic computer literacy — the site
   must never make them feel unqualified to read it. */
.term__cap {
  font-size: var(--t-sm);
  color: var(--text-muted);
  margin-bottom: var(--sp-3);
  max-width: 46ch;
}

.term__cap--after {
  margin: var(--sp-3) 0 0;
  color: var(--text-dim);
  font-size: var(--t-xs);
}

.term__cap strong {
  font-family: var(--mono);
  color: var(--text);
}

/* The terminal is machine output, so it stays dark in BOTH themes and never
   takes brand colour. That means it must not borrow theme tokens either —
   --border-strong is near-white in light mode and would paint a 12.9:1
   hairline around a black box. These values are fixed on purpose. */
.term {
  background: var(--ink-950);
  border: 1px solid #232c42;
  border-radius: var(--r-lg);
  overflow: hidden;
  box-shadow: var(--shadow-lg);
  font-family: var(--mono);
  font-size: 0.8rem;
  line-height: 1.75;
  color-scheme: dark;
}

.term__bar {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  padding: 0.6rem var(--sp-4);
  background: #0e1424;
  border-bottom: 1px solid #1c2438;
}

.term__dot {
  width: 0.62rem;
  height: 0.62rem;
  border-radius: 50%;
  flex: none;
}

.term__title {
  margin-left: var(--sp-2);
  font-size: 0.7rem;
  color: var(--slate-400);
  letter-spacing: 0.04em;
}

.term__body {
  padding: var(--sp-4);
  margin: 0;
  overflow-x: auto;
  color: var(--slate-200);
  white-space: pre;
  tab-size: 2;
}

.term__body::-webkit-scrollbar {
  height: 8px;
}

.term__body::-webkit-scrollbar-thumb {
  background: #2c3852; /* fixed: the terminal is dark in both themes */
  border-radius: var(--r-full);
}

.c-dim {
  color: var(--slate-400);
}

.c-ok {
  color: #4ade80;
}

.c-warn {
  color: #fbbf24;
}

.c-mag {
  color: var(--magenta-300);
}

.c-blue {
  color: var(--blue-300);
}

.c-vio {
  color: var(--violet-300);
}

/* ---------- the journey: the hero's ascent ----------
   The chevron points up and the program is a climb, so the hero shows the
   climb itself. Same idea as .route on /curriculum/, at a glance. */

.journey {
  position: relative;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-xl);
  padding: var(--sp-5) var(--sp-5) var(--sp-4);
  box-shadow: var(--shadow-lg);
}

.journey__cap {
  font-size: var(--t-xs);
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-dim);
  margin-bottom: var(--sp-4);
}

.journey__list {
  list-style: none;
  margin: 0;
  padding: 0;
  position: relative;
}

/* The rail climbs: deep blue at the bottom of the journey, magenta at the top
   of it — the logo's gradient, stood upright. */
.journey__list::before {
  content: "";
  position: absolute;
  left: 0.4rem;
  top: 0.55rem;
  bottom: 1.6rem;
  width: 2px;
  background: linear-gradient(to bottom, var(--blue), var(--violet), var(--magenta));
  opacity: 0.55;
  border-radius: 2px;
}

.journey__step {
  position: relative;
  padding: 0 0 var(--sp-4) 1.9rem;
}

.journey__step:last-child {
  padding-bottom: 0;
}

.journey__step::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.3rem;
  width: 0.85rem;
  height: 0.85rem;
  border-radius: 50%;
  background: var(--surface);
  border: 2px solid var(--border-strong);
}

/* The last milestone is the payoff — mark it with the brand, not a grey dot. */
.journey__step--last::before {
  background: var(--grad-btn);
  border-color: transparent;
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--magenta) 18%, transparent);
}

.journey__wk {
  display: block;
  font-family: var(--mono);
  font-size: 0.68rem;
  letter-spacing: 0.06em;
  color: var(--text-dim);
}

.journey__t {
  display: block;
  font-weight: 680;
  font-size: var(--t-base);
  color: var(--text);
  margin-top: 0.1rem;
}

.journey__d {
  display: block;
  font-size: var(--t-sm);
  color: var(--text-muted);
  margin-top: 0.15rem;
}

.journey__foot {
  margin-top: var(--sp-4);
  padding-top: var(--sp-4);
  border-top: 1px solid var(--border);
  font-size: var(--t-sm);
  color: var(--text-muted);
}

.journey__foot strong {
  color: var(--text);
}

/* ---------- numbered steps ---------- */

.steps {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: var(--sp-4);
}

.steps__item {
  display: flex;
  gap: var(--sp-4);
  align-items: flex-start;
}

.steps__n {
  flex: none;
  width: 1.7rem;
  height: 1.7rem;
  border-radius: 50%;
  display: grid;
  place-items: center;
  font-size: var(--t-xs);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--text-muted);
  background: var(--bg);
  border: 1px solid var(--border-strong);
}

.steps__item--last .steps__n {
  background: var(--grad-btn);
  border-color: transparent;
  color: #fff;
}

.steps__b {
  display: block;
}

.steps__t {
  display: block;
  font-weight: 640;
  color: var(--text);
}

.steps__d {
  display: block;
  font-size: var(--t-sm);
  color: var(--text-muted);
  margin-top: 0.1rem;
}

/* ---------- the route: 25 weeks as a climb ---------- */

.route {
  position: relative;
  padding-left: 2.6rem;
}

/* The rail the whole climb hangs from. */
.route::before {
  content: "";
  position: absolute;
  left: 0.72rem;
  top: 0.4rem;
  bottom: 0.4rem;
  width: 2px;
  background: linear-gradient(
    to bottom,
    var(--blue) 0%,
    var(--violet) 55%,
    var(--magenta) 100%
  );
  opacity: 0.5;
  border-radius: 2px;
}

.week {
  position: relative;
  margin-bottom: var(--sp-3);
}

.week::before {
  content: "";
  position: absolute;
  left: -2.6rem;
  top: 1.05rem;
  width: 1.5rem;
  height: 1.5rem;
  border-radius: 50%;
  background: var(--bg);
  border: 2px solid var(--border-strong);
  transition: border-color 0.2s var(--ease), background-color 0.2s var(--ease);
}

.week[open]::before,
.week:hover::before {
  border-color: var(--accent);
}

.week__head {
  display: flex;
  align-items: baseline;
  gap: var(--sp-3);
  padding: var(--sp-4) var(--sp-4) var(--sp-4) 0;
  cursor: pointer;
  list-style: none;
  border-bottom: 1px solid var(--border);
}

.week__head::-webkit-details-marker {
  display: none;
}

.week__n {
  font-family: var(--mono);
  font-size: var(--t-xs);
  font-weight: 700;
  letter-spacing: 0.08em;
  color: var(--text-dim);
  flex: none;
  min-width: 3.6rem;
}

.week[open] .week__n {
  color: var(--accent);
}

.week__t {
  font-weight: 640;
  font-size: var(--t-base);
  color: var(--text);
  flex: 1;
}

.week__chev {
  flex: none;
  width: 0.8rem;
  height: 0.8rem;
  background: var(--text-dim);
  clip-path: polygon(50% 0%, 100% 100%, 50% 66%, 0% 100%);
  transform: rotate(180deg);
  transition: transform 0.25s var(--ease), background-color 0.2s var(--ease);
}

.week[open] .week__chev {
  transform: rotate(0deg);
  background: var(--grad);
}

.week__body {
  padding: var(--sp-4) 0 var(--sp-5);
  border-bottom: 1px solid var(--border);
}

.week__body > p:first-child {
  color: var(--text-muted);
  font-size: var(--t-sm);
  margin-bottom: var(--sp-4);
}

.week__body h4 {
  font-size: var(--t-xs);
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--text-dim);
  margin: var(--sp-4) 0 var(--sp-2);
}

.week__body h4:first-of-type {
  margin-top: 0;
}

.week__body ul {
  columns: 2;
  column-gap: var(--sp-5);
  font-size: var(--t-sm);
}

@media (max-width: 700px) {
  .week__body ul {
    columns: 1;
  }
}

/* Same reason as .callout — a bar, not border-image. */
.lab-note {
  position: relative;
  margin-top: var(--sp-4);
  padding: var(--sp-4) var(--sp-4) var(--sp-4) calc(var(--sp-4) + 2px);
  background: var(--bg-raised);
  border-radius: var(--r);
  overflow: hidden;
  font-size: var(--t-sm);
  color: var(--text-muted);
}

.lab-note::before {
  content: "";
  position: absolute;
  inset: 0 auto 0 0;
  width: 2px;
  background: var(--grad);
}

.lab-note strong {
  color: var(--text);
}

/* ---------- phase banner ---------- */

.phase {
  display: flex;
  align-items: center;
  gap: var(--sp-4);
  margin: var(--sp-8) 0 var(--sp-5);
  padding-bottom: var(--sp-3);
  border-bottom: 1px solid var(--border);
}

.phase:first-of-type {
  margin-top: 0;
}

.phase__n {
  font-size: var(--t-xs);
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  padding: 0.3rem 0.7rem;
  border-radius: var(--r-full);
  /* --grad, not --grad-btn, would put white on #FC0084 at 3.84:1. Any gradient
     carrying white text uses the deepened stops. See the header note. */
  background: var(--grad-btn);
  color: #fff;
  flex: none;
}

.phase__t {
  font-size: var(--t-xl);
  font-weight: 720;
}

.phase__w {
  margin-left: auto;
  font-family: var(--mono);
  font-size: var(--t-xs);
  color: var(--text-dim);
  flex: none;
}

/* ---------- prose ---------- */

.prose h2 {
  font-size: var(--t-2xl);
  margin: var(--sp-7) 0 var(--sp-4);
}

.prose h3 {
  font-size: var(--t-lg);
  margin: var(--sp-5) 0 var(--sp-2);
}

.prose p,
.prose li {
  color: var(--text-muted);
}

.prose p {
  margin-bottom: var(--sp-4);
}

.prose ul,
.prose ol {
  margin: 0 0 var(--sp-4) 1.1rem;
  display: grid;
  gap: var(--sp-2);
}

.prose > :first-child {
  margin-top: 0;
}

.prose strong {
  color: var(--text);
}

.lead {
  font-size: var(--t-xl);
  color: var(--text-muted);
}

/* ---------- section heads ---------- */

/* ch units track the *heading* font here, which is far larger than the body
   text below it — 54ch made section headings wrap much narrower than their own
   supporting paragraph. Constrain by the heading instead. */
.head {
  max-width: 42rem;
  margin-bottom: var(--sp-6);
}

.head h2 {
  max-width: 18ch;
}

.head--center h2 {
  max-width: none;
}

.head h2 {
  font-size: var(--t-3xl);
}

.head p {
  margin-top: var(--sp-4);
  color: var(--text-muted);
  font-size: var(--t-lg);
}

.head--center {
  margin-inline: auto;
  text-align: center;
}

/* ---------- page hero ---------- */

.page-hero {
  padding-block: clamp(var(--sp-6), 4vw, var(--sp-8)) var(--sp-6);
  border-bottom: 1px solid var(--border);
  background: radial-gradient(
    70% 100% at 50% 0%,
    color-mix(in srgb, var(--violet) 12%, transparent),
    transparent 70%
  );
}

.page-hero h1 {
  font-size: var(--t-4xl);
}

.page-hero p {
  margin-top: var(--sp-4);
  font-size: var(--t-lg);
  color: var(--text-muted);
  max-width: 60ch;
}

/* ---------- callout ---------- */

/* A pseudo-element bar, not border-image: border-image paints every side that
   has a width, which drew a full gradient rectangle instead of a left accent. */
.callout {
  position: relative;
  border: 1px solid var(--border);
  background: var(--surface);
  padding: var(--sp-5) var(--sp-5) var(--sp-5) calc(var(--sp-5) + 3px);
  border-radius: var(--r-lg);
  overflow: hidden;
}

.callout::before {
  content: "";
  position: absolute;
  inset: 0 auto 0 0;
  width: 3px;
  background: var(--grad);
}

.callout h3 {
  margin-bottom: var(--sp-2);
}

.callout p {
  color: var(--text-muted);
}

.callout p + p {
  margin-top: var(--sp-3);
}

/* ---------- faq ---------- */

.faq {
  border-bottom: 1px solid var(--border);
}

.faq__q {
  display: flex;
  align-items: flex-start;
  gap: var(--sp-4);
  padding: var(--sp-5) 0;
  cursor: pointer;
  list-style: none;
  font-weight: 640;
  font-size: var(--t-lg);
}

.faq__q::-webkit-details-marker {
  display: none;
}

.faq__q::after {
  content: "";
  margin-left: auto;
  flex: none;
  width: 0.8rem;
  height: 0.8rem;
  margin-top: 0.45em;
  background: var(--text-dim);
  clip-path: polygon(50% 0%, 100% 100%, 50% 66%, 0% 100%);
  transform: rotate(180deg);
  transition: transform 0.25s var(--ease), background 0.2s var(--ease);
}

.faq[open] .faq__q::after {
  transform: rotate(0);
  background: var(--grad);
}

.faq__a {
  padding-bottom: var(--sp-5);
  max-width: 68ch;
}

.faq__a p {
  color: var(--text-muted);
}

.faq__a p + p {
  margin-top: var(--sp-3);
}

/* ---------- forms ---------- */

.field {
  display: grid;
  gap: var(--sp-2);
  margin-bottom: var(--sp-4);
}

.field label {
  font-size: var(--t-sm);
  font-weight: 620;
}

.field .hint {
  font-size: var(--t-xs);
  color: var(--text-dim);
  font-weight: 400;
}

.field input,
.field select,
.field textarea {
  width: 100%;
  padding: 0.75rem 0.9rem;
  background: var(--bg);
  border: 1px solid var(--border-strong);
  border-radius: var(--r);
  transition: border-color 0.15s var(--ease), box-shadow 0.15s var(--ease);
}

.field input:focus,
.field select:focus,
.field textarea:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 22%, transparent);
}

.field input:focus-visible,
.field select:focus-visible,
.field textarea:focus-visible {
  outline: 3px solid var(--focus);
  outline-offset: 2px;
}

.field textarea {
  resize: vertical;
  min-height: 7rem;
}

.field[data-invalid="true"] input,
.field[data-invalid="true"] textarea {
  border-color: #ff6b6b;
}

.field__err {
  font-size: var(--t-xs);
  color: #ff8f8f;
  min-height: 1em;
}

/* Must stay inside the media query. A bare :root:not([data-theme="dark"])
   also matches the default (no attribute) state — which is DARK — and would
   paint #b91c1c on #0a0e1a at 2.98:1. */
@media (prefers-color-scheme: light) {
  :root:not([data-theme="dark"]) .field__err {
    color: #b91c1c;
  }
}

:root[data-theme="light"] .field__err {
  color: #b91c1c;
}

.hp {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.form-status {
  padding: var(--sp-4);
  border-radius: var(--r);
  border: 1px solid var(--border-strong);
  background: var(--surface);
  margin-bottom: var(--sp-5);
}

.form-status[data-state="ok"] {
  border-color: #4ade80;
}

.form-status[data-state="err"] {
  border-color: #ff8f8f;
}

/* ---------- footer ---------- */

.site-footer {
  border-top: 1px solid var(--border);
  padding-block: var(--sp-8) var(--sp-6);
  margin-top: var(--sp-9);
  background: var(--bg-raised);
}

.footer__grid {
  display: grid;
  gap: var(--sp-6);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 12rem), 1fr));
}

.footer__grid > div:first-child {
  grid-column: 1 / -1;
}

@media (min-width: 780px) {
  .footer__grid {
    grid-template-columns: 1.6fr repeat(3, 1fr);
  }

  .footer__grid > div:first-child {
    grid-column: auto;
  }
}

.footer__h {
  font-size: var(--t-xs);
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-dim);
  margin-bottom: var(--sp-3);
}

.footer__list {
  list-style: none;
  padding: 0;
  display: grid;
  gap: var(--sp-2);
}

.footer__list a {
  color: var(--text-muted);
  text-decoration: none;
  font-size: var(--t-sm);
}

.footer__list a:hover {
  color: var(--text);
  text-decoration: underline;
}

.footer__bottom {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-4);
  align-items: center;
  justify-content: space-between;
  margin-top: var(--sp-7);
  padding-top: var(--sp-5);
  border-top: 1px solid var(--border);
  font-size: var(--t-xs);
  color: var(--text-dim);
}

.footer__blurb {
  font-size: var(--t-sm);
  color: var(--text-muted);
  margin-top: var(--sp-4);
  max-width: 34ch;
}

.footer__contact {
  margin-top: var(--sp-4);
  display: grid;
  gap: var(--sp-1);
  font-size: var(--t-sm);
}

.footer__contact a {
  color: var(--text-muted);
  text-decoration: none;
}

.footer__contact a:hover {
  color: var(--accent);
}

/* ---------- theme toggle ---------- */

.theme-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.2rem;
  height: 2.2rem;
  border-radius: var(--r);
  border: 1px solid var(--border);
  color: var(--text-muted);
  flex: none;
}

.theme-toggle:hover {
  color: var(--text);
  border-color: var(--border-strong);
}

.theme-toggle svg {
  width: 1.05rem;
  height: 1.05rem;
}

.theme-toggle .icon-sun {
  display: none;
}

:root[data-theme="dark"] .theme-toggle .icon-sun {
  display: block;
}

:root[data-theme="dark"] .theme-toggle .icon-moon {
  display: none;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .theme-toggle .icon-sun {
    display: block;
  }

  :root:not([data-theme="light"]) .theme-toggle .icon-moon {
    display: none;
  }
}

/* ---------- reveal on scroll (JS adds .in) ---------- */

.reveal {
  opacity: 0;
  transform: translateY(14px);
  transition: opacity 0.55s var(--ease), transform 0.55s var(--ease);
}

.reveal.in {
  opacity: 1;
  transform: none;
}

/* No JS? Never leave content invisible. */
.no-js .reveal {
  opacity: 1;
  transform: none;
}

@media (prefers-reduced-motion: reduce) {
  .reveal {
    opacity: 1;
    transform: none;
  }
}

/* ---------- utilities ----------
   These exist because the CSP is `style-src 'self'` with no 'unsafe-inline',
   which blocks style="" attributes outright. Rather than weaken the policy for
   a handful of one-offs, every one-off gets a real class. */

/* Alternating section band. */
.section--band {
  background: var(--bg-raised);
  border-block: 1px solid var(--border);
}

.btn-row--center {
  justify-content: center;
}

.stack-center {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--sp-4);
  padding-block: var(--sp-7);
}

.t-2xl {
  font-size: var(--t-2xl);
}

.t-3xl {
  font-size: var(--t-3xl);
}

.t-4xl {
  font-size: var(--t-4xl);
}

.t-tight {
  line-height: 1.05;
}

.m-0 {
  margin: 0;
}

.mt-0 {
  margin-top: 0;
}

.block {
  display: block;
}

/* Terminal chrome dots — fixed hues, because the terminal stays dark in both
   themes and these are the real colours of a window's traffic lights. */
.term__dot--r {
  background: #ff5f57;
}

.term__dot--y {
  background: #febc2e;
}

.term__dot--g {
  background: #28c840;
}

.center {
  text-align: center;
}

.mt-4 {
  margin-top: var(--sp-4);
}

.mt-5 {
  margin-top: var(--sp-5);
}

.mt-6 {
  margin-top: var(--sp-6);
}

.mt-7 {
  margin-top: var(--sp-7);
}

.muted {
  color: var(--text-muted);
}

.dim {
  color: var(--text-dim);
}

.small {
  font-size: var(--t-sm);
}

.xs {
  font-size: var(--t-xs);
}

.mono {
  font-family: var(--mono);
}

/* Filenames are case-sensitive. .stat__l uppercases its label, which turned
   validate.sh into VALIDATE.SH — a file that does not exist. */
.nocaps {
  text-transform: none;
}

.nowrap {
  white-space: nowrap;
}

.grid-2 {
  display: grid;
  gap: var(--sp-6);
  grid-template-columns: 1fr;
}

@media (min-width: 860px) {
  .grid-2 {
    grid-template-columns: 1fr 1fr;
  }
}

.tag {
  display: inline-block;
  padding: 0.22rem 0.6rem;
  border-radius: var(--r-full);
  border: 1px solid var(--border-strong);
  font-size: var(--t-xs);
  font-family: var(--mono);
  color: var(--text-muted);
  background: var(--surface);
}

.tag-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
}

@media print {
  .site-header,
  .site-footer,
  .btn,
  .theme-toggle {
    display: none;
  }

  .week__body {
    display: block !important;
  }
}

/* ---------- Bangla ----------
   Applied from <html lang="bn">, so a single attribute switches the whole page
   and any lang="bn" island inside an English page picks it up too.

   Bangla stacks matras above and conjuncts below the baseline, so the Latin
   metrics we tuned for English clip and crowd. It needs more leading, looser
   headings, and no letter-spacing — negative tracking mangles conjuncts. */

:root:lang(bn) body,
[lang="bn"] {
  font-family: var(--font-bn);
}

:lang(bn) body {
  line-height: 1.85;
}

:lang(bn) h1,
:lang(bn) h2,
:lang(bn) h3,
:lang(bn) h4 {
  line-height: 1.35;
  letter-spacing: 0; /* the Latin -0.022em breaks conjuncts */
  font-weight: 700;
}

/* Bangla has no case, so uppercase transforms do nothing to Bangla glyphs while
   still shouting at the English words mixed in. Drop the transform and lean on
   weight and tracking instead. */
:lang(bn) .eyebrow,
:lang(bn) .stat__l,
:lang(bn) .footer__h,
:lang(bn) .phase__n,
:lang(bn) .journey__cap,
:lang(bn) .term__title {
  text-transform: none;
  letter-spacing: 0.02em;
}

:lang(bn) .hero__lede,
:lang(bn) .lead,
:lang(bn) .head p {
  line-height: 1.8;
}

/* Bengali numerals (২৫ ৫০ ৬–১০) sit on different metrics to Latin digits and
   have ink below the Latin baseline, so the display line-height:1 that works for
   "25" clips them in half. Same for the big gradient headline numbers. */
:lang(bn) .stat__n,
:lang(bn) .journey__wk,
:lang(bn) .week__n {
  line-height: 1.45;
  letter-spacing: 0;
}

:lang(bn) .stat {
  padding-block: var(--sp-4);
}

/* A Bangla case marker hyphenated onto an English word (Cloud engineering-এ)
   must not break across lines — it reads as a word-break error. */
:lang(bn) .grad-text {
  text-wrap: balance;
}

/* Bangla runs longer than English for the same meaning; give it room. */
:lang(bn) .hero__lede {
  max-width: 52ch;
}

:lang(bn) .head h2 {
  max-width: 24ch;
}

/* Latin numerals and code keep the Latin face inside Bangla prose. */
:lang(bn) .mono,
:lang(bn) code,
:lang(bn) pre,
:lang(bn) .tag {
  font-family: var(--mono);
}

/* These target specific components because a bare `:lang(bn) h1` ties on
   specificity with `.hero h1` — the language layer has to come last AND match
   at least as tightly. Measured: without this the Bangla h1 renders at
   -1.67px tracking, which crushes conjuncts. */
:lang(bn) .hero h1,
:lang(bn) .page-hero h1,
:lang(bn) .head h2,
:lang(bn) .card h3,
:lang(bn) .btn,
:lang(bn) .faq__q,
:lang(bn) .week__t,
:lang(bn) .journey__t,
:lang(bn) .steps__t,
:lang(bn) .phase__t {
  letter-spacing: 0;
}

:lang(bn) .hero h1,
:lang(bn) .page-hero h1 {
  line-height: 1.4;
}

:lang(bn) .t-tight {
  line-height: 1.4;
}

:lang(bn) .btn {
  line-height: 1.6;
}

/* The logo lockup is the Latin wordmark even on a Bangla page — both halves
   keep their Latin metrics. The 0.4em on ACADEMY is what makes it span the
   width of LE^DS above it; zeroing it collapses the lockup. */
:lang(bn) .logo__word {
  font-family: var(--font);
  letter-spacing: 0.07em;
}

:lang(bn) .logo__sub {
  font-family: var(--font);
  letter-spacing: 0.4em;
}

