/* ==========================================================================
   Zenix Academy — section-specific styling
   Order matches the page: hero, values ring, app, why, how, about, reviews, faq
   ========================================================================== */

/* =============================================================== 1. HERO === */
/* `clip`, not `hidden`, on every section wrapper that holds .reveal children.
   Both clip the decorative bleed identically, but `overflow: hidden` makes the
   element a SCROLL CONTAINER, and `animation-timeline: view()` resolves against
   the nearest scroll container. A section that never scrolls is a timeline that
   can never advance, which leaves its children stuck at opacity 0. This is the
   same trap `.rail` hit below 900px; `clip` is not a scroll container, so it
   cannot happen here at all. */
.hero {
  position: relative;
  min-block-size: calc(100dvh - var(--header-h));
  display: grid;
  align-items: center;
  padding-block: clamp(3rem, 7vw, 6rem) clamp(4rem, 8vw, 7rem);
  overflow: clip;
  isolation: isolate;
}

/* The poster's curved teal shapes, rebuilt as soft background fields. */
.hero__wash {
  position: absolute;
  inset: 0;
  z-index: -2;
  background:
    radial-gradient(58% 46% at 82% 8%,  rgba(11, 119, 124, .13), transparent 70%),
    radial-gradient(46% 40% at 12% 88%, rgba(68, 102, 107, .12), transparent 72%),
    linear-gradient(180deg, #f7fbfb 0%, var(--paper) 55%, #eef5f6 100%);
  pointer-events: none;
}
/* Large curved sweep echoing the poster's blob, anchored to the inline-end. */
.hero__curve {
  position: absolute;
  z-index: -1;
  inset-block-start: -18%;
  inset-inline-end: -22%;
  inline-size: min(760px, 78vw);
  aspect-ratio: 1;
  border-radius: 44% 56% 52% 48% / 48% 44% 56% 52%;
  background: radial-gradient(circle at 34% 30%, rgba(11, 119, 124, .10), rgba(68, 102, 107, .04) 62%, transparent 72%);
  filter: blur(6px);
  pointer-events: none;
}

.hero__grid {
  display: grid;
  gap: clamp(2.5rem, 6vw, 4.5rem);
  align-items: center;
  grid-template-columns: minmax(0, 1.08fr) minmax(0, .92fr);
}
@media (max-width: 940px) {
  .hero__grid { grid-template-columns: 1fr; text-align: center; justify-items: center; }
  .hero { min-block-size: auto; }
}

/* min-inline-size:0 stops a long unbreakable run (a Latin URL, say) from
   blowing the grid track out past the viewport. */
.hero__copy { min-inline-size: 0; }

.hero__title { font-size: var(--fs-4xl); margin-block-end: 1.4rem; }
.hero__title .sheen {
  background-image: var(--sheen);
  background-size: 220% 100%;
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  -webkit-text-fill-color: transparent;
}
.hero__lead { margin-block-end: 2.25rem; }
.hero__lead-em {
  display: block;
  margin-block-start: .55rem;
  color: var(--ink);
  font-weight: 700;
}
@media (max-width: 940px) { .hero__lead { margin-inline: auto; } }

.hero__trust {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: .6rem 1.4rem;
  margin-block-start: 2.25rem;
  font-size: var(--fs-xs);
  color: var(--ink-soft);
}
@media (max-width: 940px) { .hero__trust { justify-content: center; } }
.hero__trust li { display: inline-flex; align-items: center; gap: .45rem; }
.hero__trust svg { inline-size: 15px; block-size: 15px; color: var(--accent); flex: none; }

/* --- the orbit stage --- */
.orbit {
  position: relative;
  inline-size: min(100%, 440px);
  aspect-ratio: 1;
  display: grid;
  place-items: center;
  margin-inline: auto;
}
.orbit__canvas {
  position: absolute;
  inset: 0;
  inline-size: 100%;
  block-size: 100%;
}
.orbit__rings {
  position: absolute;
  inset: 0;
  inline-size: 100%;
  block-size: 100%;
  color: var(--accent);
  opacity: .5;
}
.orbit__glow {
  position: absolute;
  inline-size: 62%;
  aspect-ratio: 1;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(11, 119, 124, .3), transparent 66%);
  filter: blur(26px);
}
/* Same reasoning as .brand__mark: the PNG is a squircle with transparent
   corners, so the shadow is a drop-shadow that follows its alpha. */
