/* AAKB — custom CSS beyond Tailwind utilities. Keep this file small;
   prefer Tailwind classes in markup wherever possible. */

:root {
  --ease-calm: cubic-bezier(0.4, 0, 0.2, 1);
}

/* Gujarati typography fix — two real bugs, not style preferences:
   1. Elements carrying their own .font-serif/.font-sans class (headings,
      body copy) always win over the inherited font-family from
      html.font-gujarati (an element's own declared value beats an
      inherited one regardless of selector specificity) — so Gujarati text
      was silently falling through Literata/Noto Serif Devanagari (neither
      has Gujarati glyphs) to a generic system serif, never actually
      loading Noto Serif Gujarati/Noto Sans Gujarati at all.
   2. That fallback font's vertical metrics didn't fit the tight
      Latin-tuned heading line-heights (leading-[1.1] etc.), so matras/
      conjuncts visually overlapped between lines. Both selectors below
      have higher specificity than a single Tailwind utility class, so no
      !important is needed. */
html.font-gujarati .font-serif {
  font-family: "Noto Serif Gujarati", serif;
}
html.font-gujarati .font-sans {
  font-family: "Noto Sans Gujarati", sans-serif;
}
html.font-gujarati h1,
html.font-gujarati h2,
html.font-gujarati h3 {
  line-height: 1.35;
}

html {
  scroll-behavior: smooth;
  /* Homepage full-viewport panels (see index.html <main> comment).
     "mandatory" forces a real landing on every scroll release — the
     trade-off is every .snap-section must actually fit one viewport
     (see the content sizing in index.html); an overflowing section would
     get yanked away mid-read, which is why this isn't "proximity". */
  scroll-snap-type: y mandatory;
}
@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
    scroll-snap-type: none;
  }
}

.snap-section {
  scroll-snap-align: start;
  /* Header clearance is real padding-top on the section (see index.html
     pt-20), not scroll-margin-top — margin only shifts where scrolling
     stops, it doesn't reserve space inside the section. That mismatch
     made vertical centering asymmetric: the previous section's tail
     bled in at the top while this section's own tail got pushed off
     the bottom. Real padding keeps content-center's math honest. */
}

body {
  background: #FFEFD4;
}

/* Loading overlay */
#loadingOverlay {
  position: fixed;
  inset: 0;
  z-index: 100;
  background: #FFEFD4;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2rem;
}
#logoStage {
  width: min(60vw, 260px);
  aspect-ratio: 1258 / 1218;
  position: relative;
  /* Hidden through the whole load phase (progress bar only, per direct
     feedback) — js/loading-screen.js fades this in only once "Enter" is
     clicked, right before the fill/rustle/sweep reveal plays. */
  opacity: 0;
}
/* Hidden until the ritual settles and JS reveals it (loading-screen.js) —
   base opacity here avoids a flash of visible gate before that. */
#entryGate {
  opacity: 0;
}

/* Load-phase progress bar (js/loading-screen.js) — real per-asset progress,
   not a simulated timer. Hidden once the entry gate takes over. */
#loadProgressTrack {
  width: min(50vw, 220px);
  height: 4px;
  border-radius: 9999px;
  background: rgba(63, 63, 63, 0.12);
  overflow: hidden;
}
#loadProgressFill {
  height: 100%;
  width: 0%;
  border-radius: 9999px;
  background: #FB6900;
  transform-origin: left center;
}
#logoStage svg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: visible;
}

/* Lightweight top progress bar (repeat visits within a session) */
#navProgressBar {
  position: fixed;
  top: 0;
  left: 0;
  height: 3px;
  width: 100%;
  background: #FB6900;
  z-index: 100;
  transform: scaleX(0);
}

/* Whole-page scroll-drawn background motif (js/motif-background.js).
   Fixed + centered, capped so it never dominates the viewport; behind all
   real content (z-index 0) and never intercepts input. See
   DESIGN_UX_ANIMATION_SPEC.md §1.4. */
#motifBackground {
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  display: flex;
  align-items: center;
  justify-content: center;
}
#motifBackground svg {
  max-width: 70vw;
  max-height: 70vh;
  width: auto;
  height: auto;
  overflow: visible;
}

/* Persistent settings control (sound / calm mode) — low-opacity until
   hovered/focused so it never competes with content, per
   DESIGN_UX_ANIMATION_SPEC.md §1.3. Exact visual polish (glassmorphic vs.
   plain, etc.) is intentionally left simple for now. */
