/* Small custom touches that go beyond Tailwind utilities */

html {
  scroll-behavior: smooth;
}

/* Safety net: a few decorative elements (e.g. the rotating "AI TECH DIGI"
   seal) are intentionally positioned past their container's edge. Clip any
   stray overflow at the viewport instead of letting it create a horizontal
   scrollbar on mobile. */
html,
body {
  overflow-x: hidden;
}

/* Fluid media. This deliberately matches Tailwind's Preflight (`max-width: 100%`) rather than
   overriding it.

   DO NOT set this to 98%. It was 98% briefly and it painted a black strip down the whole right edge
   of the hero: .hero-still and the hero <video> are both `w-full object-cover` cover layers, and
   max-width beats `w-full` regardless of specificity, so each stopped ~30px short of the viewport
   and exposed the section's own bg-[#050C05] behind them -- full height, so it read as black space
   on the right and across the top. The same 2% gap opened on all 24 cover images and clips on the
   page (process cards, blog thumbnails, testimonial videos).

   If you want breathing room around content images, scope it to those images instead of every
   <img> and <video> on the page, e.g.:
     @media (max-width: 640px) { .prose img { max-width: 98%; } } */
img,
video {
  max-width: 100%;
  height: auto;
}

/* Custom scrollbar.
   The track MUST stay light. It was #121212 originally, which painted a near-black column down the
   full right edge of the viewport on every section of the page -- easy to mistake for a gap in the
   layout, especially next to the hero video. The page is light, so the track has to be light too. */
html {
  scrollbar-width: thin;
  scrollbar-color: #1F5D34 #EFEFEF;
}

::-webkit-scrollbar {
  width: 10px;
  background: #EFEFEF;
}

::-webkit-scrollbar-track {
  background: #EFEFEF;
}

::-webkit-scrollbar-thumb {
  background-color: #1F5D34;
  border-radius: 999px;
  border: 2px solid #EFEFEF;
  background-clip: padding-box;
}

::-webkit-scrollbar-thumb:hover {
  background-color: #164526;
}

/* Mobile hamburger -> X animation */
#menuBtn.is-open .menu-bar:nth-child(1) {
  transform: translateY(6px) rotate(45deg);
}

#menuBtn.is-open .menu-bar:nth-child(2) {
  opacity: 0;
}

#menuBtn.is-open .menu-bar:nth-child(3) {
  transform: translateY(-6px) rotate(-45deg);
}

/* Slow rotation for the circular "AI TECH DIGI" seal in the About section */
@keyframes spin-slow {
  to {
    transform: rotate(360deg);
  }
}

.animate-spin-slow {
  animation: spin-slow 8s linear infinite;
}

/* Services cards: the featured card is full size by default. Hovering any
   card in the row expands that card to full size and shrinks the rest,
   including the featured one. Desktop only -- mobile keeps its scroll row. */
@media (min-width: 1024px) {
  .service-row .service-card {
    flex-grow: 1;
    flex-basis: 0%;
    transition: flex-grow 0.5s cubic-bezier(0.4, 0, 0.2, 1);
  }

  .service-row .service-card.is-featured {
    flex-grow: 3;
  }

  .service-row:hover .service-card {
    flex-grow: 1;
  }

  .service-row:hover .service-card:hover {
    flex-grow: 3;
  }

  /* Description + Learn More: visible on the featured card by default,
     swaps to whichever card is hovered, hidden on every other card. */
  .service-card .service-desc-panel {
    display: grid;
    grid-template-rows: 0fr;
    transition: grid-template-rows 0.4s ease;
  }

  .service-card .service-desc-panel>div {
    overflow: hidden;
  }

  .service-card.is-featured .service-desc-panel {
    grid-template-rows: 1fr;
  }

  .service-row:hover .service-card .service-desc-panel {
    grid-template-rows: 0fr;
  }

  .service-row:hover .service-card:hover .service-desc-panel {
    grid-template-rows: 1fr;
  }
}

/* "How It Works" slider: equal-height cards, no default Slick arrows/dots */
.why-slider .slick-track {
  display: flex !important;
}

.why-slider .slick-slide {
  height: auto;
}

.why-slider .slick-slide>div {
  height: 100%;
}

/* Running marquee under the video section: two identical groups placed
   side by side, scrolled left by exactly one group's width for a seamless loop. */
.marquee-track {
  animation: marquee-scroll 24s linear infinite;
}

.marquee:hover .marquee-track {
  animation-play-state: paused;
}

@keyframes marquee-scroll {
  from {
    transform: translateX(0);
  }

  to {
    transform: translateX(-50%);
  }
}

/* Team slider: equal-height cards, plain (unboxed) dot row */
.team-slider .slick-track {
  display: flex !important;
}

.team-slider .slick-slide {
  height: auto;
}

.team-slider .slick-slide>div {
  height: 100%;
}

.team-dots ul.slick-dots {
  position: static;
  width: -moz-fit-content;
  width: fit-content;
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  list-style: none;
  margin: 0;
  padding: 0;
}

.team-dots ul.slick-dots li {
  width: auto;
  height: auto;
  margin: 0;
}

.team-dots ul.slick-dots li button {
  width: 8px;
  height: 8px;
  padding: 0;
  border-radius: 9999px;
  background: #d1d5db;
  font-size: 0;
  line-height: 0;
  transition: background-color 0.3s, width 0.3s;
}

.team-dots ul.slick-dots li button:before {
  content: none;
}

.team-dots ul.slick-dots li.slick-active button {
  width: 20px;
  background: #121212;
}

/* FAQ accordion: smooth height animation via the 0fr/1fr grid-rows trick
   (no JS height measurement needed), plus-to-minus icon via opacity fade. */
.faq-panel {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows 0.35s ease;
}

.faq-item.is-open .faq-panel {
  grid-template-rows: 1fr;
}

.faq-panel-inner {
  overflow: hidden;
}

.faq-icon-vert {
  transition: opacity 0.2s ease;
  transform-origin: center;
}

.faq-item.is-open .faq-icon-vert {
  opacity: 0;
}


/* ============ MOBILE RESPONSIVE FIXES (<= 768px) ============ */
@media (max-width: 768px) {

  /* Rotating "AI TECH DIGI" seal: its desktop offset (-right-6/-bottom-6)
     pushes it past the page's own side padding on narrow screens, which is
     what was creating the horizontal overflow. Pull it back in. */
  .seal-badge {
    right: -0.25rem;
    bottom: -0.25rem;
  }
}

.rounded-full-1 {
  border-radius: 100% !important;
}

.rounded-full {
  border-radius: 10px !important;
}

/* "Arrow" CTA pills (text + circular arrow icon, e.g. "Let's Talk", "Book Now",
   "Learn More"...): on hover, the icon's own background floods outward from
   its circle to fill the whole pill, and the arrow keeps sliding in place. */