.orbit__mark {
  position: relative;
  inline-size: 39%;
  block-size: auto;
  filter:
    drop-shadow(0 22px 30px rgba(9, 43, 48, .28))
    drop-shadow(0 3px 8px rgba(9, 43, 48, .18));
}
.orbit__chip {
  position: absolute;
  display: inline-flex;
  align-items: center;
  gap: .45rem;
  padding: .5rem .9rem;
  border-radius: var(--r-pill);
  background: rgba(255, 255, 255, .9);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  border: 1px solid var(--rule);
  box-shadow: var(--shadow);
  font-size: var(--fs-xs);
  font-weight: 700;
  color: var(--ink);
  white-space: nowrap;
}
.orbit__chip svg { inline-size: 14px; block-size: 14px; color: var(--accent); flex: none; }
.orbit__chip--a { inset-block-start: 8%;  inset-inline-start: -4%; }
.orbit__chip--b { inset-block-end: 14%;   inset-inline-end: -6%; }
.orbit__chip--c { inset-block-end: 2%;    inset-inline-start: 12%; }
@media (max-width: 520px) {
  .orbit { inline-size: min(100%, 300px); }
  .orbit__chip { font-size: 11px; padding: .35rem .7rem; }
  .orbit__chip--a { inset-inline-start: 0; }
  .orbit__chip--b { inset-inline-end: 0; }
}

/* ========================================================= 2. VALUES RING === */
.ring-band { position: relative; overflow: clip; isolation: isolate; }
/* The drifting particle field. It is also what the glass cards have to refract:
   frosted panels over a flat white ground read as flat white panels. */
.ring-band__field {
  position: absolute;
  inset: 0;
  z-index: -1;
  inline-size: 100%;
  block-size: 100%;
  pointer-events: none;
}
.ring-band::before {
  content: "";
  position: absolute;
  z-index: -2;
  inset: 0;
  background:
    radial-gradient(48% 60% at 50% 46%, rgba(11, 119, 124, .10), transparent 68%),
    radial-gradient(38% 44% at 12% 8%,  rgba(68, 102, 107, .09), transparent 70%),
    radial-gradient(38% 44% at 88% 92%, rgba(11, 119, 124, .08), transparent 70%);
  pointer-events: none;
}

/* --- default: a plain four-up grid. js/ring.js upgrades it to 3D --- */
.ring { position: relative; }
.ring__stage { position: relative; }
.ring__spin {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: clamp(1rem, 2.2vw, 1.6rem);
}
@media (max-width: 980px) { .ring__spin { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 480px) { .ring__spin { grid-template-columns: 1fr; } }
.ring__face { block-size: 100%; }

/* --- the glass card --- */
.gcard {
  position: relative;
  block-size: 100%;
  padding: clamp(1.4rem, 2.6vw, 1.9rem);
  border-radius: var(--r-lg);
  /* Glass: a translucent gradient body, a bright hairline along the top inside
     edge, and a soft cast shadow. No backdrop-filter — inside a preserve-3d
     subtree it is both unreliable and expensive, and the per-card blur below
     already carries the depth cue. */
  background: linear-gradient(158deg, rgba(255, 255, 255, .88), rgba(255, 255, 255, .58));
  border: 1px solid rgba(255, 255, 255, .9);
  box-shadow:
    0 22px 44px -26px rgba(9, 43, 48, .42),
    0 2px 6px -3px rgba(9, 43, 48, .12),
    inset 0 1px 0 rgba(255, 255, 255, .95);
  overflow: hidden;
}
.gcard::before {
  content: "";
  position: absolute;
  inset-block-start: -40%;
  inset-inline-end: -30%;
  inline-size: 70%;
  aspect-ratio: 1;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(11, 119, 124, .16), transparent 62%);
  pointer-events: none;
}
.gcard > * { position: relative; }

.gcard__idx {
  display: block;
  font-family: var(--font-wordmark);
  font-weight: 700;
  font-size: .9rem;
  letter-spacing: .18em;
  color: var(--accent-ink);
  opacity: .75;
  margin-block-end: 1.1rem;
}
/* The rule under the index is what replaces the icon plate: it gives the card a
   fixed anchor without another rounded-square-with-a-thin-glyph. */