#settingsControl {
  position: fixed;
  right: 1.25rem;
  bottom: 1.25rem;
  z-index: 90;
}
#settingsToggleBtn {
  width: 44px;
  height: 44px;
  border-radius: 9999px;
  background: rgba(255, 239, 212, 0.75);
  backdrop-filter: blur(6px);
  border: 1px solid rgba(63, 63, 63, 0.15);
  display: flex;
  align-items: center;
  justify-content: center;
  color: #3F3F3F;
  opacity: 0.5;
  transition: opacity 0.2s ease;
  cursor: pointer;
}
#settingsControl:hover #settingsToggleBtn,
#settingsToggleBtn:focus-visible,
#settingsControl.open #settingsToggleBtn {
  opacity: 1;
}
#settingsPanel {
  position: absolute;
  right: 0;
  bottom: calc(100% + 0.75rem);
  min-width: 160px;
  background: #FFFBF3;
  border: 1px solid rgba(63, 63, 63, 0.12);
  border-radius: 12px;
  box-shadow: 0 10px 30px -10px rgba(63, 63, 63, 0.25);
  padding: 0.75rem;
  display: none;
  flex-direction: column;
  gap: 0.5rem;
}
#settingsControl.open #settingsPanel {
  display: flex;
}
.settingsRow {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  font-size: 0.875rem;
  color: #3F3F3F;
  cursor: pointer;
}

/* Sound / Calm Mode toggle switches — real <input type="checkbox"> underneath
   (keeps native keyboard/aria semantics: Space/Enter toggles, screen readers
   announce checked state) with the checkbox itself visually hidden and a
   switch-shaped track+thumb painted on top, driven purely by :checked. */
.switchControl {
  position: relative;
  display: inline-flex;
  width: 40px;
  height: 24px;
  flex-shrink: 0;
}
.switchControl input {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  opacity: 0;
  cursor: pointer;
  z-index: 1;
}
.switchTrack {
  position: absolute;
  inset: 0;
  border-radius: 9999px;
  background: rgba(63, 63, 63, 0.2);
  transition: background 0.2s var(--ease-calm);
}
.switchThumb {
  position: absolute;
  top: 3px;
  left: 3px;
  width: 18px;
  height: 18px;
  border-radius: 9999px;
  background: #FFFBF3;
  box-shadow: 0 1px 3px rgba(63, 63, 63, 0.4);
  transition: transform 0.2s var(--ease-calm);
}
.switchControl input:checked ~ .switchTrack {
  background: #FB6900;
}
.switchControl input:checked ~ .switchTrack .switchThumb {
  transform: translateX(16px);
}
.switchControl input:focus-visible ~ .switchTrack {
  outline: 2px solid #FB6900;
  outline-offset: 2px;
}

.settingsLangBtn {
  border-radius: 9999px;
  width: 32px;
  height: 32px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 0.75rem;
  font-weight: 500;
  background: rgba(63, 63, 63, 0.08);
  border: 1px solid rgba(63, 63, 63, 0.15);
  color: #3F3F3F;
  cursor: pointer;
}
.settingsLangBtn:hover {
  background: rgba(63, 63, 63, 0.14);
}

/* Menu panel — hidden by default so there's no flash before JS runs;
   main.js toggles display via GSAP when opening/closing. */
#menuPanel {
  display: none;
}

/* Hero portrait 3D tilt card (see js/home.js initTiltCard) */
#heroImageWrap {
  will-change: transform;
  transform-style: preserve-3d;
}

/* Lineage Thread (see js/lineage-thread.js) — one continuous line spanning
   the whole homepage, scrolling in normal document flow like real content
   (not fixed-position), with a small stop circle at each section seam
   drawn in the same SVG/coordinate space as the line itself — no separate
   alignment math. z-index 3 is deliberate: above each section's z-auto
   background wash, below each section's .snap-fade content (z-10) — see
   the file header comment in lineage-thread.js for why that's safe to
   reason about globally even though sections aren't individually
   stacking contexts. left-6/md:left-12 matches the same px-6/md:px-12
   gutter every section's own content column uses, so the thread and the
   text line up at every breakpoint without extra offset math. The 50%
   dimming used to live here as a single opacity on the whole wrapper —
   moved to per-element stroke-opacity/fill-opacity/stop-opacity in
   js/lineage-thread.js instead, so the #supportWork span (recolored to
   aakb-papaya there, see buildThreadGradient) can render at full
   strength instead of inheriting the same 50% wash as the rest of the
   thread, where it read as too muted against that section's solid
   orange background. */