.arrow-btn {
  position: relative;
  z-index: 0;
  overflow: hidden;
  transition: color 0.4s ease, border-color 0.4s ease;
}

.arrow-btn.absolute {
  position: absolute;
}

.arrow-btn:hover {
  color: #fff !important;
  border-color: var(--arrow-btn-fill, #1F5D34) !important;
}

/* Negative z-index puts the icon (and the flood it grows) behind the
   button's own label text, so the flood sweeps under the words instead
   of covering them. */
.arrow-btn .arrow-btn-icon {
  position: relative;
  z-index: -1;
}

.arrow-btn .arrow-btn-icon::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 0;
  border-radius: inherit;
  background-color: var(--arrow-btn-fill, #1F5D34);
  transform: scale(1);
  transition: transform 0.45s cubic-bezier(0.4, 0, 0.2, 1);
}

.arrow-btn:hover .arrow-btn-icon::before {
  transform: scale(35);
}

.arrow-btn .arrow-btn-icon svg {
  position: relative;
  z-index: 1;
}

.arrow-btn:hover .arrow-btn-icon svg {
  animation: arrow-slide-x 0.9s ease-in-out infinite;
}

@keyframes arrow-slide-x {

  0%,
  100% {
    transform: translateX(0);
  }

  50% {
    transform: translateX(4px);
  }
}


/* ============================================================================
   HERO -- "Mahadev Dairy" cinematic banner
   ----------------------------------------------------------------------------
   ARCHITECTURE (read before editing):

     photo  ->  video  ->  cinematic tint  ->  left gradient  ->  content/decor

   There is deliberately NO left/right column split. Everything is a full-bleed
   layer and the copy simply floats on top. That is the whole point: a split
   creates a boundary, and a boundary between two different images always shows
   up as a seam no matter how it is feathered.

   The one join that does exist -- where the video fades out over the photo --
   is placed entirely INSIDE the dark part of the left gradient, so it happens
   under ~40-90% black and cannot be perceived. If you ever shorten the gradient
   or lengthen the video mask so they stop overlapping, the seam comes back.
   ========================================================================== */

/* Hero palette. These sit on :root, NOT on .hero, and that placement is deliberate.
   The <header> is a SIBLING of the hero section, not a descendant -- so while these were scoped to
   .hero, every var() lookup in header CSS resolved to nothing, and a declaration built on an
   undefined custom property is dropped as invalid at computed-value time. Three things were
   silently losing their background because of it: .hdr-call (no dark glass), .hdr-call-icon (no
   gold disc, which left a near-black glyph on nothing) and the .hero-glass mobile menu panel.
   Anything genuinely hero-only belongs in the .hero rule below instead. */
:root {
  --hero-ink: 5, 12, 5;
  /* deep green-black, as rgb parts for rgba() */
  --hero-gold: #DCB45A;
  --hero-cream: #F6E9CE;
}

.hero {
  min-height: 100vh;
}

/* Devanagari headline. Noto is listed first because Poppins' Devanagari glyphs are much lighter
   than its Latin ones at the same weight -- left to Poppins the Hindi heading renders visibly
   thinner than the rest of the page. Poppins stays in the stack for any Latin characters or
   punctuation mixed into the same line. */
.font-hi {
  font-family: 'Noto Sans Devanagari', 'Poppins', sans-serif;
  /* Devanagari has no uppercase and tight conjuncts; letter-spacing hurts it. */
  letter-spacing: 0;
}

/* Video layer: anchored right and faded out toward the left.
   Its width is capped in the markup rather than set as a plain percentage. The source is 576x1024,
   so every extra pixel of width is pure upscaling -- that is what reads as both "zoomed" and "blurry",
   and a percentage width makes it worse on larger monitors rather than better.

   The ramp is expressed in % of this element, so its real length moves with the width cap above:
   ~48% of ~820px is roughly 390px of feather. Long enough to hide the join, short enough that the
   photo showing through the semi-transparent part does not read as a double exposure. If the cap
   changes a lot, re-check this -- the two are linked. */
.hero-video-layer {
  -webkit-mask-image: linear-gradient(90deg, transparent 0%, rgba(0, 0, 0, 0.3) 18%, rgba(0, 0, 0, 0.8) 34%, #000 48%);
  mask-image: linear-gradient(90deg, transparent 0%, rgba(0, 0, 0, 0.3) 18%, rgba(0, 0, 0, 0.8) 34%, #000 48%);

  /* PERFORMANCE: a mask over a playing video is expensive -- without its own compositor layer the
     browser re-composites the masked frame on the main thread and playback judders. Promoting the
     layer lets the mask be applied once on the GPU instead of per frame. */
  transform: translateZ(0);
  will-change: transform;
}

.hero-video-layer video {
  /* Same reason: keep the video itself on its own layer so decoded frames go straight to the
     compositor rather than being repainted with everything stacked above them. */
  transform: translateZ(0);
  backface-visibility: hidden;
}

/* Let clicks through the EMPTY half of the copy column, so the sound button can be pressed.
   ----------------------------------------------------------------------------------------
   .hero-copy is a full-bleed flex wrapper (max-width 1600px) whose only child is a narrow text
   column, so on any window under ~1600px it stretches edge to edge and its empty right-hand half
   lies directly over the sound button in the video layer's bottom-right corner. It is z-20 and
   hit-testable, so it swallowed every click aimed at that button.

   Raising the button did not help and cannot: .hero-video-layer is promoted for the mask
   (transform + will-change above), which makes it a STACKING CONTEXT, so the button's z-30 only
   ranks it inside that layer. The layer itself is z-auto, so the whole subtree -- button included --
   paints below .hero-copy's z-20. Lifting the layer above the copy instead would put the video over
   the headline and above the two gradients that keep it readable, which is worse.

   Hence pointer-events rather than z-index: the wrapper stops catching clicks, its child column
   (headline, offer card, both CTAs, and text selection) keeps them exactly as before. This is also
   why the rule targets the direct child rather than a list of links -- add anything to the column
   later and it keeps working.

   Symptom if this regresses: the sound button works at >=1600px wide and is dead below it. */
.hero-copy {
  pointer-events: none;
}

.hero-copy > * {
  pointer-events: auto;
}

/* The left-side darkening that lets the copy read. Its dark end must extend
   past where the video mask finishes so the two overlap -- see the note above. */
.hero-gradient {
  background: linear-gradient(90deg,
      rgba(var(--hero-ink), 0.92) 0%,
      rgba(var(--hero-ink), 0.78) 25%,
      rgba(var(--hero-ink), 0.40) 45%,
      rgba(var(--hero-ink), 0.08) 65%,
      transparent 100%);
}

/* Overall cinematic grade: a touch of green in the shadows plus a vignette, so
   the photo and the video sit in the same colour world instead of looking like
   two different sources.

   NOTE: this deliberately does NOT darken the top any more. The header already has its own top
   vignette for nav legibility, and the two used to stack -- 0.55 here under 0.60 there compounds to
   ~82% black, which turned the whole top strip into a black bar (worst over the video, which is
   darker than the photo). Darken the top in ONE place only. The edge vignette is likewise kept
   light, since it compounds with that same top gradient in the corners. */
.hero-grade {
  background:
    radial-gradient(140% 115% at 50% 45%, transparent 62%, rgba(var(--hero-ink), 0.28) 100%),
    linear-gradient(180deg, transparent 0%, transparent 68%, rgba(var(--hero-ink), 0.62) 100%);
}

/* --- Glass surfaces --------------------------------------------------------- */

/* PERFORMANCE: backdrop-filter is the single most expensive thing that can sit over a playing video --
   the browser has to re-blur everything behind the panel on every frame, and with several panels on
   screen that alone is enough to make the clip stutter.
   So the blur is kept small and the fill is carried mostly by opacity instead. If playback is still
   uneven, delete the two backdrop-filter lines below entirely: the panels barely change, because the
   background alpha is already doing most of the work. */
.hero-glass {
  background: rgba(var(--hero-ink), 0.55);
  border: 1px solid rgba(255, 255, 255, 0.14);
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
}

/* No backdrop-filter at all: this is the widest panel on the page, so it was the costliest to
   re-blur each frame. A more opaque fill gives the same read for free. */
.hero-strip {
  background: rgba(46, 37, 14, 0.72);
  border: 1px solid rgba(220, 180, 90, 0.45);
  border-radius: 18px;
}

/* --- CTA -------------------------------------------------------------------- */

.hero-cta {
  box-shadow: 0 10px 30px rgba(31, 93, 52, 0.38);
  transition: transform 0.35s cubic-bezier(0.2, 0.7, 0.2, 1), box-shadow 0.35s ease, background-color 0.25s ease;
}

.hero-cta:hover {
  transform: translateY(-3px);
  box-shadow: 0 16px 40px rgba(31, 93, 52, 0.5);
}

/* Secondary CTA. Gold glass rather than a second solid fill: two solid buttons side by side
   compete, and orange next to another saturated colour muddies the brand accent. This picks up
   the same gold as the seal and the feature strip, so it reads as part of the system. */
.hero-cta-alt {
  color: var(--hero-cream, #F6E9CE);
  /* Opaque fill rather than a backdrop blur -- see the note on .hero-glass above. */
  background: rgba(46, 37, 14, 0.72);
  border: 1px solid rgba(220, 180, 90, 0.6);
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3);
  transition: transform 0.35s cubic-bezier(0.2, 0.7, 0.2, 1), box-shadow 0.35s ease,
    background-color 0.25s ease, color 0.25s ease, border-color 0.25s ease;
}

.hero-cta-alt:hover {
  transform: translateY(-3px);
  color: #3A2A0B;
  background: rgba(224, 190, 110, 0.95);
  border-color: rgba(240, 214, 150, 0.9);
  box-shadow: 0 16px 40px rgba(220, 180, 90, 0.35);
}

/* --- Entrance choreography -------------------------------------------------- */

@keyframes hero-rise {
  from {
    opacity: 0;
    transform: translateY(26px);
  }

  to {
    opacity: 1;
    transform: none;
  }
}

.hero-rise {
  animation: hero-rise 0.95s cubic-bezier(0.2, 0.7, 0.2, 1) both;
}

/* --- Idle motion ------------------------------------------------------------ */

@keyframes hero-float {

  0%,
  100% {
    transform: translateY(0);
  }

  50% {
    transform: translateY(-12px);
  }
}

/* will-change keeps these on their own layers. The matka and the seal both sit directly over the
   video, and an animated element that is NOT promoted forces the video underneath to repaint on
   every step of the animation. */
.hero-floats {
  animation: hero-float 7s ease-in-out infinite;
  will-change: transform;
}

/* Gold seal. No rim: the depth comes from the sunburst behind it and a soft drop shadow, so the
   edge stays clean instead of being outlined.
   `isolation` is needed because the gloss sweep is an ::after that must stay clipped inside the
   circle -- without it the band can bleed past the rounded edge on some browsers. The sweep rests
   for most of the cycle (see the keyframe stops) so it reads as an occasional glint rather than a
   constant shimmer. */
.hero-seal {
  position: relative;
  isolation: isolate;
  box-shadow: 0 14px 38px rgba(0, 0, 0, 0.4);
  /* clip-path, not just overflow:hidden + border-radius. The image inside carries its own transform
     (scale) and an ancestor animates a transform too, and in that situation the rounded overflow clip
     is unreliable -- the PNG's square corners leak through as a visible box. clip-path always wins. */
  -webkit-clip-path: circle(50% at 50% 50%);
  clip-path: circle(50% at 50% 50%);
}

/* Sunburst behind the seal: a warm radial glow plus slowly rotating rays. The rays are a repeating
   conic gradient masked to fade out before the edge -- without that mask they stop on a hard circle
   and read as a cog rather than light. */
.hero-sun {
  pointer-events: none;
  background: radial-gradient(closest-side,
      rgba(255, 226, 155, 0.55) 0%,
      rgba(255, 193, 95, 0.30) 40%,
      rgba(255, 170, 60, 0.10) 62%,
      transparent 76%);
  animation: hero-sun-pulse 6s ease-in-out infinite;
}

.hero-sun::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: repeating-conic-gradient(from 0deg,
      rgba(255, 231, 170, 0.26) 0deg 3.5deg,
      transparent 3.5deg 13deg);
  -webkit-mask-image: radial-gradient(closest-side, rgba(0, 0, 0, 0.9) 22%, transparent 70%);
  mask-image: radial-gradient(closest-side, rgba(0, 0, 0, 0.9) 22%, transparent 70%);
  /* Safety net: a conic gradient fills its box corner to corner, so if mask-image is unsupported the
     rays would render as a rotating square. This keeps them circular either way. */
  -webkit-clip-path: circle(50% at 50% 50%);
  clip-path: circle(50% at 50% 50%);
  animation: hero-sun-rotate 48s linear infinite;
  /* Promoted so the masked conic gradient is rasterised once and then merely rotated, instead of
     being re-painted every frame over the video behind it. */
  will-change: transform;
}

@keyframes hero-sun-rotate {
  to {
    transform: rotate(360deg);
  }
}

@keyframes hero-sun-pulse {

  0%,
  100% {
    opacity: 0.75;
  }

  50% {
    opacity: 1;
  }
}

.hero-seal::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
  background: linear-gradient(115deg,
      transparent 38%,
      rgba(255, 255, 255, 0.45) 47%,
      rgba(255, 255, 255, 0.8) 51%,
      rgba(255, 255, 255, 0.45) 55%,
      transparent 64%);
  transform: translateX(-130%);
  animation: hero-seal-shine 6s ease-in-out infinite;
}

@keyframes hero-seal-shine {
  0% {
    transform: translateX(-130%);
  }

  35%,
  100% {
    transform: translateX(130%);
  }
}

/* Everything decorative stops moving for users who ask for reduced motion; the
   entrance animations resolve to their final state rather than being skipped. */
@media (prefers-reduced-motion: reduce) {

  .hero-floats,
  .hero-seal::after,
  .hero-sun,
  .hero-sun::after {
    animation: none;
  }

  .hero-rise {
    animation-duration: 1ms;
  }

  .hero-cta:hover,
  .hero-cta-alt:hover {
    transform: none;
  }
}

/* --- Responsive ------------------------------------------------------------- */

/* Below lg the video becomes the full background, so the gradient has to carry
   all the way across to keep the copy readable rather than fading out mid-screen. */
@media (max-width: 1023px) {
  .hero-video-layer {
    -webkit-mask-image: none;
    mask-image: none;
  }

  .hero-gradient {
    background: linear-gradient(180deg,
        rgba(var(--hero-ink), 0.82) 0%,
        rgba(var(--hero-ink), 0.72) 45%,
        rgba(var(--hero-ink), 0.88) 100%);
  }
}

@media (max-width: 640px) {
  .hero {
    min-height: 92vh;
  }
}

/* ============================================================================
   VIDEO BANNER (#our-process)
   ----------------------------------------------------------------------------
   The banner holds a real <video> that only starts on a click. Everything drawn
   over it -- grade, heading, brand lockup -- is chrome for the POSTER state, so
   it all clears out of the way on play and comes back on pause/end. The single
   .is-playing class on the wrapper drives every one of those transitions;
   js/script.js does nothing but toggle it.
   ========================================================================== */

/* Requested: no hard black slab behind the clip. Browsers paint a black ground behind a <video>
   by default -- visible before the poster or first frame is decoded, and anywhere object-cover
   does not reach -- so both the wrapper and the element itself are held transparent. */
.video-banner,
.video-banner video {
  background: transparent;
}

/* The mat: a translucent mount around the video, like the border of a framed print. Kept as a
   real element rather than a border on the video itself, because the video is clipped by
   overflow-hidden + rounded corners -- a border there would be cut by its own clip. */
/* The mat used to be a visible mount -- translucent white fill, gold hairline, a few
   pixels of padding showing as a rim. All of that is off now: the card sits straight
   on the background photograph with nothing framing it.

   The wrapper element stays rather than being deleted, because it is what carries the
   height-derived max-width that keeps the section to one screen (see .process-stage).
   It is simply invisible: transparent border and fill, no blur, no rim.

   The shadow that used to sit here is gone too -- at this size it read as a frame around
   the video rather than as depth under it, which is the opposite of merging into the
   background. Nothing is drawn on this element at all now. */
.video-mat {
  box-shadow: none;
}

/* Feathered edges, so the card dissolves into the pasture instead of ending on a hard
   rectangle. Two masks -- one fading left/right, one fading top/bottom -- intersected, so
   all four sides and the corners fade together. A single radial gradient would have been
   simpler but it fades in an ellipse, which eats the corners of the artwork.

   --edge is how far in the fade reaches. 2.5% of a 1152px card is about 29px: enough to
   dissolve the join, small enough that the thumbnail's own artwork survives it.

   Degrades safely: where mask-composite is unsupported the two masks simply add together
   instead of intersecting, which shows the whole card unfeathered -- no fade, nothing
   broken. Set --edge to 0 for crisp edges again. */
.process-stage .video-banner {
  --edge: 2.5%;
  -webkit-mask-image:
    linear-gradient(to right, transparent 0, #000 var(--edge), #000 calc(100% - var(--edge)), transparent 100%),
    linear-gradient(to bottom, transparent 0, #000 var(--edge), #000 calc(100% - var(--edge)), transparent 100%);
  mask-image:
    linear-gradient(to right, transparent 0, #000 var(--edge), #000 calc(100% - var(--edge)), transparent 100%),
    linear-gradient(to bottom, transparent 0, #000 var(--edge), #000 calc(100% - var(--edge)), transparent 100%);
  -webkit-mask-composite: source-in;
  mask-composite: intersect;
}

/* Resting opacity, so the process card sits back into the section instead of shouting over it.
   It comes up to full on hover and stays there while playing -- nobody should watch a video at
   94%. Scoped to .process-stage: the testimonial player reuses .video-banner for its controls and
   should not be dimmed. */
.process-stage .video-banner {
  opacity: 0.94;
  transition: opacity 0.45s ease;
}

.video-mat:hover .video-banner,
.video-banner.is-playing {
  opacity: 1;
}

/* Nothing is drawn over the poster any more: no grade, no caption, no lockup. The thumbnail is
   finished artwork that already carries its own headline and wordmark, so anything laid on top was
   a second set of type fighting the first. Only the play and sound buttons remain. */

/* Gold-rimmed glass, matching .hero-cta-alt rather than the old white/15 disc.
   No transform here on purpose: the button carries Tailwind's -translate-x-1/2
   -translate-y-1/2 centring plus hover:scale-105, and Tailwind composes those
   into one transform via CSS variables -- a transform declared here would
   replace the whole thing and knock the button off centre. */
.video-banner-btn {
  background: rgba(10, 26, 12, 0.5);
  border: 2px solid rgba(220, 180, 90, 0.8);
  color: var(--md-cream, #F6E9CE);
  -webkit-backdrop-filter: blur(4px);
  backdrop-filter: blur(4px);
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.35);
  transition: background-color 0.3s ease, color 0.3s ease, border-color 0.3s ease,
    opacity 0.35s ease, transform 0.3s ease;
}

.video-banner-btn:hover {
  background: rgba(220, 180, 90, 0.92);
  border-color: rgba(240, 214, 150, 0.9);
  color: #1A1206;
}

/* While playing, the controls get out of the way and only return on hover
   (or on keyboard focus -- otherwise they would be unreachable by tab). */
.video-banner.is-playing .video-banner-btn {
  opacity: 0;
}

.video-banner.is-playing:hover .video-banner-btn,
.video-banner .video-banner-btn:focus-visible {
  opacity: 1;
}

/* Sound toggle: hidden entirely until there is audio to control. */
.video-banner-sound {
  background: rgba(10, 26, 12, 0.55);
  border: 1px solid rgba(220, 180, 90, 0.55);
  color: var(--md-cream, #F6E9CE);
  -webkit-backdrop-filter: blur(4px);
  backdrop-filter: blur(4px);
  opacity: 0;
  pointer-events: none;
  transition: background-color 0.3s ease, color 0.3s ease, opacity 0.35s ease;
}

.video-banner.is-playing .video-banner-sound {
  opacity: 1;
  pointer-events: auto;
}

.video-banner-sound:hover {
  background: rgba(220, 180, 90, 0.92);
  color: #1A1206;
}

@media (prefers-reduced-motion: reduce) {

  .video-banner-btn,
  .video-banner-sound {
    transition-duration: 1ms;
  }
}

/* ============================================================================
   "OUR PROCESS" -- ONE-SCREEN LAYOUT (#our-process)
   ----------------------------------------------------------------------------
   The section fills exactly one viewport: heading, video, marquee, no scroll.

   Layout: a flex column -- heading (shrink-0), video (flex-1), marquee (shrink-0).
   The card stays width-driven, but its max-width is capped by the height left
   over, so a 16:9 card can never be taller than the space it has. See the note
   on .process-stage .video-mat below for why the height-driven version fails.
   ========================================================================== */

.process-screen {
  /* svh, not vh: on mobile, vh is the height with the address bar HIDDEN, so a
     100vh section is taller than what you can actually see when the bar is
     showing -- the marquee would sit just off the bottom of the screen. */
  min-height: 100svh;
}

@supports not (height: 100svh) {
  .process-screen {
    min-height: 100vh;
  }
}

.process-stage {
  /* min-height:0 is required. A flex item defaults to min-height:auto, which
     refuses to shrink below its content. */
  flex: 1 1 auto;
  min-height: 0;
}

/* Fit the card to the leftover height WITHOUT percentage heights.

   The obvious approach -- height:100% down the chain, width derived from the
   aspect ratio -- does not work here, and this is the trap to avoid: the section
   uses min-height, so its height is content-based, and a percentage height
   against an auto height computes to auto. Both axes then resolve to auto, and
   because the <video> inside is position:absolute the card has no in-flow content
   to size against, so it collapses to 0x0 and the video vanishes.

   So the card stays width-driven (w-full + aspect-[16/9], the reliable direction)
   and instead its max-width is capped by the height available: whatever is left
   of the viewport after the heading and marquee, converted to a width through the
   16:9 ratio. The 21rem is that chrome allowance; adjust it if the heading grows.
   max() keeps the card from shrinking to nothing on very short windows. */
@media (min-width: 1024px) {
  .process-stage .video-mat {
    max-width: min(72rem, max(28rem, calc((100svh - 21rem) * 16 / 9)));
  }
}

/* Below lg the screen is tall and narrow, so leftover height would make the card
   comically small. There the card goes back to filling the width, and the
   section simply grows past one screen if it must -- readable beats rigid. */
@media (max-width: 1023px) {
  .process-screen {
    min-height: 0;
  }
}

/* ============================================================================
   PROCESS STEP CARDS (#our-ghee)
   ----------------------------------------------------------------------------
   Each card is a photograph (assets/process/) under a bottom caption gradient.
   Nothing else is drawn over the image except the small sparkle badge and the
   step number in the top corners -- the big line-art icon that used to sit in
   the middle was a stand-in for the missing photographs and is gone now.
   ========================================================================== */

/* Text sitting directly on a photograph (#our-process heading), with no scrim
   between them. A soft white halo lifts dark type off the busy pasture behind it
   -- the legibility a dark overlay panel would have given, without dimming the
   photograph itself. Two shadows: a tight one for the letterforms, a wider soft
   one to separate the whole block from the grass. */
.on-photo {
  text-shadow:
    0 1px 2px rgba(255, 252, 245, 0.95),
    0 2px 14px rgba(255, 252, 245, 0.75);
}

/* ----------------------------------------------------------------------------
   #our-process background fit
   ----------------------------------------------------------------------------
   The background is a designed illustration (a cow at bottom-left, the matka at
   bottom-right, village and ghee swirl along the top) at 1536x1024 -- a 3:2
   picture. A full-width section on a laptop is about 2.1:1, so background-size:
   cover has to throw away roughly 30% of the image's height to fill that width,
   and what it throws away is the bottom: the cow's legs and the base of the jar.

   All three of these cannot hold at once for a 3:2 image on a wide screen:
     (a) spans the full width,   (b) nothing cropped,   (c) fits in one screen.
   'contain' would satisfy (b) but shrinks the art to ~1350px wide, which tucks
   the cow and the matka behind the 1152px video card -- worse than a crop.

   ONE SCREEN IS THE REQUIREMENT, so (b) is what gives. At 1920x970 of content the
   image renders 1920x1280 and 310px of its height is lost. That is unavoidable
   until the artwork is re-cut to about 2:1 (2400x1200) -- at that ratio the loss
   drops to roughly 1% and this whole note can be deleted along with the
   background-position line below.

   Until then, WHERE the crop lands is controlled: background-position: center 90%
   sits the image low in its box, so ~90% of the overflow is taken off the TOP
   (sky, which nobody misses) and only ~10% off the bottom -- keeping the cow's
   legs and the base of the jar. Mind the direction: a percentage BELOW 50% trims
   more from the BOTTOM, which is exactly the wrong end. Higher is safer here.
   -------------------------------------------------------------------------- */

.process-screen {
  background-position: center 90%;
}


/* Section rule widths: a hairline at both ends.

   The bottom was 38px for a while, as a decorative band. It had to go: the marquee
   is the last row of this section's flex column and is meant to BE its bottom edge,
   but a border is painted outside the content box, so the 38px sat underneath the
   strip and showed 38px of the pasture background below it. The marquee ended up
   looking like it was floating above the section rather than closing it.

   If you want that band back, it cannot be a border on this element -- put it after
   the marquee as a real element inside the column, or move the marquee out of the
   section entirely so the band has somewhere to sit.

   Still scoped to .process-screen rather than written as `.border-y { ... }`:
   overriding the utility itself would work today -- #our-process is the only
   element on the page using border-y -- but it would silently re-shape every future
   use of that class, which is not what a utility is for. */
.process-screen {
  border-top-width: 1px;
  border-bottom-width: 1px;
}

/* Review slider (#testimonials): four equal-height cards per view.

   The equal height is the whole trick here. Slick sizes each slide to its own
   content, so a two-line quote sits in a short card next to a four-line one and
   the row looks broken. display:flex on the track makes every slide stretch to
   the tallest, and height:100% passes that down to the card itself -- which is
   why the markup has h-full on both the slide wrapper and the card, and why the
   card is a flex column with flex-1 on the quote: the quote absorbs the slack so
   every footer (avatar, name, town) lines up across the row. */
.review-slider .slick-track {
  display: flex !important;
}

.review-slider .slick-slide {
  height: auto;
}

.review-slider .slick-slide>div {
  height: 100%;
}

/* Dots: the same pill treatment the other sliders use, in gold rather than black. */
.review-dots ul.slick-dots {
  position: static;
  width: -moz-fit-content;
  width: fit-content;
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  list-style: none;
  margin: 0;
  padding: 0;
}

.review-dots ul.slick-dots li {
  width: auto;
  height: auto;
  margin: 0;
}

.review-dots ul.slick-dots li button {
  width: 8px;
  height: 8px;
  padding: 0;
  border-radius: 9999px;
  background: #E3D5B8;
  font-size: 0;
  line-height: 0;
  transition: background-color 0.3s, width 0.3s;
}

.review-dots ul.slick-dots li button:before {
  content: none;
}

.review-dots ul.slick-dots li.slick-active button {
  width: 20px;
  background: #A87C2A;
}

/* FAQ skin. The open/close mechanics live further up (.faq-panel grid-rows) -- these rules are
   only the look: a closed row is a quiet white card, and the open one lifts out of the stack with
   a gold border, a warmer fill and a soft shadow, so it is obvious which answer you are reading. */
.faq-item {
  transition: border-color 0.3s ease, background-color 0.3s ease, box-shadow 0.3s ease;
}

.faq-item:hover {
  border-color: rgba(168, 124, 42, 0.35);
}

.faq-item.is-open {
  border-color: rgba(220, 180, 90, 0.6);
  background: #FFFDF7;
  box-shadow: 0 14px 34px -24px rgba(74, 52, 12, 0.55);
}

/* The number is the quiet index of a closed row and the marker of the open one. */
.faq-num {
  color: #C9A24D;
  transition: color 0.3s ease;
}

.faq-item.is-open .faq-num {
  color: #A87C2A;
}

/* Hindi line under each question: readable but clearly secondary to the English above it. */
.faq-hi {
  color: #9A7530;
}

/* Plus turns to minus by fading the vertical stroke (see .faq-icon-vert above); the whole icon
   warms to gold as it opens. */
.faq-icon {
  color: #C9A24D;
  transition: color 0.3s ease, transform 0.3s ease;
}

.faq-item.is-open .faq-icon {
  color: #A87C2A;
  transform: rotate(180deg);
}

/* ============================================================================
   HERO ON MOBILE -- stacked, not overlaid
   ----------------------------------------------------------------------------
   On desktop the hero is a stack of full-bleed layers with the copy floating on
   top of the footage (see the architecture note above). That composition needs
   width: on a phone the copy sits directly over the speaker's face, so both the
   video and the words lose.

   Below lg the section becomes a plain flex column instead: the clip first, at
   its own 16:9, then the copy underneath on solid ink green. Nothing overlaps,
   so every grade, vignette and gradient that existed only to make overlaid text
   readable is switched off here -- they would just dim the footage for no reason.

   From lg up none of this applies and the original overlay design is untouched.
   ========================================================================== */
@media (max-width: 1023px) {

  /* MOBILE HERO -- the clip is a full-width band ABOVE the copy, not a background behind it.

     Requested shape: video on top, copy underneath, band running the full width, and the header
     floating over the video rather than sitting above it.

     THE RATIO MUST MATCH THE CLIP. It is 9/10 because hero.mp4 is 576x640 (0.9 wide-over-tall), so
     object-cover has nothing to crop and the whole frame is shown edge to edge. It was 9/16 while the
     clip was 576x1024; when the clip was rebuilt at 576x640 this number was left behind, so the band
     kept reserving the old height -- 177.78vw against 111vw, i.e. 693px instead of 433px on a 390px
     phone -- and object-cover then cropped the sides of the new clip to fill it. If you re-export the
     clip at a different shape, change this to match it.

     max-height: 100vh is a guard, not a style choice. Note the band is TALLER than the viewport width
     (height = width / 0.9 = 111vw), so it is 433px on a 390px phone and 853px on a 768px tablet. The
     cap only bites on wide-but-short viewports, and there object-cover crops the sides, which is the
     right thing to lose.

     NOTE the .hero prefix throughout: the element carries Tailwind's "absolute inset-y-0 right-0"
     utilities, a bare .hero-video-layer rule ties .absolute on specificity, and the Tailwind CDN
     injects its sheet AFTER this file -- so on a tie the utility wins and the layer would stay
     absolutely positioned. .hero .hero-video-layer outranks it. */
  .hero {
    /* Stacked, the content decides the height -- 100vh would leave a gap under the copy. */
    min-height: 0;
    display: flex;
    flex-direction: column;
    background-color: #0A1A0C;
  }

  /* The foliage still only ever existed as a ground for the video to fade into on desktop. */
  .hero .hero-still {
    display: none;
  }

  .hero .hero-video-layer {
    position: relative;
    inset: auto;
    width: 100%;
    aspect-ratio: 9 / 10;
    max-height: 100vh;
    /* First block in the column, so the band sits above the copy. The header is absolute at top:0
       with z-50, so it floats over this band -- which is what ::after below is for. */
    order: -1;
    /* The desktop rule promotes this layer (translateZ + will-change) so the fade mask runs on the
       GPU. There is no mask at this breakpoint, so the promotion buys nothing -- and a promoted
       element that is also a flex item composites unreliably. Drop it. */
    transform: none;
    will-change: auto;
  }

  /* Taken out of flow INSIDE the band, or the clip's intrinsic portrait height wins over the
     aspect-ratio above and stretches the parent again. */
  .hero .hero-video-layer video {
    position: absolute;
    inset: 0;
    height: 100%;
    width: 100%;
    object-fit: cover;
  }

  /* All three exist to keep overlaid text legible. Nothing is overlaid now. */
  .hero .hero-grade,
  .hero .hero-gradient,
  .hero .hero-topshade {
    display: none;
  }

  /* Utilities on this element are pt-36 / pb-16 / min-h-[inherit], all sized for copy floating over
     a full-screen hero. Stacked, min-h-[inherit] would inherit 0 and the top padding would just be
     a gap under the video. */
  .hero .hero-copy {
    min-height: 0;
    /* The seal/jar row above is a flex item now, so it reserves its own space and the copy only
       needs breathing room under it -- not clearance for an overlapping absolute element. */
    padding-top: 1rem;
    padding-bottom: 2.5rem;
    justify-content: flex-start;
  }

  /* The header floats over the top of the band, so the logo needs a shade to read against bright
     footage -- same job .hero-topshade does on desktop, which is switched off above. */
  .hero .hero-video-layer::after {
    content: '';
    position: absolute;
    inset: 0 0 auto 0;
    height: 6.5rem;
    background: linear-gradient(180deg, rgba(5, 12, 5, 0.55), transparent);
    pointer-events: none;
  }

  /* The sound button belongs to the video, so it follows the band -- but NOT to the top-right,
     where the header's hamburger sits. Bottom-right of the band instead.

     The offset repeats the band's own height maths: min(177.78vw, 100vh), i.e. 9:16 of the width
     capped at the viewport. Keep this in step with the rule above -- change the ratio or the cap
     there and this number has to move with it. */
  /* Seal + ghee jar on mobile. They were display:none here (the wrapper was "hidden lg:block"), so
     the two strongest brand images on the page never appeared on a phone at all.

     Stacked vertically as on desktop they would be ~260px tall and swallow the copy, so they run as
     a ROW instead, sitting BELOW the video band and above the copy.

     They used to overlap the footage: margin-top was -2.5rem, which pulled the row up so it straddled
     the seam, half on the video. It read as the seal and jar sitting on top of the speaker's face, so
     the row is now fully clear of the band -- the negative margin is a positive one.

     PLACED IN FLOW, NOT ABSOLUTELY. The first attempt pinned this with
     top: calc(min(177.78vw, 100vh) - 2.25rem), duplicating the band's own height maths. That works
     in a desktop devtools emulator and fails on a real phone: mobile browsers resize 100vh as the
     URL bar shows and hides, so the row detached from the band and floated in the black gap below
     it. Making it a flex item with order:-1 puts it directly after the band in the column, so it is
     anchored to whatever height the band ACTUALLY has, and the negative margin-top is the only
     number involved -- it pulls roughly half the row back up over the footage.

     order:-1 matches the video layer's, and among equal-order flex items the DOM order decides:
     the band is earlier in the markup, so it stays first and this lands between band and copy. */
  .hero .hero-decor {
    position: static;
    order: -1;
    align-self: center;
    /* Clear of the band, on the dark copy panel. */
    margin-top: 1.25rem;
    margin-bottom: 0;
    transform: none;
  }

  /* flex-end, NOT center, and this is the third attempt at it -- worth explaining so it does not get
     "tidied" back.

     align-items:center lines up the two BOUNDING BOXES, and their boxes measured level (both centres
     at 678px). It still read as misaligned, because the jar's box is not the jar: its top quarter is
     a thin spoon handle, so the heavy part of the artwork sits low in the box while the seal is a
     solid disc filling its own. Matching centres therefore puts the seal's mass ABOVE the jar's --
     which is exactly the "shield up, ghee down" it looked like.

     Aligning the bottom edges instead stands both on one ground line, and the spoon is simply
     allowed to rise above the badge, which is what it does in real life. Optical alignment beats
     geometric alignment whenever the artwork is not evenly distributed in its box. */
  .hero .hero-decor .hero-floats {
    flex-direction: row;
    align-items: flex-end;
    gap: 0.85rem;
  }

  .hero .hero-decor .hero-seal-box {
    height: 4.5rem;
    width: 4.5rem;
  }

  /* Sized by HEIGHT, not width: the seal is a circle and the jar a 0.9:1 portrait, so equal widths
     would give them very different heights. 5rem against the seal's 4.5rem leaves the spoon about
     8px proud of the badge -- enough to read as deliberate, not as a misalignment.

     Height sizing only works because the PNG is now trimmed to its artwork. It used to carry 153px
     of transparent padding on its left edge against 3px on its right, so centring the BOX left the
     visible jar well right of centre with a dead gap beside the seal. */
  .hero .hero-decor .hero-ghee {
    height: 5rem;
    width: auto;
  }

  /* The sunburst is 250% of the seal box. At 4.5rem that is a 405px glow around a 72px badge, which
     washes out the footage behind the whole row. It is a desktop flourish; drop it here. */
  .hero .hero-decor .hero-sun {
    display: none;
  }
}

/* ---- Header contact controls -------------------------------------------------
   The number used to be hidden inside an "Order Now" button that simply dialled it.
   For a dairy that takes its orders over the phone, the digits themselves are the
   more useful call to action, so they now sit on the surface of the header.

   Both controls point at the same line (+91 97626 78386): one dials it, one opens
   WhatsApp. If the line ever moves, it appears once per link in index.html.

   "Highlighted" here is done with a gold ring and a green halo rather than solid
   fills -- the header is transparent over the hero video, and two heavy blocks of
   colour would sit on the footage like stickers. */
.hdr-call {
  background: rgba(var(--hero-ink), 0.55);
  border: 1px solid rgba(220, 180, 90, 0.55);
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
  transition: border-color .25s ease, box-shadow .25s ease, transform .25s ease;
}

.hdr-call:hover {
  border-color: rgba(220, 180, 90, 0.95);
  box-shadow: 0 6px 22px rgba(220, 180, 90, 0.28);
  transform: translateY(-1px);
}

/* The disc the phone glyph sits in. The glyph is WHITE, so the disc is the deeper end of the gold
   ramp rather than the bright end -- white on #DCB45A is only about 1.9:1 and the phone shape
   disappears into it, while against #A87C2E it holds up. Keep that relationship if you retint this:
   brighten the disc and you have to darken the glyph again. */
.hdr-call-icon {
  background: linear-gradient(140deg, #B98F3C, #A87C2E);
  color: #fff;
}

.hdr-wa {
  position: relative;
  background: linear-gradient(140deg, #25D366, #12A150);
  color: #fff;
  box-shadow: 0 6px 20px rgba(37, 211, 102, 0.35);
  transition: box-shadow .25s ease, transform .25s ease;
}

.hdr-wa:hover {
  box-shadow: 0 8px 26px rgba(37, 211, 102, 0.55);
  transform: translateY(-1px);
}

/* One slow ring, so the eye finds WhatsApp without the header turning into an
   advert. Decorative only: it never takes the pointer, and it is the first thing
   dropped for anyone who asked for reduced motion. */
.hdr-wa::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: 9999px;
  border: 2px solid rgba(37, 211, 102, 0.6);
  animation: hdr-wa-pulse 2.6s ease-out infinite;
  pointer-events: none;
}

@keyframes hdr-wa-pulse {
  0%   { opacity: .7; transform: scale(1); }
  70%  { opacity: 0;  transform: scale(1.28); }
  100% { opacity: 0;  transform: scale(1.28); }
}

@media (prefers-reduced-motion: reduce) {
  .hdr-wa::after { animation: none; opacity: 0; }
  .hdr-call:hover,
  .hdr-wa:hover { transform: none; }
}

/* Ghee jar under the hero seal. The gold rim that used to be here is gone on request, and so is the
   circular crop -- the artwork is now a transparent-background product PNG, which a round clip was
   slicing through (spoon, label, jar base). It stands on its own silhouette instead.

   drop-shadow, NOT box-shadow. box-shadow traces the element's BOX, so on a transparent PNG it
   paints a hard rectangle in mid-air around the jar. The filter follows the alpha channel, so the
   shadow hugs the glass. This is the one line that must not be "simplified" back to box-shadow.

   Keep some shadow. It is all that separates the jar from the video playing behind it; flat and
   unshadowed, it stops looking placed and starts looking pasted on. */
.hero-ghee {
  filter: drop-shadow(0 14px 26px rgba(0, 0, 0, 0.45));
  margin-left:40px;
}

/* ---- Hero launch offer -------------------------------------------------------
   Glass card over the video, same construction as .hero-glass but with the gold border turned up,
   because this one is meant to be picked out rather than blend in. */
.offer-card {
  background: rgba(var(--hero-ink), 0.62);
  border: 1px solid rgba(220, 180, 90, 0.45);
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
}

/* Orange, not gold. Everything around it in the hero is gold, so a gold discount chip would sink
   into the card it is sitting on -- this is the one element that should not harmonise. */
.offer-badge {
  background: linear-gradient(140deg, #FF7A2F, #E5431B);
  color: #fff;
  box-shadow: 0 4px 14px rgba(255, 90, 31, 0.35);
}

.offer-track {
  height: 6px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.14);
  overflow: hidden;
}

/* Width is set from data-claimed in script.js, never in the markup -- keeping it out of the HTML is
   what stops the bar and the printed numbers from disagreeing after someone edits one of them. */
.offer-fill {
  display: block;
  height: 100%;
  width: 0;
  border-radius: inherit;
  background: linear-gradient(90deg, #DCB45A, #FF7A2F);
  transition: width .6s ease;
}

/* All claimed: the bar goes flat gold and the badge stops shouting, so the card reads as closed
   rather than as an offer you can still take. */
.offer-card[data-soldout] .offer-fill {
  background: #DCB45A;
}

.offer-card[data-soldout] .offer-badge {
  background: rgba(255, 255, 255, 0.14);
  box-shadow: none;
}

@media (prefers-reduced-motion: reduce) {
  .offer-fill { transition: none; }
}

/* ---- Illustrated section backgrounds on narrow screens -----------------------
   services-bg.jpg and pasture-bg.jpg are NOT textures. They are framed illustrations, ~1.74:1, whose
   entire content sits around the edges -- tree, cows, farm shed, the branded Mahadev Dairy pots --
   around a deliberately blank cream middle for the copy to sit on.

   `cover` therefore destroys them on a phone. Measured: a 390px-wide section 1800px tall renders the
   image 3131px wide and shows the middle 12.5% of it, which is exactly the blank part. Every piece
   of artwork is off-screen, and a 1654px source is being upscaled to 3131px to achieve it. The
   section ends up a blurry cream wash.

   So below lg the image is fitted to the WIDTH and pinned to the bottom edge, where the cows and the
   branded pots are. The whole illustration is visible, at 1:1 or better, as a band along the foot of
   the section. background-color carries the rest -- sampled from each image's own middle, not
   guessed, so there is no seam where the band ends.

   NO extra bottom padding. That was tried and it was wrong: reserving the band's full ~57.5vw height
   below the content turned the illustration into a detached strip sitting AFTER the section, before
   the next one began -- which is exactly the "background showing after the section" fault this was
   meant to cure. The band is allowed to sit BEHIND the content instead. That works because the
   artwork hugs the lower corners (cows left, ghee pot right) while the middle of the sheet is blank,
   and each section's existing bottom padding -- py-24 on #our-ghee, py-16 inside #faq -- is enough
   for those corners to clear the last card and read as a footer to the section.

   EVERY selector here must be an ID. Tailwind's bg-cover is a class (0,1,0), and the CDN build
   injects its <style> AFTER this file is linked -- so a class selector of ours ties on specificity
   and then LOSES on order. That is not theoretical: this block first used .process-screen and it
   silently did nothing, while the #our-ghee and #faq rules beside it worked. Verified at a 400px
   viewport before and after.

   #team is deliberately absent even though that section also uses services-bg.jpg: it lives inside
   <template id="team-section-hidden">, so it is inert and never renders. Move it out of the
   template and it needs adding here. */
@media (max-width: 1023px) {

  /* THIRD ATTEMPT, and the first one that looks right. Read the two failures above before changing
     it back.

     Fitting the sheet to the width and pinning it to the bottom (background-size: 100% auto;
     background-position: center bottom) was better than cover, but it still failed on a phone. The
     band is 224px tall at 390px wide, and these two sections are long -- #faq is 1280px with eight
     cards -- so the content covers all of the band except the last ~60px. What actually rendered was
     a chopped horizontal slice of the illustration below the final card: the tops of the cows on the
     left, the top of the ghee pot on the right, both cut through the middle. It read as a stray strip
     pasted onto the end of the section, which is the fault this rule was meant to cure.

     So on mobile these two sections drop the illustration and keep only the cream sampled from its
     middle. Nothing is lost: `cover` was already showing that blank middle and nothing else, so the
     colour IS what the artwork contributed here. The sections keep their warm tone, the strip is
     gone, and a 1654px JPEG is no longer downloaded on a phone to be hidden behind cards.

     The full illustration still does its job from lg up, where the section is wide enough for the
     artwork in the corners to sit beside the content instead of under it.

     #our-process keeps its image below -- its bottom edge is the marquee, a solid dark band, so no
     slice of artwork is exposed there. */
  #our-ghee,
  #faq {
    background-image: none;
    background-color: #FAF5F0;
  }

  /* Same treatment, warmer cream -- pasture-bg.jpg's own middle is #FDF3E7, not #FAF5F0.

     This one was left with its illustration at first, on the reasoning that the marquee closes the
     section so no slice of artwork could be exposed. That was wrong. The band is 219px tall at 390px
     wide and the marquee is only 52px of it, so the remaining ~167px rode up BEHIND the video card:
     grass and cows appeared either side of the thumbnail and a cut strip ran across just above the
     marquee. Same fault as the two sections above, just hidden in a different place. */
  #our-process {
    background-image: none;
    background-color: #FDF3E7;
  }

  /* #contact, same fault and same cure. Its sheet is pasture-bg1.webp on a full-bleed child div
     rather than on the section, so this needs the class hook -- see the note in index.html. The
     section is 1191px tall on a phone against a 224px band, so all that showed under the form was
     the usual cut strip: cows bottom-left, ghee pot bottom-right, both sliced.

     The cream is left to the element's own bg-[#FBF3E2] utility, which is already sampled from this
     sheet's middle, so there is nothing to restate here. #contact .contact-bg is (1,1,0) and beats
     the bg-[url(...)] utility whatever the stylesheet order turns out to be. */
  #contact .contact-bg {
    background-image: none;
  }
}