.gcard__idx::after {
  content: "";
  display: block;
  inline-size: 26px;
  block-size: 2px;
  border-radius: 2px;
  margin-block-start: .5rem;
  background: var(--accent-grad);
}
.gcard h3 { font-size: var(--fs-lg); margin-block-end: .6rem; }
.gcard p  { font-size: var(--fs-sm); color: var(--ink-soft); }

/* --- 3D mode (added by js/ring.js only) --- */
/* left/top/translate are physical on purpose: this is a camera, not a layout.
   The ring must turn the same way in either writing direction. */
.ring.is-3d .ring__stage {
  block-size: var(--stage-h, 400px);
  perspective: var(--persp, 1250px);
  /* Looking slightly down on the ring turns the circle into an ellipse without
     tilting the cards themselves out of the reading plane. */
  perspective-origin: 50% 34%;
}
/* --rot is the one value ring.js writes per frame; everything else about the
   geometry is declared here and derived from it. */
.ring.is-3d .ring__spin {
  position: absolute;
  inset: 0;
  display: block;
  gap: 0;
  transform: rotateY(var(--rot, 0deg));
  transform-style: preserve-3d;
}
.ring.is-3d .ring__slot {
  position: absolute;
  left: 50%;
  top: 50%;
  width: var(--cw, 300px);
  transform: translate(-50%, -50%) rotateY(var(--a)) translateZ(var(--r, 300px)) translateY(var(--dy));
  transform-style: preserve-3d;
}
/* Undo both the seat angle and the ring's own turn, so the card faces the
   reader the whole way round instead of edging away. --rot inherits down from
   .ring__spin, so this needs no per-frame write of its own. */
.ring.is-3d .ring__face {
  block-size: auto;
  transform: rotateY(calc(-1 * var(--a) - var(--rot, 0deg)));
  transform-style: preserve-3d;
}
/* Static seat angles + a vertical stagger, so the far card never sits exactly
   behind the near one. */
.ring.is-3d .ring__slot:nth-child(1) { --a:   0deg; --dy: -14px; }
.ring.is-3d .ring__slot:nth-child(2) { --a:  90deg; --dy:  20px; }
.ring.is-3d .ring__slot:nth-child(3) { --a: 180deg; --dy: -22px; }
.ring.is-3d .ring__slot:nth-child(4) { --a: 270deg; --dy:  14px; }

/* --stage-h has to clear the FRONT card, which perspective scales up by
   persp / (persp − r): 1.33× at the widest, 1.21× on a phone. The vertical
   stagger adds another ~22px on top of that. */
/* --rot is declared here, not only written from JS, so the geometry still
   resolves for one frame before the script has run. */
.ring.is-3d { --rot: 0deg; --cw: 300px; --r: 310px; --stage-h: 420px; --persp: 1250px; }
@media (max-width: 1080px) { .ring.is-3d { --cw: 280px; --r: 260px; --stage-h: 410px; --persp: 1100px; } }
@media (max-width: 760px)  { .ring.is-3d { --cw: 260px; --r: 190px; --stage-h: 400px; --persp: 900px;  } }
@media (max-width: 480px)  { .ring.is-3d { --cw: 224px; --r: 132px; --stage-h: 390px; --persp: 760px;  } }

/* --- grab affordance + hint --- */
.ring.is-3d .ring__stage {
  cursor: grab;
  /* Claim the horizontal axis for the drag, leave the vertical one to the page
     so a phone can still scroll past the section. */
  touch-action: pan-y;
  -webkit-user-select: none;
  user-select: none;
}
.ring.is-3d.is-grabbed .ring__stage { cursor: grabbing; }
.ring.is-3d .ring__stage:focus-visible {
  outline: 3px solid var(--accent);
  outline-offset: 8px;
  border-radius: var(--r-lg);
}

/* Depth is written per frame by ring.js as --b / --o. The values declared here
   are what a card looks like if the script never gets that far, which is:
   perfectly normal. */
.ring.is-3d .gcard {
  --b: 0px;
  --o: 1;
  filter: blur(var(--b));
  opacity: var(--o);
}

.ring__hint { display: none; }
.ring.is-3d .ring__hint {
  display: block;
  margin-block-start: clamp(1.25rem, 2.5vw, 2rem);
  text-align: center;
  font-size: var(--fs-xs);
  color: var(--ink-mute);
}