#lineageThread {
  position: absolute;
  inset-inline: 0;
  top: 0;
  z-index: 3;
  pointer-events: none;
  color: #fb6900; /* aakb-orange-safety */
  /* Hidden below md: the left-6/md:left-12 offset below is deliberately
     matched to each section's own px-6/md:px-12 content gutter so the
     thread and text align without extra offset math — but that only
     works at desktop widths, where the centered max-w-content column
     leaves real empty margin outside it for the thread to run through.
     At mobile widths the content column IS the full viewport width (no
     such margin exists), so the thread lands directly on top of the
     text it was meant to run alongside. Rather than invent a second
     positioning scheme just for mobile, it's simplest to drop the
     thread there — it's a desktop-only decorative device, not load-
     bearing content. */
  display: none;
}
@media (min-width: 768px) {
  #lineageThread {
    display: block;
  }
}
.lineage-line {
  position: absolute;
  left: 1.5rem;
  top: 0;
}
@media (min-width: 768px) {
  .lineage-line {
    left: 3rem;
  }
}

/* Who We Are — photo drifts slightly slower than the text column while the
   section is in view (see js/home.js initWhoWeAreParallax) */
#whoImageWrap {
  will-change: transform;
}
.tilt-glare {
  position: absolute;
  inset: -20%;
  pointer-events: none;
  background: radial-gradient(circle, rgba(255, 255, 255, 0.55), transparent 60%);
  opacity: 0;
  mix-blend-mode: soft-light;
}

/* What We Do — pointer-follow 3D tilt on each pillar card (see
   js/home.js initPillarTilt), the same mechanism as the Hero portrait's
   #heroImageWrap tilt, reused per-card instead of on one shared element —
   each card needs its own 3D transform context to tilt independently. */
.whatWeDo-pillar {
  will-change: transform;
  transform-style: preserve-3d;
}

/* Programs title dock (js/home.js's initProgramsTitleDock) — natural state
   is untouched (inherits #programsIntro's own text-center/wrap); this
   class is added the instant each element's own pin engages, flipping it
   to a single-line, left-aligned "docked" reading — "Programs" / "Where
   the pillars become practice." on one line each, not the big view's
   centered 2-line wrap. Text reflow (wrap↔nowrap, center↔left) isn't a
   smoothly tweenable CSS property, so this is a discrete class toggle
   (js/home.js masks the jump with a quick fade rather than an instant
   snap), timed to coincide with the pin/scale transition already in
   motion, rather than something GSAP scrubs frame-by-frame. */
#programsHeadline.is-docked,
#programsEyebrow.is-docked {
  text-align: left;
}
/* No max-width override here — #programsHeadline's box keeps its fixed
   w-full/max-w-3xl width (index.html) in both states, on purpose: letting
   max-width go to "none" here let the box itself grow to the container's
   full width the instant this class applied, re-centering it (since its
   parent uses items-center, which sizes/positions a flex item by its
   OWN current width) at a different spot than the eyebrow's still-fixed
   box — confirmed by testing, this is exactly what threw the pair out of
   alignment. white-space: nowrap alone is enough: the box stays put, and
   the single line of text simply overflows past its right edge instead
   of wrapping. */
#programsHeadline.is-docked {
  white-space: nowrap;
}
/* Mobile: the box's own max-w-3xl (768px, index.html) is wider than the
   entire viewport at this breakpoint, so the docked, nowrap single line
   above genuinely overflows past the screen edge, not just past its own
   box — confirmed live. Capping max-width here (ID selector, so it beats
   the inline max-w-3xl utility regardless of source order) keeps the box
   itself narrower than the viewport in EITHER state — same value whether
   docked or not, so the "box width must stay constant between states"
   invariant above (that's what keeps the eyebrow and headline aligned)
   still holds; only which value applies changes, by breakpoint, not by
   .is-docked. Docked nowrap is also dropped at this width: even a
   narrower box doesn't make "Where the pillars become practice." fit on
   one line at a readable size, so it wraps to two short lines instead —
   normal for a small corner-docked title, and the box's own width is
   unaffected by how many lines render inside it. */
@media (max-width: 767px) {
  #programsHeadline,
  #programsEyebrow {
    max-width: calc(100vw - 3rem);
  }
  #programsHeadline.is-docked {
    white-space: normal;
  }
}

/* Programs — scroll-pinned cinematic card sequence (see
   js/programs-cards.js), ported from
   experimentation-zone/05-what-we-do-cards/index.html with final copy and
   real i18n swapped in (that prototype was English-only placeholder text,
   proving the mechanism, not the content) — no changes to the mechanism
   itself. Pinned mode: #programsStage is exactly one viewport tall and
   pinned by ScrollTrigger for a tall scroll "runway"; cards live
   absolutely-centered inside it, driven entirely by GSAP transforms
   (x/scale/opacity/radius), never by normal document flow, while pinned.
   Reduced-motion mode swaps the same DOM into a plain vertical stack in
   normal flow via the .programs-stage--reduced override rules below. */
#programsStage {
  position: relative;
  z-index: 25;
  height: 100svh;
  width: 100%;
  overflow: hidden;
  background: radial-gradient(ellipse 60% 55% at 50% 50%, rgba(63, 63, 63, 0.05), transparent 70%);
}

.programs-slot {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  /* No padding here — .programs-card's own comment below says its
     dominant state is meant to be "a true edge-to-edge fill," but this
     slot's padding was leaving a permanent ~24px gutter on both sides
     even at full scale, contradicting that (confirmed by testing: the
     background stayed visible on the left/right at the card's biggest
     state). Cards are scaled/positioned entirely by GSAP transforms
     (js/programs-cards.js), not by this container's own spacing, so
     removing it doesn't affect the small/off-stage states either. */
}

/* Card's intrinsic size is the full stage (viewport) — "small" is achieved
   purely via GSAP scale, so the "dominant" state is a true edge-to-edge
   fill. border-radius is animated by GSAP (PROGRAMS_CARD_RADIUS px at
   small scale, 0 at full scale) — not set here. */
.programs-card {
  position: relative;
  width: 100%;
  height: 100%;
  background: #FFFBF3;
  box-shadow: 0 30px 60px -20px rgba(63, 63, 63, 0.25), 0 4px 16px rgba(63, 63, 63, 0.08);
  display: grid;
  grid-template-columns: 1fr 1fr;
  overflow: hidden;
  will-change: transform, opacity, border-radius;
  transform-origin: 50% 50%;
}
@media (max-width: 767px) {
  .programs-card {
    grid-template-columns: 1fr;
    grid-template-rows: minmax(0, 34%) 1fr;
  }
}

/* Real photo (PSCC) fills the slot; the placeholder treatment (every other
   program — no genuine photo exists in the client archive, per
   HOME_CONTENT_DRAFT.md §5) reuses the same mandala-watermark + "coming
   soon" badge language already established on Who We Are's photo slot,
   rather than inventing a second placeholder convention. */
.programs-card-media {
  position: relative;
  overflow: hidden;
  background: linear-gradient(135deg, rgba(251, 105, 0, 0.16), rgba(255, 205, 133, 0.45) 60%, rgba(251, 105, 0, 0.12));
  border-right: 1px solid rgba(63, 63, 63, 0.08);
  display: flex;
  align-items: center;
  justify-content: center;
}
@media (max-width: 767px) {
  .programs-card-media {
    border-right: none;
    border-bottom: 1px solid rgba(63, 63, 63, 0.08);
  }
}
.programs-card-photo {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.programs-card-motif {
  width: 50%;
  height: 50%;
  object-fit: contain;
  opacity: 0.3;
}
.programs-card-placeholder-badge {
  position: absolute;
  bottom: 1rem;
  right: 1rem;
  border-radius: 9999px;
  background: rgba(255, 255, 255, 0.75);
  backdrop-filter: blur(6px);
  padding: 0.35rem 0.85rem;
  font-size: 0.7rem;
  font-weight: 500;
  color: rgba(63, 63, 63, 0.7);
}

.programs-card-inner {
  padding: clamp(2rem, 5vw, 5rem);
  display: flex;
  flex-direction: column;
  justify-content: center;
  opacity: 0;
  transform: translateY(16px);
  min-height: 0;
  overflow: auto;
}
.programs-card-inner > * {
  max-width: 34rem; /* keeps line length readable now the card itself is full-viewport-wide */
}

#programsIntro {
  min-height: 60svh;
}