/* ============================================================== 3. APP ==== */
.app { overflow: clip; }   /* clip, not hidden — see the note on .hero */
/* Stacked, not two-column. Side by side, the desktop screenshot only got about
   500px — the app's own 14px UI text lands under 6px there and no amount of
   source resolution can rescue it. Full width it gets ~940px and is legible. */
.app__grid {
  display: grid;
  gap: clamp(2.5rem, 5vw, 3.5rem);
  justify-items: center;
}
.app__copy {
  min-inline-size: 0;
  max-inline-size: 68ch;
  text-align: center;
}
.app__copy .lead { margin-block-start: 1.1rem; margin-inline: auto; }

.app__points {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: .7rem 1.75rem;
  margin-block-start: 1.75rem;
}
.app__points li {
  display: flex;
  align-items: center;
  gap: .6rem;
  font-size: var(--fs-sm);
  color: var(--ink-soft);
}
.app__points svg { inline-size: 17px; block-size: 17px; color: var(--accent); flex: none; }
.app__cta { margin-block-start: 2rem; }

/* --- device mock-ups --- */
/* The frames are drawn in CSS rather than shipped as artwork, so they inherit
   the palette and cost nothing. Only the two screenshots are images. */
/* ⚠ These two numbers are arithmetic, not layout taste. Do not round them.
   Sharpness is (source pixels) / (device pixels painted), and a HiDPI screen
   doubles the denominator. The desktop screenshot is 1280px of source, so the
   largest it can be painted without upscaling on a 2× display is 640 CSS px:
     850 (mock) - 190 (gutter) - 20 (bezel) = 640 exactly.
   That is 1:1 on a HiDPI screen and a clean 2:1 downscale on a plain one. Shown
   larger it goes soft — which is what a 1040px box was doing.
   The 190px gutter is where the phone stands. It is wide enough that the phone
   overlaps only the laptop's BEZEL, never the screenshot: the app's sidebar nav
   runs the full height of that edge, and a phone parked on top of it hid the
   whole navigation. Widening the screenshot needs a LARGER CAPTURE first
   (>=1920px); the cap then moves to half of whatever that source is. */
.mock {
  position: relative;
  inline-size: 100%;
  max-inline-size: 850px;
  /* Own stacking context, so the z-index:-1 glow cannot escape behind an
     ancestor's background. */
  isolation: isolate;
  padding-block-end: clamp(2.5rem, 5vw, 3.5rem);
  /* Fixed, NOT a clamp on vw. A viewport-relative gutter is fractional at most
     widths, which lands the image on a sub-pixel width and forces the browser
     to resample it. 190px keeps 850 - 190 - 20 = 640 exact. */
  padding-inline-start: 190px;
}
.mock__glow {
  position: absolute;
  z-index: -1;
  inset-block-start: -12%;
  inset-inline: -8%;
  block-size: 90%;
  border-radius: 50%;
  background: radial-gradient(circle at 50% 45%, rgba(11, 119, 124, .2), transparent 66%);
  filter: blur(10px);
  pointer-events: none;
}