/* Reduced-motion override: same DOM, normal flow, no pin/scale. */
#programsStage.programs-stage--reduced {
  height: auto;
  overflow: visible;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2.5rem;
  padding: 3rem 1.5rem 5rem;
  background: none;
}
#programsStage.programs-stage--reduced .programs-slot {
  position: static;
  padding: 0;
  width: 100%;
}
#programsStage.programs-stage--reduced .programs-card {
  width: 100%;
  max-width: 900px;
  height: auto;
  margin: 0 auto;
  border-radius: 2rem; /* pinned mode animates this via GSAP; reduced mode needs its own static value */
}
#programsStage.programs-stage--reduced .programs-card-inner {
  overflow: visible;
}
@media (max-width: 767px) {
  #programsStage.programs-stage--reduced .programs-card {
    grid-template-rows: 220px auto;
  }
}

/* ================= Cross-page wipe transition (js/page-transition.js) =====
   Per DESIGN_UX_ANIMATION_SPEC.md §1.7: every page gets the lightweight
   top-bar loader by default; entering About → Swami ji specifically gets a
   heavier full-screen solid-color wipe. One shared overlay element/script,
   present on every page that can navigate to or from that one page —
   dormant (no wipe) everywhere else. */
#wipeTransition {
  position: fixed;
  inset: 0;
  z-index: 90; /* above page content, below #loadingOverlay's z-100 */
  background: #FB6900;
  transform: scaleY(0);
  transform-origin: bottom;
  pointer-events: none;
  will-change: transform;
}

/* ================= About → Swami ji (biography page) =================
   Rebuilt as a cinematic, full-viewport scroll-snap sequence (matching
   Home's own mechanism — see index.html's <main> comment) rather than a
   continuous-scroll article. Real decision, not a default: the earlier
   continuous-scroll build with a side-gutter thread read as a standard
   long-form page, not the flagship, full-scale-motion page the design
   spec calls for. Each "beat" below is its own .snap-section. */

.swamiji-beat {
  position: relative;
  height: 100dvh;
  width: 100%;
  overflow: hidden;
  display: flex;
  align-items: center;
}

/* Photo beats — full-bleed real archival photo or extracted video frame,
   with a dark gradient so white/dark text stays legible over any part of
   the image. js/about-swamiji.js adds a slow Ken Burns scale (subtle
   zoom-in tied to the beat's own scroll-snap dwell) on the media layer —
   cinematic movement without competing with the text reveal. */
.swamiji-beat-media {
  position: absolute;
  inset: 0;
  z-index: 0;
  overflow: hidden;
}
.swamiji-beat-media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  will-change: transform;
}
/* DSC05420.jpg is near-square (700x749) — in a wide full-bleed beat,
   object-fit:cover's default center crop loses most of the frame's
   height, which cuts his face out of view entirely (only the robe/torso
   remained visible). Biased toward the top instead, where his face
   actually sits in the source photo. Scoped to this one title-beat use
   of the image (Home's own hero crops it inside a narrower portrait box,
   where the default center crop already keeps his face in frame). */
.swamiji-title-portrait {
  object-position: 50% 10%;
}
/* aftersannyas.jpg — default center crop (50% 50%) favored the right side
   of the group, pushing the senior guru figure (white shawl, left-of-
   center in the source photo) uncomfortably close to the text overlay's
   edge at narrow widths. Shifted left so both he and Swamiji read clearly
   in frame together. */
.swamiji-vow-portrait {
  object-position: 25% 35%;
}
.swamiji-beat-overlay {
  position: absolute;
  inset: 0;
  z-index: 1;
  background: linear-gradient(180deg, rgba(20, 14, 8, 0.15) 0%, rgba(20, 14, 8, 0.55) 65%, rgba(20, 14, 8, 0.75) 100%);
}
.swamiji-beat--photo .swamiji-beat-content {
  color: #FFFBF3;
}
.swamiji-beat--photo .swamiji-beat-eyebrow {
  color: #FFCD85; /* warm gold, legible on the dark overlay — not the site's usual orange-safety, which loses contrast here */
}

/* Growing-circular-reveal — reserved for the two heaviest archival photos
   only (bhuj-entry.jpg, aftersannyas.jpg), per §2.3: "the other chapters
   stay simpler... so motion budget concentrates where the real content
   is." The extracted video-frame photos (founding ceremony, teaching,
   podium) get the plain Ken Burns treatment instead — a deliberate
   distinction between "precious archival find" and "found footage." */
.swamiji-beat-media--circle-reveal {
  clip-path: circle(0% at 50% 50%);
}

.swamiji-beat-content {
  position: relative;
  z-index: 2;
  max-width: 46rem;
  padding: 0 1.5rem;
}
@media (min-width: 768px) {
  .swamiji-beat-content {
    padding: 0 3rem;
  }
}

/* Text-only beats (no photo yet found for these moments in the archive)
   keep the page's normal papaya background + a faint mandala watermark,
   rather than forcing a photo that doesn't exist. */
.swamiji-beat--text {
  background: #FFEFD4;
}
.swamiji-beat--text .swamiji-beat-watermark {
  position: absolute;
  inset: 0;
  z-index: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  pointer-events: none;
}
.swamiji-beat--text .swamiji-beat-watermark img {
  width: 60vw;
  max-width: 32rem;
  opacity: 0.06;
}

.swamiji-beat-stat {
  display: inline-block;
  margin-top: 1.25rem;
  padding: 0.5rem 1.1rem;
  border-radius: 9999px;
  font-size: 0.85rem;
  font-weight: 500;
  background: rgba(255, 255, 255, 0.14);
  backdrop-filter: blur(6px);
  border: 1px solid rgba(255, 255, 255, 0.25);
}
.swamiji-beat--text .swamiji-beat-stat {
  background: rgba(251, 105, 0, 0.1);
  border: 1px solid rgba(251, 105, 0, 0.25);
  color: #FB6900;
}

/* Pull-quote — third-person, per content decision (not a fabricated direct
   quote). Opening beat only. */
.swamiji-pullquote {
  font-family: "Literata", "Noto Serif Devanagari", serif;
  font-style: italic;
}

/* Progress dots — replaces the old side-gutter thread now that beats are
   full-viewport snap panels, not a continuous column with room for a
   rail. One dot per beat; the current one fills in as its section snaps
   into place (js/about-swamiji.js, same "section arrival = divider" idea
   as §1.6, just rendered as a fixed indicator instead of an inline mark). */
#swamijiProgress {
  position: fixed;
  right: 1.25rem;
  top: 50%;
  transform: translateY(-50%);
  z-index: 20;
  display: none;
  flex-direction: column;
  gap: 0.6rem;
}
@media (min-width: 768px) {
  #swamijiProgress {
    display: flex;
  }
}
.swamiji-progress-dot {
  width: 7px;
  height: 7px;
  border-radius: 9999px;
  background: rgba(63, 63, 63, 0.25);
  transition: background 0.3s var(--ease-calm), transform 0.3s var(--ease-calm);
}
.swamiji-progress-dot.is-active {
  background: #FB6900;
  transform: scale(1.4);
}

/* ================= About → AAKB (institutional page) =================
   Rebuilt as full-viewport scroll-snap panels (one .snap-section per
   .aakb-block), matching Lakshyavedh's own treatment — see
   about-aakb.html's own comment. The old .aakb-divider rule is gone
   (nothing to divide — the panel boundary itself is the divider now). */
.aakb-block {
  position: relative;
}

.aakb-pillar {
  padding: 1.75rem;
  border-radius: 1.25rem;
  background: #FFFBF3;
  box-shadow: 0 20px 40px -24px rgba(63, 63, 63, 0.18);
}
@media (min-width: 768px) {
  .aakb-pillar {
    padding: 2.25rem;
  }
}

.aakb-trustee-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  padding: 1.5rem;
  border-radius: 1.25rem;
  background: #FFFBF3;
  box-shadow: 0 20px 40px -24px rgba(63, 63, 63, 0.18);
}
@media (min-width: 768px) {
  .aakb-trustee-card {
    padding: 1.75rem;
  }
}
.aakb-trustee-photo {
  width: 5.5rem;
  height: 5.5rem;
  border-radius: 9999px;
  overflow: hidden;
  box-shadow: 0 8px 20px -8px rgba(63, 63, 63, 0.3);
}
@media (min-width: 768px) {
  .aakb-trustee-photo {
    width: 7rem;
    height: 7rem;
  }
}
.aakb-trustee-photo img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