.mock__desk { position: relative; margin: 0; }
.mock__desk .mock__screen {
  padding: 10px;
  border-radius: 16px;
  background: linear-gradient(160deg, #24444a, #14282c);
  box-shadow:
    0 40px 70px -38px rgba(9, 43, 48, .62),
    0 4px 10px -6px rgba(9, 43, 48, .34),
    inset 0 1px 0 rgba(255, 255, 255, .16);
}
.mock__desk img { border-radius: 8px; inline-size: 100%; max-inline-size: 640px; }
/* Neck + foot: enough of a laptop to read as one, without faking any OS chrome
   that would be wrong for one of the two platforms. */
.mock__stand {
  display: block;
  inline-size: 16%;
  block-size: 14px;
  margin-inline: auto;
  background: linear-gradient(180deg, #24444a, #1b3438);
}
.mock__foot {
  display: block;
  inline-size: 34%;
  block-size: 9px;
  margin-inline: auto;
  border-radius: 0 0 6px 6px;
  background: linear-gradient(180deg, #1b3438, #12262a);
  box-shadow: 0 16px 24px -16px rgba(9, 43, 48, .6);
}

/* 639px of source in a ~205px box — 3.1× spare, so this one is nowhere near
   its limit and can be shown large. Only the desktop shot is constrained.
   It sits in .mock's leading gutter and clears the screenshot entirely. */
.mock__phone {
  position: absolute;
  z-index: 1;
  margin: 0;
  inset-inline-start: 0;
  inset-block-end: 0;
  inline-size: clamp(124px, 24%, 205px);
  padding: 7px;
  border-radius: 26px;
  background: linear-gradient(160deg, #24444a, #14282c);
  box-shadow:
    0 34px 54px -28px rgba(9, 43, 48, .66),
    0 3px 8px -4px rgba(9, 43, 48, .4),
    inset 0 1px 0 rgba(255, 255, 255, .18);
}
.mock__phone img { border-radius: 19px; inline-size: 100%; }
/* inset-inline:0 + margin-inline:auto centres it without a physical translate,
   which would have to be sign-flipped per writing direction. */
.mock__notch {
  position: absolute;
  z-index: 2;
  inset-block-start: 12px;
  inset-inline: 0;
  margin-inline: auto;
  inline-size: 34%;
  block-size: 5px;
  border-radius: var(--r-pill);
  background: rgba(255, 255, 255, .3);
}
/* Too narrow for a 190px gutter, so it goes proportional: 24% of gutter against
   a 28% phone still leaves the phone clear of everything but the bezel. */
@media (max-width: 620px) {
  .mock { padding-inline-start: 24%; padding-block-end: 3rem; }
  .mock__phone { inset-inline-start: 0; inline-size: 28%; }
}

/* ============================================================= 4. WHY ===== */
.pillars {
  display: grid;
  gap: clamp(1.5rem, 3vw, 2.25rem);
  grid-template-columns: minmax(0, .9fr) minmax(0, 1.1fr);
  align-items: start;
}
@media (max-width: 980px) { .pillars { grid-template-columns: 1fr; } }

.pillars__intro {
  position: relative;
  overflow: hidden;
  isolation: isolate;
  padding: clamp(1.9rem, 4vw, 3rem);
  border-radius: var(--r-xl);
  background-image: var(--hero-grad);
  color: var(--on-dark);
}
.pillars__intro::before {
  content: "";
  position: absolute;
  z-index: -1;
  inset-block-start: -34%;
  inset-inline-end: -26%;
  inline-size: 82%;
  aspect-ratio: 1;
  border-radius: 46% 54% 50% 50% / 52% 46% 54% 48%;
  background: radial-gradient(circle at 42% 40%, rgba(111, 195, 192, .26), transparent 64%);
  pointer-events: none;
}
.pillars__intro h2 { color: #fff; font-size: var(--fs-2xl); }
.pillars__intro p  { color: var(--on-dark-soft); margin-block-start: 1.1rem; font-size: var(--fs-sm); }
@media (min-width: 981px) {
  /* The intro is the shorter column; pinning it keeps the heading beside
     whichever panel the reader is on. */
  .pillars__intro { position: sticky; inset-block-start: calc(var(--header-h) + 1.5rem); }
}

.pillars__cta {
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  margin-block-start: 1.75rem;
  color: #9fd8d5;
  font-weight: 700;
  font-size: var(--fs-sm);
  text-decoration: none;
}
.pillars__cta:hover { color: #fff; }
.pillars__cta svg {
  inline-size: 16px; block-size: 16px;
  transform: scaleX(-1);   /* RTL: forward points visually left */
  transition: transform var(--t-med) var(--ease-out);
}
.pillars__cta:hover svg { transform: scaleX(-1) translateX(4px); }

.pillars__list { display: grid; gap: clamp(1rem, 2vw, 1.25rem); }

.pillar {
  position: relative;
  display: flex;
  gap: clamp(1rem, 2.4vw, 1.9rem);
  padding: clamp(1.5rem, 3vw, 2.2rem);
  border-radius: var(--r-lg);
  background: var(--surface);
  border: 1px solid var(--rule);
  box-shadow: var(--shadow-sm);
  overflow: hidden;
  transition: transform var(--t-med) var(--ease-out),
              box-shadow var(--t-med) var(--ease-out),
              border-color var(--t-med) var(--ease);
}
/* A rule that runs the full height of the panel and fills with teal on hover —
   the accent lives on the box itself instead of in a decorative icon tile. */
.pillar::before {
  content: "";
  position: absolute;
  inset-block: 0;
  inset-inline-start: 0;
  inline-size: 4px;
  background-image: var(--accent-grad);
  transform: scaleY(0);
  transform-origin: 50% 0;
  transition: transform var(--t-med) var(--ease-out);
}
.pillar:hover {
  transform: translateY(-4px);
  box-shadow: var(--shadow-lg);
  border-color: var(--accent-line);
}
.pillar:hover::before { transform: scaleY(1); }

.pillar__idx {
  flex: none;
  font-family: var(--font-wordmark);
  font-weight: 700;
  font-size: clamp(1.6rem, 3.4vw, 2.4rem);
  line-height: 1;
  color: var(--accent);
  opacity: .28;
  transition: opacity var(--t-med) var(--ease);
}
.pillar:hover .pillar__idx { opacity: .6; }
.pillar__body { min-inline-size: 0; }
.pillar h3 { font-size: var(--fs-lg); margin-block-end: .6rem; }
.pillar p  { color: var(--ink-soft); font-size: var(--fs-sm); }
@media (max-width: 460px) {
  .pillar { flex-direction: column; gap: .75rem; }
}

/* ============================================================== 5. STEPS === */
.steps {
  display: grid;
  gap: clamp(1.25rem, 3vw, 2rem);
  grid-template-columns: repeat(3, minmax(0, 1fr));
  position: relative;
}
@media (max-width: 860px) { .steps { grid-template-columns: 1fr; max-width: 34rem; margin-inline: auto; } }

.step { position: relative; padding-block-start: .5rem; }
.step__num {
  inline-size: 52px; block-size: 52px;
  display: grid; place-items: center;
  border-radius: 50%;
  background: var(--surface);
  border: 2px solid var(--accent-line);
  color: var(--accent-ink);
  font-weight: 800;
  font-size: var(--fs-lg);
  font-family: var(--font-wordmark);
  margin-block-end: 1.25rem;
  position: relative;
  z-index: 1;
  transition: background var(--t-med) var(--ease), color var(--t-med) var(--ease), border-color var(--t-med) var(--ease);
}
.step:hover .step__num { background-image: var(--accent-grad); border-color: transparent; color: #fff; }
/* Connector rail. Uses a physical translate because it is a drawn line, not
   layout — its direction is handled by the RTL-aware inset below. */
.step:not(:last-child)::after {
  content: "";
  position: absolute;
  inset-block-start: 26px;
  inset-inline-start: 52px;
  inline-size: calc(100% - 52px + clamp(1.25rem, 3vw, 2rem));
  block-size: 2px;
  background: linear-gradient(to left, var(--accent-line), transparent);
  z-index: 0;
}
@media (max-width: 860px) { .step:not(:last-child)::after { display: none; } }
.step h3 { font-size: var(--fs-lg); margin-block-end: .55rem; }
.step p  { color: var(--ink-soft); font-size: var(--fs-sm); }

/* ============================================================== 6. ABOUT === */
.about {
  position: relative;
  background-image: var(--hero-grad);
  color: var(--on-dark);
  overflow: clip;   /* clip, not hidden — see the note on .hero */
  isolation: isolate;
}
.about::after {
  content: "";
  position: absolute;
  z-index: -1;
  inset-block-start: -30%;
  inset-inline-start: -14%;
  inline-size: min(620px, 70vw);
  aspect-ratio: 1;
  border-radius: 46% 54% 50% 50% / 52% 46% 54% 48%;
  background: radial-gradient(circle at 40% 40%, rgba(111, 195, 192, .17), transparent 66%);
  pointer-events: none;
}
.about__grid {
  display: grid;
  gap: clamp(2.5rem, 5vw, 4rem);
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  align-items: center;
}
@media (max-width: 900px) { .about__grid { grid-template-columns: 1fr; } }
.about h2 { color: #fff; }
.about p { color: var(--on-dark-soft); }
.about__body > p + p { margin-block-start: 1.1rem; }

/* The four cards used to be captioned «مدرّس» over an icon tile, which said
   nothing: no name behind it, and a role label is not information. They now
   name the AREA and what is in it, which is a fact the academy can stand
   behind today — and if real teachers are ever listed, the same markup takes a
   name in the <b> and a subject in the <span>. */
.coverage { min-inline-size: 0; }
.coverage__title {
  font-size: var(--fs-sm);
  font-weight: 700;
  color: #9fd8d5;
  margin-block-end: 1.25rem;
}
.coverage__list {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1rem;
}
@media (max-width: 620px) { .coverage__list { grid-template-columns: 1fr; } }

.coverage__item {
  position: relative;
  padding: clamp(1.1rem, 2.4vw, 1.4rem);
  padding-inline-start: clamp(1.4rem, 3vw, 1.8rem);
  border-radius: var(--r-lg);
  background: rgba(255, 255, 255, .07);
  border: 1px solid rgba(255, 255, 255, .14);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  overflow: hidden;
  transition: background var(--t-med) var(--ease),
              border-color var(--t-med) var(--ease),
              transform var(--t-med) var(--ease-out);
}
/* A teal rule on the leading edge replaces the icon tile — same job, no glyph
   that has to be guessed at. */
.coverage__item::before {
  content: "";
  position: absolute;
  inset-block: 0;
  inset-inline-start: 0;
  inline-size: 3px;
  background: linear-gradient(180deg, #6fc3c0, rgba(111, 195, 192, .15));
}
.coverage__item:hover {
  background: rgba(255, 255, 255, .12);
  border-color: rgba(255, 255, 255, .26);
  transform: translateY(-3px);
}
.coverage__item b {
  display: block;
  color: #fff;
  font-size: var(--fs-sm);
  font-weight: 700;
  line-height: 1.5;
  margin-block-end: .35rem;
}
.coverage__item span {
  display: block;
  font-size: var(--fs-xs);
  color: var(--on-dark-soft);
  line-height: 1.75;
}

/* ======================================================= 7. TESTIMONIALS === */
.rail {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(1rem, 2vw, 1.5rem);
}
@media (max-width: 900px) {
  .rail {
    grid-template-columns: none;
    grid-auto-flow: column;
    grid-auto-columns: min(84%, 22rem);
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    overscroll-behavior-inline: contain;
    padding-block-end: 1rem;
    /* let cards bleed to the viewport edge on phones */
    margin-inline: calc(var(--page-pad) * -1);
    padding-inline: var(--page-pad);
    scrollbar-width: thin;
  }
  .rail > * { scroll-snap-align: center; }
}

/* No avatar disc, and deliberately no initial-in-a-circle: an invented monogram
   for a real person reads as a stand-in for a photo that does not exist. The
   card leads with the words and signs off underneath a hairline instead. */
.quote {
  position: relative;
  display: grid;
  gap: 1.1rem;
  padding: clamp(1.5rem, 3vw, 2.1rem);
  border-radius: var(--r-lg);
  background: var(--surface);
  border: 1px solid var(--rule);
  box-shadow: var(--shadow-sm);
  overflow: hidden;
  transition: transform var(--t-med) var(--ease-out),
              box-shadow var(--t-med) var(--ease-out),
              border-color var(--t-med) var(--ease);
}
.quote::before {
  content: "";
  position: absolute;
  inset-block-start: 0;
  inset-inline: 0;
  block-size: 3px;
  background-image: var(--accent-grad);
  transform: scaleX(0);
  transform-origin: 100% 50%;   /* RTL: grow from the inline-start edge */
  transition: transform var(--t-med) var(--ease-out);
}
.quote:hover {
  transform: translateY(-4px);
  box-shadow: var(--shadow-lg);
  border-color: var(--accent-line);
}
.quote:hover::before { transform: scaleX(1); }

.quote__mark { color: var(--accent); opacity: .22; inline-size: 30px; block-size: 30px; }
.quote p {
  font-size: var(--fs-base);
  color: var(--ink);
  line-height: 1.85;
}

.quote__who {
  display: flex;
  align-items: baseline;
  gap: .7rem;
  /* Pushes the sign-off to the bottom so three cards of different lengths still
     line their attributions up. */
  margin-block-start: auto;
  padding-block-start: 1.1rem;
  border-block-start: 1px solid var(--rule);
}
.quote__who b {
  font-size: var(--fs-sm);
  font-weight: 700;
  color: var(--ink);
  line-height: 1.5;
}
.quote__who span {
  font-size: var(--fs-xs);
  color: var(--accent-ink);
  font-weight: 700;
  white-space: nowrap;
}
/* A teal dot between the name and the role, drawn rather than typed so it never
   lands on the wrong side of the bidi boundary. */
.quote__who span::before {
  content: "";
  display: inline-block;
  inline-size: 4px;
  block-size: 4px;
  border-radius: 50%;
  background: var(--accent);
  margin-inline-end: .5rem;
  vertical-align: middle;
  opacity: .6;
}

/* ================================================================ 8. FAQ === */
.faq-list { max-width: 52rem; margin-inline: auto; }
