/* ==========================================================================
   KHEDUT BAZAR PRIVATE LIMITED — Website stylesheet
   Loaded after Bootstrap, so everything here is an intentional override.

   TABLE OF CONTENTS
     01. DESIGN TOKENS (CSS variables)
     02. BASE / RESET
     03. SHARED UI — titles, eyebrows, buttons, decorations
     04. PHONE MOCKUP (pure CSS, used by hero + app showcase)
     05. FLOATING NAVBAR
     06. HERO
     07. ABOUT COMPANY
     08. OUR PLATFORM
     09. KEY FEATURES
     10. HOW IT WORKS
     11. AUDIENCE (farmers + buyers)
     12. WHY KHEDUT BAZAR (sticky scroll)
     13. APP SHOWCASE
     14. VISION + COMPANY INFORMATION
     15. CONTACT US
     16. CLOSING (final CTA + footer)
     17. SCROLL ANIMATION STATES
     18. RESPONSIVE
   ========================================================================== */


/* ==========================================================================
   01. DESIGN TOKENS
   Every colour, radius, shadow and spacing value used on the site is
   declared once here so the whole theme can be re-skinned from one place.
   ========================================================================== */
:root{

  /* --- Brand colours ------------------------------------------------ */
  --kb-primary:        #305711;   /* client-specified primary green */
  --kb-primary-dark:   #1F3A09;   /* deeper shade for gradients / footer */
  --kb-primary-darker: #142706;   /* deepest shade, footer bottom */
  --kb-primary-light:  #4C8520;   /* lighter shade for hovers */
  --kb-primary-soft:   #7FB03C;   /* soft accent */
  --kb-accent:         #8DC63F;   /* lime accent from the logo */

  /* --- Neutrals ----------------------------------------------------- */
  --kb-cream:   #F8FBF4;          /* page background */
  --kb-mint:    #EDF5E2;          /* tinted section background */
  --kb-white:   #FFFFFF;
  --kb-ink:     #16240F;          /* headings */
  --kb-body:    #54624B;          /* body copy */
  --kb-muted:   #83907B;          /* captions, labels */
  --kb-line:    #E0EBD4;          /* hairlines and card borders */

  /* --- On-dark colours ---------------------------------------------- */
  --kb-on-dark:       #FFFFFF;
  --kb-on-dark-soft:  rgba(255,255,255,.78);
  --kb-on-dark-line:  rgba(255,255,255,.16);

  /* --- Typography ---------------------------------------------------- */
  --kb-font: "Hind Vadodara", system-ui, -apple-system, "Segoe UI", sans-serif;
  --kb-fs-h1: clamp(2.1rem, 1.2rem + 2.8vw, 3.9rem);
  --kb-fs-h2: clamp(1.75rem, 1.1rem + 2vw, 2.9rem);
  --kb-fs-h3: clamp(1.15rem, 1rem + .5vw, 1.45rem);
  --kb-fs-lead: clamp(1rem, .95rem + .25vw, 1.15rem);
  --kb-lh-tight: 1.25;
  --kb-lh-body: 1.8;

  /* --- Radii --------------------------------------------------------- */
  --kb-r-sm:  12px;
  --kb-r-md:  20px;
  --kb-r-lg:  28px;
  --kb-r-xl:  38px;
  --kb-r-pill: 999px;

  /* --- Shadows ------------------------------------------------------- */
  --kb-shadow-sm:  0 4px 16px rgba(22,36,15,.06);
  --kb-shadow-md:  0 14px 40px rgba(22,36,15,.10);
  --kb-shadow-lg:  0 30px 80px rgba(22,36,15,.16);
  --kb-shadow-nav: 0 10px 40px rgba(22,36,15,.14);

  /* --- Layout -------------------------------------------------------- */
  /* The pill is driven by this ONE value, not by a hard height on
     `.kb-nav__shell` — hero padding-top, sticky offsets and
     `scroll-padding-top` all calc against it, so changing the number here
     keeps every anchor landing in the right place automatically. */
  --kb-nav-h: 65px;               /* height of the floating navbar shell */
  --kb-nav-gap: 18px;             /* gap between navbar and viewport top */
  --kb-section-y: clamp(4rem, 2rem + 6vw, 7.5rem);  /* vertical rhythm */

  /* --- Motion -------------------------------------------------------- */
  --kb-ease: cubic-bezier(.22,.61,.36,1);
  --kb-t-fast: .18s var(--kb-ease);
  --kb-t-base: .32s var(--kb-ease);
  --kb-t-slow: .6s  var(--kb-ease);
}


/* ==========================================================================
   02. BASE / RESET
   ========================================================================== */
*,
*::before,
*::after{ box-sizing:border-box; }

html{
  scroll-behavior:smooth;
  /* keep anchored sections clear of the floating navbar */
  scroll-padding-top:calc(var(--kb-nav-h) + var(--kb-nav-gap) + 20px);
}

body{
  margin:0;
  font-family:var(--kb-font);
  font-size:1rem;
  line-height:var(--kb-lh-body);
  color:var(--kb-body);
  background:var(--kb-cream);
  -webkit-font-smoothing:antialiased;
  /* Floating decorations may hang off the right edge; clip them horizontally.
     `overflow-x:hidden` is the fallback, but on <body> it turns the body into
     a scroll container and that silently kills every `position:sticky`
     descendant (the Why section). `overflow-x:clip` clips without creating a
     scroll container, so sticky keeps working. Older browsers that do not
     understand `clip` simply ignore the second declaration. */
  overflow-x:hidden;
  overflow-x:clip;
}

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

a{ text-decoration:none; color:inherit; }

h1,h2,h3,h4,h5,h6{
  font-family:var(--kb-font);
  color:var(--kb-ink);
  font-weight:700;
  line-height:var(--kb-lh-tight);
  margin:0;
}

p{ margin:0; }
ul,ol,dl,dd{ margin:0; padding:0; list-style:none; }

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

/* Visible focus ring for keyboard users only */
:focus-visible{
  outline:3px solid var(--kb-primary-soft);
  outline-offset:3px;
  border-radius:6px;
}

/* Skip link */
.kb-skip{
  position:absolute; top:10px; left:10px; z-index:2000;
  background:var(--kb-primary); color:#fff;
  padding:.6rem 1.1rem; border-radius:var(--kb-r-pill);
}

/* Generic vertical rhythm for every section */
.kb-section{
  position:relative;
  padding-block:var(--kb-section-y);
  /* Keeps floating decorations inside the section.
     `clip` is preferred over `hidden` for the same reason as on <body>:
     `hidden` makes the section a scroll container, which disables
     `position:sticky` for anything inside it (see .why__sticky).
     `hidden` stays first as the fallback for very old browsers.          */
  overflow:hidden;
  overflow:clip;
}

/* Modifier: trims the TOP half of the rhythm only.
   Used by any section that already inherits breathing room from whatever
   sits above it — e.g. .about, which follows the hero's tall ribbon
   reserve, so the full --kb-section-y on top read as dead space.
   It is a separate class rather than an edit to .kb-section because that
   base rhythm is shared by every section on the page. */
.kb-section--tight-top{
  /* Still well under the full --kb-section-y rhythm, but no longer so tight
     that the eyebrow looks glued to the divider above it. */
  padding-top:clamp(2.75rem, 1.4rem + 3vw, 4.75rem);
}

/* Bootstrap container tuning */
.container{ max-width:1240px; }


/* ==========================================================================
   03. SHARED UI
   ========================================================================== */

/* --- Eyebrow (small label above a title) ------------------------------ */
.kb-eyebrow{
  display:inline-block;
  font-size:.78rem;
  font-weight:600;
  letter-spacing:.16em;
  text-transform:uppercase;
  color:var(--kb-primary);
  /* Tinted with the PRIMARY green rather than --kb-mint. The mint fill was
     the same family as the cream/mint section backgrounds it sits on, so on
     "Why Khedut Bazar" and "Contact Us" the chip disappeared entirely. A
     low-alpha primary tint reads against cream, mint AND white alike. */
  background:rgba(48,87,17,.10);
  border:1px solid rgba(48,87,17,.24);
  padding:.35rem 1rem;
  border-radius:var(--kb-r-pill);
  margin-bottom:1.1rem;
}
/* Same idea inverted for chips sitting on the dark green sections — .12 was
   too faint to register as a pill at all. */
.kb-eyebrow--light{
  color:#fff;
  background:rgba(255,255,255,.18);
  border-color:rgba(255,255,255,.34);
}

/* --- Titles ----------------------------------------------------------- */
.kb-title{
  font-size:var(--kb-fs-h2);
  font-weight:700;
  letter-spacing:-.01em;
}
.kb-title--light{ color:var(--kb-on-dark); }

/* Highlighted words inside a title */
.kb-hl{
  color:var(--kb-primary);
  position:relative;
  white-space:nowrap;
}
.kb-hl--light{ color:var(--kb-accent); }

/* --- Section head block ----------------------------------------------- */
.kb-section-head{ margin-bottom:clamp(2.2rem,1.4rem + 2vw,3.6rem); }
.kb-section-head--center{ text-align:center; max-width:820px; margin-inline:auto; }

/* SPLIT header — copy left-aligned, a single call-to-action sitting opposite
   it on the same baseline. Used where the section's cards should NOT each
   repeat the same button; the action is hoisted up here once instead. */
.kb-section-head--split{
  display:flex;
  flex-wrap:wrap;
  align-items:center;
  justify-content:space-between;
  gap:1.5rem 2rem;
  text-align:left;
}
.kb-section-head--split .kb-section-head__copy{
  /* Lets the copy shrink before the button does, and gives the pair a sane
     wrap point on narrower desktops instead of a one-word-per-line title. */
  flex:1 1 28rem;
  min-width:0;
}
.kb-section-head--split .kb-title{ margin-bottom:0; }
.kb-section-head__cta{ flex:0 0 auto; }

.kb-section-sub{
  margin-top:1.1rem;
  font-size:var(--kb-fs-lead);
  color:var(--kb-body);
}
.kb-section-sub--light{ color:var(--kb-on-dark-soft); }

/* --- Buttons ---------------------------------------------------------- */
.kb-btn{
  --_bg:      var(--kb-primary);
  --_fg:      #fff;
  --_border:  var(--kb-primary);
  --_bg-h:    var(--kb-primary-light);
  --_fg-h:    #fff;
  --_border-h:var(--kb-primary-light);

  display:inline-flex;
  align-items:center;
  justify-content:center;
  gap:.5rem;
  padding:.78rem 1.7rem;
  font-size:.98rem;
  font-weight:600;
  line-height:1.3;
  text-align:center;
  border-radius:var(--kb-r-pill);
  border:2px solid var(--_border);
  background:var(--_bg);
  color:var(--_fg);
  cursor:pointer;
  transition:background var(--kb-t-base), color var(--kb-t-base),
             border-color var(--kb-t-base), transform var(--kb-t-fast),
             box-shadow var(--kb-t-base);
}
.kb-btn:hover{
  background:var(--_bg-h);
  color:var(--_fg-h);
  border-color:var(--_border-h);
  transform:translateY(-2px);
  box-shadow:var(--kb-shadow-md);
}
.kb-btn:active{ transform:translateY(0); }

/* Solid green — the primary action */
.kb-btn--primary{
  --_bg:var(--kb-primary);      --_fg:#fff;  --_border:var(--kb-primary);
  --_bg-h:var(--kb-primary-light); --_fg-h:#fff; --_border-h:var(--kb-primary-light);
  box-shadow:0 8px 24px rgba(48,87,17,.22);
}

/* Outlined — the secondary action on light backgrounds.
   The fill is a FROSTED WHITE, not `transparent`. In the hero this button
   sits straight on the field photograph, and a transparent fill left the
   green label fighting the green crops behind it — the button effectively
   vanished. The translucent plate + blur keeps it legible over artwork
   while still reading as the quieter, outlined sibling of --primary. */
.kb-btn--outline{
  --_bg:rgba(255,255,255,.86);  --_fg:var(--kb-primary); --_border:var(--kb-primary);
  --_bg-h:var(--kb-primary);    --_fg-h:#fff;            --_border-h:var(--kb-primary);
  -webkit-backdrop-filter:blur(6px);
          backdrop-filter:blur(6px);
  box-shadow:0 6px 18px rgba(48,87,17,.12);
}

/* Tinted — quiet tertiary action */
.kb-btn--soft{
  --_bg:var(--kb-mint);         --_fg:var(--kb-primary); --_border:var(--kb-line);
  --_bg-h:var(--kb-primary);    --_fg-h:#fff;            --_border-h:var(--kb-primary);
}

/* White — for use on dark green backgrounds */
.kb-btn--light{
  --_bg:#fff;                   --_fg:var(--kb-primary); --_border:#fff;
  --_bg-h:var(--kb-accent);     --_fg-h:var(--kb-primary-dark); --_border-h:var(--kb-accent);
}

.kb-btn--lg{ padding:1rem 2.1rem; font-size:1.04rem; }

.kb-btn-row{
  display:flex;
  flex-wrap:wrap;
  gap:.9rem;
  margin-top:1.8rem;
}

/* --- Floating decorative assets --------------------------------------- */
.kb-deco{
  position:absolute;
  z-index:0;
  pointer-events:none;
  user-select:none;
  opacity:.55;
  will-change:transform;

  /* Mirror switch. A decoration sets `--kb-deco-flip:-1` to face the other
     way; every float keyframe multiplies scaleX by it, so the mirroring and
     the animation can coexist on the same `transform` property (a separate
     `transform:scaleX(-1)` rule would simply be overwritten by the
     animation). Default 1 = not mirrored. */
  --kb-deco-flip:1;
}
/* three gentle float rhythms so the leaves never move in lockstep */
[data-float="1"]{ animation:kb-float-a 9s  ease-in-out infinite; }
[data-float="2"]{ animation:kb-float-b 11s ease-in-out infinite; }
[data-float="3"]{ animation:kb-float-c 13s ease-in-out infinite; }

/* Static fallback so a mirrored leaf still faces the right way when the
   animation is suppressed (reduced motion) or has not started yet. */
.kb-deco{ transform:scaleX(var(--kb-deco-flip)); }

@keyframes kb-float-a{
  0%,100%{ transform:translate3d(0,0,0)      rotate(0deg) scaleX(var(--kb-deco-flip)); }
  50%    { transform:translate3d(0,-22px,0)  rotate(5deg) scaleX(var(--kb-deco-flip)); }
}
@keyframes kb-float-b{
  0%,100%{ transform:translate3d(0,0,0)        rotate(0deg)  scaleX(var(--kb-deco-flip)); }
  50%    { transform:translate3d(-16px,16px,0) rotate(-6deg) scaleX(var(--kb-deco-flip)); }
}
@keyframes kb-float-c{
  0%,100%{ transform:translate3d(0,0,0)        rotate(0deg) scaleX(var(--kb-deco-flip)); }
  50%    { transform:translate3d(14px,-18px,0) rotate(8deg) scaleX(var(--kb-deco-flip)); }
}

/* --- Reusable soft blob behind imagery -------------------------------- */
.about__blob,
.why__blob{
  position:absolute;
  inset:8% 6%;
  border-radius:48% 52% 56% 44% / 46% 42% 58% 54%;
  background:radial-gradient(circle at 35% 30%, var(--kb-accent) 0%, var(--kb-primary) 70%);
  opacity:.16;
  filter:blur(6px);
  z-index:0;
}


/* ==========================================================================
   04. PHONE MOCKUP
   Pure-CSS recreation of the reference mockup: brushed metal rail,
   dynamic island, deep soft shadow. Used in the hero and app showcase.
   ========================================================================== */
/* Corner radius lives in a token because the same phone component is used at
   two very different sizes: large in the hero, small in the app showcase.
   A single hard-coded 40px made the little showcase phones look like rounded
   blobs, so each context dials it down (see .appshow__phone). */
.kb-phone{ --kb-phone-r:28px; position:relative; }

/* SIDE BUTTONS.
   Two pseudo-elements on the wrapper — a volume rocker on the left rail and a
   power key on the right — are what tip the mockup over from "screenshot in a
   rounded box" into "photo of a handset". They live on .kb-phone rather than
   on .kb-phone__frame because the frame clips its own overflow for the screen
   corners, which would swallow anything hanging off the edge. The wrapper is
   shrink-to-fit in every context it is used in, so its box is exactly the
   frame's box and the rails land on the real edges. They also inherit the
   hero's rotateY, so they turn with the device. */
.kb-phone::before,
.kb-phone::after{
  content:"";
  position:absolute;
  width:3px;
  border-radius:3px;
  /* Darker at the ends, lit in the middle — reads as a machined metal key */
  background:linear-gradient(180deg,#5c5f66 0%,#9aa0a9 28%,#9aa0a9 72%,#5c5f66 100%);
  box-shadow:0 1px 2px rgba(0,0,0,.35);
  z-index:0;
}
/* Volume rocker: longer, sits higher */
.kb-phone::before{ left:-2px;  top:23%; height:13%; }
/* Power key: shorter, sits a little lower — mirrors real hardware layout */
.kb-phone::after{  right:-2px; top:31%; height:9%; }

.kb-phone__frame{
  position:relative;
  aspect-ratio:9 / 19.5;
  /* Bezel as a PERCENTAGE of the frame width, not a fixed 9px. A flat 9px was
     a believable bezel on the 270px hero phones but a fat plastic border on
     the small showcase ones; modern handsets are nearly all screen, so ~2.2%
     keeps the proportion right at every size. */
  padding:2.2%;
  border-radius:var(--kb-phone-r);
  /* Dark graphite body. The old bright chrome gradient looked like a chunk of
     polished steel; real devices are dark with a thin lit rim, which is what
     the inset highlights below provide. */
  background:
    linear-gradient(145deg,#4a4e55 0%,#23262b 16%,#15171a 46%,
                    #2b2e34 62%, #16181b 84%, #41454c 100%);
  box-shadow:
    0 0 0 1px rgba(255,255,255,.20) inset,
    0 1px 1px rgba(255,255,255,.45) inset,
    0 -1px 2px rgba(0,0,0,.55) inset,
    0 34px 70px rgba(14,24,8,.34),
    0 8px 20px rgba(14,24,8,.18);
  overflow:hidden;
  z-index:1;
}
.kb-phone__frame img{
  width:100%;
  height:100%;
  object-fit:cover;
  object-position:top center;
  /* Screen radius tracks the frame radius minus the bezel */
  border-radius:calc(var(--kb-phone-r) - 6px);
  background:#0d0f0b;
  display:block;
}
/* Glass sheen. A single soft diagonal band across the display — the one cue
   that says "this surface is glass" rather than a flat image. Kept very low
   contrast so it never fights the UI screenshot underneath. */
.kb-phone__frame::after{
  content:"";
  position:absolute;
  inset:0;
  border-radius:var(--kb-phone-r);
  pointer-events:none;
  z-index:3;
  background:linear-gradient(
    118deg,
    rgba(255,255,255,0)    38%,
    rgba(255,255,255,.085) 46%,
    rgba(255,255,255,.14)  50%,
    rgba(255,255,255,.04)  56%,
    rgba(255,255,255,0)    64%
  );
}
/* Dynamic island */
.kb-phone__island{
  position:absolute;
  /* Percentages of the frame, not fixed px, so the island stays in scale on
     the small showcase phones as well as the large hero ones. */
  top:2.2%; left:50%;
  transform:translateX(-50%);
  width:27%; height:3.1%;
  background:#07080a;
  /* Faint rim so the island separates from a dark app bar behind it */
  box-shadow:0 0 0 1px rgba(255,255,255,.08);
  border-radius:var(--kb-r-pill);
  z-index:4;
}


/* ==========================================================================
   05. FLOATING NAVBAR
   A pill that floats over the page with a sliding indicator behind the
   active link. Reference behaviour: bedimcode/responsive-navbar-interaction
   ========================================================================== */
.kb-nav{
  position:fixed;
  inset:var(--kb-nav-gap) 0 auto 0;
  z-index:1000;
  padding-inline:1rem;
  pointer-events:none;         /* only the shell itself is interactive */
}

.kb-nav__shell{
  pointer-events:auto;
  max-width:1240px;
  margin-inline:auto;
  height:var(--kb-nav-h);
  display:flex;
  align-items:center;
  gap:1rem;
  padding:0 .85rem 0 .35rem;
  background:rgba(255,255,255,.82);
  backdrop-filter:blur(18px) saturate(150%);
  -webkit-backdrop-filter:blur(18px) saturate(150%);
  border:1px solid rgba(255,255,255,.7);
  border-radius:var(--kb-r-pill);
  box-shadow:var(--kb-shadow-nav);
  transition:background var(--kb-t-base), box-shadow var(--kb-t-base),
             height var(--kb-t-base);
}
/* Shrinks slightly and becomes more opaque once the page is scrolled */
.kb-nav.is-scrolled .kb-nav__shell{
  background:rgba(255,255,255,.94);
  box-shadow:0 14px 44px rgba(22,36,15,.18);
}

.kb-nav__brand{ display:flex; align-items:center; flex:0 0 auto; }
/* The logo lock-up carries the Gujarati wordmark under the roundel, so it
   needs real size to stay legible — 40px rendered the tagline as mush.
   Height is capped against --kb-nav-h so it can never outgrow the pill. */
.kb-nav__brand img{ height:min(58px, calc(var(--kb-nav-h) - 10px)); width:auto; }

/* --- Link row with sliding indicator ---------------------------------- */
.kb-nav__menu{
  position:relative;
  margin-left:auto;
  display:flex;
  align-items:center;
}
.kb-nav__list{
  display:flex;
  align-items:center;
  gap:.15rem;
  position:relative;
  z-index:1;
}
.kb-nav__link{
  display:block;
  padding:.5rem .95rem;
  font-size:.92rem;
  font-weight:600;
  color:var(--kb-body);
  border-radius:var(--kb-r-pill);
  white-space:nowrap;
  transition:color var(--kb-t-base);
}
.kb-nav__link:hover{ color:var(--kb-primary); }

/* The sliding pill is a single element, so exactly ONE link may wear the
   "on top of the pill" white at any moment.
   - `.is-active`  = the section currently in view (default resting state)
   - `.is-peek`    = the link the pill is parked on while hovering
   - `.has-peek`   = set on the list for as long as a hover preview is running
   Without the `.has-peek` rule the active link would keep its white text out
   on the cream bar (invisible) while the hovered link kept dark text on the
   dark-green pill (also invisible) — that was the reported bug. */
.kb-nav__link.is-active,
.kb-nav__link.is-peek{ color:#fff; }
.kb-nav__list.has-peek .kb-nav__link.is-active:not(.is-peek){
  color:var(--kb-body);
}
/* `:hover` must not fight `.is-peek` for the link under the pill */
.kb-nav__link.is-peek:hover{ color:#fff; }

/* The pill that slides behind the active link */
.kb-nav__indicator{
  position:absolute;
  top:50%;
  left:0;
  height:38px;
  width:0;
  transform:translateY(-50%);
  background:var(--kb-primary);
  border-radius:var(--kb-r-pill);
  box-shadow:0 6px 18px rgba(48,87,17,.3);
  transition:transform var(--kb-t-base), width var(--kb-t-base), opacity var(--kb-t-fast);
  opacity:0;
  z-index:0;
}
.kb-nav__indicator.is-ready{ opacity:1; }

.kb-nav__cta{ flex:0 0 auto; padding:.62rem 1.3rem; font-size:.9rem; }
.kb-nav__cta-mobile{ display:none; }

/* --- Hamburger -------------------------------------------------------- */
.kb-nav__toggle{
  display:none;
  flex-direction:column;
  justify-content:center;
  gap:5px;
  width:44px; height:44px;
  padding:0 10px;
  margin-left:auto;
  background:var(--kb-mint);
  border:1px solid var(--kb-line);
  border-radius:var(--kb-r-pill);
  cursor:pointer;
}
.kb-nav__toggle span{
  display:block;
  height:2px;
  width:100%;
  background:var(--kb-primary);
  border-radius:2px;
  transition:transform var(--kb-t-base), opacity var(--kb-t-fast);
}
.kb-nav__toggle[aria-expanded="true"] span:nth-child(1){ transform:translateY(7px) rotate(45deg); }
.kb-nav__toggle[aria-expanded="true"] span:nth-child(2){ opacity:0; }
.kb-nav__toggle[aria-expanded="true"] span:nth-child(3){ transform:translateY(-7px) rotate(-45deg); }


/* ==========================================================================
   06. HERO
   ========================================================================== */
.hero{
  position:relative;

  /* Full-viewport hero.
     `min-height` (not `height`) on purpose: the hero should FILL the screen
     when there is room, but must be allowed to grow past it when there is
     not — short laptop viewports, 150% OS zoom, or the long Gujarati
     headline wrapping to an extra line. With a hard `height` that content
     would simply spill over the ribbon.
     `svh` = small viewport height, so mobile browsers measure against the
     state where their URL bar is VISIBLE and nothing gets clipped on load;
     the `vh` line above it is the fallback for engines without svh.
     The paddings below stay exactly as they were — they are the part that
     keeps the layout correct whenever 100vh is not enough, and the flex
     centring then distributes any leftover space evenly instead of
     stacking everything at the top of a tall screen. */
  min-height:100vh;
  min-height:100svh;
  display:flex;
  flex-direction:column;
  justify-content:center;

  padding-top:calc(var(--kb-nav-h) + var(--kb-nav-gap) + clamp(2.5rem,1rem + 5vw,5rem));
  /* Extra bottom room so the .hero__line ribbon overlays empty background
     instead of sitting on top of the copy / mockup.
     The reserve is a PURE vw value, deliberately NOT a clamp. The ribbon is
     a full-bleed image, so its visible band is always a fixed percentage of
     the viewport width tall — it grows and shrinks with the screen. A clamp
     stopped tracking it past its min/max, which is why the ribbon sat flush
     at some widths and floated clear of the edge at others. Matching the
     reserve to the ribbon's own ratio keeps the join identical everywhere.
     line-divider-2.png is shifted down 35.5% (see .hero__line), so the band
     that actually needs clearing is rows 83-300 of a 2008px-wide PNG — the
     green wave plus a small cream cushion = 10.8vw. */
  padding-bottom:calc(clamp(3.5rem,2rem + 5vw,6.5rem) + 10.8vw);
  overflow:hidden;

  /* Generated background photo shown CLEAN — no tint layer on top of it.
     The earlier cream veil washed the artwork out and left a flat band
     across the foot of the section. The background image is already light
     enough for the copy to read; `background-color` is only the fallback
     for the moment before the image decodes. */
  background-color:var(--kb-mint);
  background-image:url("../img/deco/hero-bg.png");
  background-size:cover;
  background-position:center bottom;
  background-repeat:no-repeat;
}

/* Readability wash for the COPY COLUMN ONLY.
   This is deliberately NOT the old full-section veil: that one covered the
   whole photo and left a flat band along the foot of the hero. This is a
   purely HORIZONTAL fade — cream at the left edge, fully transparent by the
   midpoint — so the headline and lead sit on a light ground while the right
   half of the artwork (sky, fields and the phone mockup) stays untouched.
   Without it the lead paragraph runs over the dark green field band and
   drops below an accessible contrast ratio. */
.hero::before{
  content:"";
  position:absolute;
  inset:0;
  z-index:1;
  pointer-events:none;
  background:linear-gradient(
    to right,
    rgb(248 251 244 / .70) 0%,
    rgb(248 251 244 / .55) 24%,
    rgb(248 251 244 / .22) 40%,
    rgb(248 251 244 / 0)   54%
  );
}
.hero__row{ position:relative; z-index:2; }

.hero__title{
  /* Deliberately a step below --kb-fs-h1. The Gujarati headline is long and
     at the full h1 size it ran to five lines and overpowered the mockup; the
     token itself is left alone so other h1-scale type is unaffected. */
  font-size:clamp(1.75rem, 1.05rem + 1.95vw, 2.85rem);
  font-weight:700;
  line-height:1.3;
  letter-spacing:-.015em;
  margin-bottom:1.1rem;
  max-width:30ch;
}
.hero__lead{
  font-size:var(--kb-fs-lead);
  max-width:38rem;
  color:var(--kb-body);
}

/* --- 3D tilted mockup -------------------------------------------------- */
.hero__mockup{
  position:relative;
  perspective:1700px;
  /* A FIXED height, not min-height. The phones are sized from this height
     (see below) so the mockup can never grow taller than its own box and
     push the vertically-centred copy column out of the hero. */
  height:clamp(400px, 44vw, 580px);
}
.hero__mockup .kb-phone{
  position:absolute;
  transform-style:preserve-3d;
  /* Hero phones are large, so they can carry a slightly softer corner */
  --kb-phone-r:34px;
}
/* Phones are sized by HEIGHT; the frame's aspect-ratio derives the width.
   Sizing by width instead would make tall phones overflow the hero. */
.hero__mockup .kb-phone__frame{
  height:100%;
  width:auto;
}
/* Both phones stay PERFECTLY UPRIGHT — no rotateZ — exactly like the
   reference mockup. The only 3D is a shared rotateY so the two devices read
   as one turned pair rather than two independently skewed images.
   Keeping the rotateY identical on both is what sells the effect; giving
   them different angles makes them look like separate photos. */

/* Left phone: sits LOWER and slightly smaller, overlapping in front */
.hero__mockup .kb-phone--back{
  height:90%;
  /* Pushed in from 2% so the two devices actually OVERLAP. At the old offset
     they sat with a ~50px gap between them, which read as two unrelated
     screenshots instead of one stacked pair. */
  left:13%;
  top:10%;
  z-index:2;
  transform:rotateY(-13deg);
  filter:brightness(.98);
}
/* Right phone: taller, higher, set back behind the left one */
.hero__mockup .kb-phone--front{
  height:100%;
  right:1%;
  top:0;
  z-index:1;
  transform:rotateY(-13deg);
}

/* --- Short-viewport fit ------------------------------------------------
   `min-height:100svh` alone only guarantees the hero is never SHORTER than
   the screen. On a laptop (or at 125-150% OS zoom) the usable height drops
   to ~700-800px while the hero's own stack — nav offset + copy column +
   the 10.8vw ribbon reserve — still wants ~1100px, so it spills past the
   fold no matter what the min-height says.

   These steps shrink the stack against the viewport HEIGHT (the width is
   already handled by the clamps) until it genuinely fits: the decorative
   padding comes off first, then the mockup, then one notch of type scale.
   Desktop-only (`min-width:992px`) because below that the layout is
   single-column and a full-height hero is not the goal.

   NOTE: this block must stay BELOW `.hero__mockup` / `.hero__title`.
   Media queries add no specificity, so placing it earlier in the file let
   the unconditional rules win and nothing resized.                       */
@media (min-width:992px) and (max-height:900px){
  .hero{
    /* Only the nav clearance is kept on top; the decorative extra goes. */
    padding-top:calc(var(--kb-nav-h) + var(--kb-nav-gap) + 1.25rem);
    /* The 10.8vw ribbon reserve is NON-NEGOTIABLE — go below it and the copy
       slides under the divider artwork. Only the cushion above it is cut. */
    padding-bottom:calc(1.25rem + 10.8vw);
  }
  /* Cap the mockup at whatever vertical room is actually left over once
     the nav offset and the ribbon reserve have taken their share. */
  .hero__mockup{
    height:min(
      clamp(400px, 44vw, 580px),
      calc(100svh - var(--kb-nav-h) - var(--kb-nav-gap) - 10.8vw - 4.5rem)
    );
  }
}
@media (min-width:992px) and (max-height:800px){
  /* Last step: one notch off the headline and lead. By this point the copy
     column, not the mockup, is the tallest thing in the row. */
  .hero__title{
    font-size:clamp(1.55rem, .95rem + 1.5vw, 2.25rem);
    line-height:1.25;
    margin-bottom:.85rem;
  }
  .hero__lead{ font-size:1rem; }
  .hero__actions{ margin-top:1.1rem; }
}

/* Hero decorations.
   --3 is mirrored so its stem grows IN from the right edge instead of
   pointing back out of the viewport. `scaleX(-1)` is applied via a custom
   property so the float animation can compose with it (see .kb-deco). */
.hero__deco--1{ width:180px; top:12%;  left:-50px; }
.hero__deco--3{ width:160px; top:18%;  right:-46px; --kb-deco-flip:-1; }

/* Decorative vine divider pinned to the very bottom edge of the hero.
   `bottom:0` with a negative offset would clip, so it is flush and the hero
   simply ends behind it. Purely ornamental, hence aria-hidden in markup. */
.hero__line{
  position:absolute;
  left:0;
  right:0;
  bottom:0;
  width:100%;
  height:auto;
  /* line-divider-2.png is 2008x465 (4.32:1). Three measured facts drive the
     numbers here and in .hero's padding-bottom:
       - rows  83-464 are opaque (no transparent padding at the bottom),
       - rows 266-464 are FLAT CREAM, pixel-identical to --kb-cream,
       - the green wave itself therefore ends at row ~265.

     Left at `bottom:0` the ~200 cream rows sat inside the hero and ate
     ~10vw of the fold for nothing. Instead the image is pushed down by
     35.5% of its own height so row ~300 lands on the hero's bottom edge;
     the leftover cream tail runs past it and is cut by `.hero{overflow:
     hidden}`. Cream-on-cream, so the cut is invisible, and the fold gets
     those pixels back.

     The 35px of cream kept below the wave (row 265 -> 300) is deliberate
     breathing room so the soft leaf tips at the wave's lowest points are
     never clipped. */
  transform:translateY(35.5%);
  z-index:3;
  pointer-events:none;
  user-select:none;
}


/* ==========================================================================
   07. ABOUT COMPANY
   Eyebrow, title and body copy now sit in one column so the heading is
   never stranded away from the text it introduces.
   ========================================================================== */
.about{ background:var(--kb-cream); }

.about__visual{
  position:relative;
  padding:1.5rem;
}
.about__visual img{
  position:relative;
  z-index:1;
  border-radius:var(--kb-r-xl);
  width:100%;
}

.about__copy{ position:relative; z-index:2; }

.about__text{
  font-size:var(--kb-fs-lead);
  margin-bottom:1.8rem;
}
.about__text strong{ color:var(--kb-primary); font-weight:600; }

/* Fact rows */
.about__facts{
  display:grid;
  gap:.65rem;
  margin-bottom:2rem;
}
.about__facts li{
  display:flex;
  flex-wrap:wrap;
  align-items:baseline;
  gap:.4rem 1rem;
  background:var(--kb-white);
  border:1px solid var(--kb-line);
  border-left:4px solid var(--kb-primary);
  border-radius:var(--kb-r-sm);
  padding:.85rem 1.2rem;
  transition:transform var(--kb-t-base), box-shadow var(--kb-t-base);
}
.about__facts li:hover{ transform:translateX(5px); box-shadow:var(--kb-shadow-sm); }

.about__fact-label{
  flex:0 0 auto;
  font-size:.76rem;
  font-weight:700;
  letter-spacing:.11em;
  text-transform:uppercase;
  color:var(--kb-muted);
  min-width:9.5rem;
}
.about__fact-value{ font-weight:600; color:var(--kb-ink); line-height:1.5; }

.about__deco{ width:150px; bottom:4%; right:-40px; }
/* --2 hangs off the top-left corner, --3 fills the gap under the visual.
   Both are held well below full opacity so they stay background texture and
   never compete with the photograph they sit around. */
.about__deco--2{ width:170px; top:2%;    left:-52px; opacity:.55; }
.about__deco--3{ width:210px; bottom:2%; left:-10px; opacity:.28; --kb-deco-flip:-1; }


/* ==========================================================================
   08. OUR PLATFORM
   The flagship section — deep green, raised cards, numbered pillars.
   ========================================================================== */
.platform{
  /* NO tint layer. The generated field artwork is shown clean — the dark
     gradient that used to sit on top of it flattened the photo into a plain
     dark-green slab and the artwork may as well not have been there.
     Contrast for the body copy is now carried by the CARDS instead (see
     .platform__card / .platform__pillar, which are real frosted glass), and
     the heading block sits on the photo's own dark upper region.
     The solid gradient underneath is only the fallback for the moment
     before the image decodes. */
  background:
    url("../img/deco/platform-bg.png"),
    linear-gradient(160deg, var(--kb-primary) 0%, var(--kb-primary-darker) 100%);
  background-size:cover, auto;
  background-position:center, center;
  background-repeat:no-repeat;
  color:var(--kb-on-dark-soft);
  /* Both edges are cut by a 70px-deep curve (::before / ::after), so the
     rhythm gets that much extra on each side — otherwise the eyebrow sits
     right under the top lobe and the last pillar inside the bottom one.
     Symmetrical on purpose: the two curves now mirror each other, so uneven
     padding would make the section look like it was pasted in crooked. */
  padding-top:calc(var(--kb-section-y) + 70px);
  padding-bottom:calc(var(--kb-section-y) + 70px);
}
/* Soft curved cut at the top so it lifts away from the About section */
.platform::before{
  content:"";
  position:absolute;
  top:-1px; left:0; right:0;
  height:70px;
  background:var(--kb-cream);
  border-radius:0 0 50% 50% / 0 0 100% 100%;
  transform:scaleX(1.5);
}
/* ...and the same cut mirrored along the bottom edge, so the section is
   closed by a curve instead of a hard horizontal line. Same geometry as
   ::before with the radii moved to the TOP corners, which makes the lobe
   rise out of the next section (.features, cream) instead of hanging down
   out of this one. Painted in the FOLLOWING section's colour — that is what
   makes it read as the next section eating into this one. */
.platform::after{
  content:"";
  position:absolute;
  bottom:-1px; left:0; right:0;
  height:70px;
  background:var(--kb-cream);
  border-radius:50% 50% 0 0 / 100% 100% 0 0;
  transform:scaleX(1.5);
}
.platform__row{ position:relative; z-index:2; }

/* Frosted glass, shared by the main card and the pillars.
   With the section's dark tint gone, this is now doing real work: it is the
   only thing separating white copy from a photographic background, so the
   recipe is a proper glass stack rather than a faint 7% wash —
     - a slightly stronger white fill for body,
     - a real blur WITH saturation so the greens behind stay colourful
       instead of going grey,
     - a 1px inset highlight along the top edge, which is what actually
       sells "pane of glass" rather than "translucent box",
     - a soft drop shadow to lift it off the photo. */
.platform__card,
.platform__pillar{
  background:linear-gradient(180deg, rgb(255 255 255 / .16) 0%, rgb(255 255 255 / .09) 100%);
  border:1px solid rgb(255 255 255 / .22);
  backdrop-filter:blur(16px) saturate(150%);
  -webkit-backdrop-filter:blur(16px) saturate(150%);
  box-shadow:
    inset 0 1px 0 rgb(255 255 255 / .28),
    0 18px 40px rgb(10 24 4 / .28);
}

.platform__card{
  /* Single source of truth for the corner icon's size — the icon itself and
     the text reserves beside it all derive from this one value. */
  --kb-pcard-icon:clamp(140px, 10vw + 2rem, 215px);
  position:relative;
  height:100%;
  padding:clamp(1.8rem,1.2rem + 1.6vw,2.8rem);
  border-radius:var(--kb-r-lg);
  /* The icon is now flush in the corner, so it has to be clipped by the
     card's own radius instead of hanging over it. */
  overflow:hidden;
}
.platform__card p{ color:var(--kb-on-dark-soft); }
.platform__card p + p{ margin-top:1.1rem; }

/* Lifted OUT of the text flow and parked in the card's top-right corner.
   Inline it was a small 78px tile stacked above the heading, which wasted a
   whole row of vertical space and read as an afterthought. Absolute keeps
   the heading at the top of the card and lets the icon be much larger.
   The tile chrome (plate + border) is dropped — at this size the 3D icon
   carries itself and a box around it just looked heavy. */
.platform__card-icon{
  position:absolute;
  /* Flush INTO the top-right corner, not inset from it. The old clamp inset
     left the icon floating in the middle of the card's padding, which made
     the corner look padded on one side and crowded on the other; sitting on
     the corner itself (and clipped by the card's radius via
     `.platform__card{overflow:hidden}`) reads as part of the card. */
  top:0;
  right:0;
  display:grid;
  place-items:center;
  /* Deliberately large — this is the section's hero icon, not a bullet glyph.
     The width is exported as a custom property so the copy below can derive
     its own right-hand reserve from exactly the same value instead of two
     hand-tuned numbers drifting apart. */
  width:var(--kb-pcard-icon);
  height:var(--kb-pcard-icon);
  pointer-events:none;
}
.platform__card-icon img{
  width:100%; height:100%;
  object-fit:contain;
  filter:drop-shadow(0 10px 22px rgba(0,0,0,.3));
}

.platform__card-title{
  color:var(--kb-on-dark);
  font-size:var(--kb-fs-h3);
  margin-bottom:.9rem;
  /* Keep the heading clear of the absolutely-positioned icon above-right.
     The icon is now corner-flush, so the reserve is measured from the card's
     padding edge: icon width MINUS the padding it no longer sits inside. */
  padding-right:calc(var(--kb-pcard-icon) - clamp(1.8rem,1.2rem + 1.6vw,2.8rem) + 1rem);
}
/* Proper text wrap around the corner icon.
   A plain `padding-right` reserved the gutter for the WHOLE paragraph, so
   the text stayed in a narrow column long after the icon had ended and the
   card showed a permanent empty strip down its right side.
   A float does the real thing instead: an invisible spacer is floated into
   the top-right, the copy wraps around it for exactly as many lines as the
   icon is tall, and every line below runs the card's full width. */
.platform__card--main > p:first-of-type{ padding-right:0; }
.platform__card--main > p:first-of-type::before{
  content:"";
  float:right;
  /* Same width as the icon, less the padding the icon overhangs, plus a
     1rem gutter so the text never touches the artwork. */
  width:calc(var(--kb-pcard-icon) - clamp(1.8rem,1.2rem + 1.6vw,2.8rem) + 1rem);
  /* How far the icon still reaches DOWN past the title. Derived from the
     icon box, not hand-tuned: icon height minus whatever the title already
     covered. Clamped at 0 so a short icon never produces a negative. */
  height:max(0px, calc(var(--kb-pcard-icon) - 4.2rem));
  shape-outside:content-box;
}

/* Pillars column */
.platform__pillars{
  display:grid;
  gap:1rem;
  height:100%;
  align-content:stretch;
}
.platform__pillar{
  display:flex;
  align-items:center;
  gap:1.1rem;
  padding:1.3rem 1.6rem;
  /* Fill / border / blur come from the shared glass rule above — only the
     radius and the hover behaviour are pillar-specific. */
  border-radius:var(--kb-r-md);
  transition:background var(--kb-t-base), transform var(--kb-t-base),
             box-shadow var(--kb-t-base);
}
.platform__pillar:hover{
  background:linear-gradient(180deg, rgb(255 255 255 / .26) 0%, rgb(255 255 255 / .15) 100%);
  transform:translateX(6px);
}

.platform__pillar-num{
  flex:0 0 auto;
  display:grid; place-items:center;
  width:48px; height:48px;
  font-weight:700;
  color:var(--kb-primary-dark);
  background:var(--kb-accent);
  border-radius:var(--kb-r-pill);
}
.platform__pillar-title{
  color:var(--kb-on-dark);
  font-size:1.18rem;
  margin:0;
}

/* Mirrored so the stem grows in from the right edge (see .kb-deco) */
.platform__deco--1{ width:160px; top:16%; right:-40px; opacity:.3; --kb-deco-flip:-1; }
.platform__deco--2{ width:120px; bottom:8%; left:-34px; opacity:.28; }


/* ==========================================================================
   09. KEY FEATURES
   Icons are absolutely positioned so they can be large and overlap the
   card edge instead of sitting small and inline.
   ========================================================================== */
.features{ background:var(--kb-cream); }

.feature-card{
  position:relative;
  height:100%;
  /* Was 260px. The row-1 cards have short copy, so the floor was taller
     than their content and the surplus all collected as dead space under
     the last line. The grid still equalises heights per row, so the cards
     stay level — they just stop being padded out from below. */
  min-height:210px;
  padding:1.9rem 1.8rem 1.6rem;
  border-radius:var(--kb-r-lg);
  border:1px solid var(--kb-line);
  overflow:hidden;
  isolation:isolate;
  transition:transform var(--kb-t-base), box-shadow var(--kb-t-base);
}
.feature-card:hover{ transform:translateY(-6px); box-shadow:var(--kb-shadow-md); }

/* Per-card pastel tints */
.feature-card--1{ background:#EAF4DC; }
.feature-card--2{ background:#E3EFF7; }
.feature-card--3{ background:#FBEDE6; }
.feature-card--4{ background:#FAF4DC; }
.feature-card--5{ background:#E9F1E2; }
.feature-card--6{ background:linear-gradient(120deg,#EAF4DC 0%,#DFF0F7 100%); }

/* The big illustration in the top-right of every card.

   It used to be pulled outside the card with negative offsets, so the card's
   `overflow:hidden` sliced the top and right off each illustration and every
   card lost a different amount of it. It is now fully INSET: identical size
   and identical offsets on all six cards, `object-fit:contain` so nothing is
   ever cropped, and `--kb-fcard-icon` as the single place the size lives. */
.feature-card{ --kb-fcard-icon:clamp(124px, 10vw, 158px); }
/* The two short cards in row 1 carry the least copy, so they can afford the
   largest illustration; the wide and banner cards have more text competing
   for the same line, so they stay a step smaller. Per-card sizing is why
   --kb-fcard-icon is a variable rather than a hard-coded width. */
.feature-card--1,
.feature-card--2,
.feature-card--3{ --kb-fcard-icon:clamp(134px, 11vw, 172px); }
.feature-card--wide{   --kb-fcard-icon:clamp(128px, 10.5vw, 164px); }
.feature-card--banner{ --kb-fcard-icon:clamp(132px, 11vw, 176px); }

/* Anchored to the card's BOTTOM-RIGHT and allowed to bleed a little past the
   edge, rather than floating in the top-right corner behind the copy.

   The previous version sat at top:1.1rem with `z-index:-1`, i.e. it was
   painted UNDER the text — so on the short row-1 cards the description ran
   straight across the illustration. Moving it to the opposite corner of the
   card from the heading means the copy and the artwork occupy different
   regions by construction, and the negative offsets let the illustration run
   right up to the card's edge while giving the text back the width that the
   overlap reserve was eating. The offsets are zero rather than negative
   because the card clips its own overflow to keep its rounded corners — a
   bleed would simply be sliced off. */
.feature-card__icon{
  position:absolute;
  bottom:0;
  right:0;
  width:var(--kb-fcard-icon);
  height:var(--kb-fcard-icon);
  object-fit:contain;
  object-position:bottom right;
  z-index:0;
  opacity:.95;
  filter:drop-shadow(0 12px 26px rgba(22,36,15,.18));
  transition:transform var(--kb-t-slow);
  transform-origin:center;
}
.feature-card:hover .feature-card__icon{ transform:scale(1.07) rotate(-4deg); }

.feature-card__num{
  display:inline-grid;
  place-items:center;
  width:44px; height:44px;
  margin-bottom:1rem;
  font-size:.92rem;
  font-weight:700;
  color:#fff;
  background:var(--kb-primary);
  border-radius:var(--kb-r-pill);
}
/* Both the heading and the body copy are held clear of the illustration by
   the SAME reserve, so the left column has one straight right-hand edge
   instead of two different ragged ones.

   The expression reads: full content width, minus the illustration, plus the
   card's own right padding (which the illustration sits inside of, since it
   is positioned against the padding box). That is the exact clearance — no
   magic percentage to re-tune whenever --kb-fcard-icon changes. The max() is
   a floor so a very large illustration can never starve the copy into a
   one-word-per-line column. */
.feature-card__title,
.feature-card__text{
  position:relative;
  z-index:1;
  max-width:max(50%, calc(100% - var(--kb-fcard-icon) + 1.8rem));
}
.feature-card__title{
  font-size:var(--kb-fs-h3);
  margin-bottom:.6rem;
}

/* Wide card (04) — chips get their own band at the bottom */
.feature-card--wide{ display:flex; flex-direction:column; }
.feature-card--wide .feature-card__title,
.feature-card--wide .feature-card__text{ max-width:30rem; }

.feature-card__chips{
  display:flex;
  flex-wrap:wrap;
  gap:.5rem;
  margin-top:auto;
  padding-top:1.4rem;
}
.feature-card__chips li{
  font-size:.82rem;
  font-weight:600;
  color:var(--kb-primary);
  background:rgba(255,255,255,.85);
  border:1px solid var(--kb-line);
  border-radius:var(--kb-r-pill);
  padding:.35rem .9rem;
}

/* Full-width banner card (06) */
/* The banner card is short and wide, so the illustration is centred on the
   vertical axis instead of hugging the top — but it keeps the SAME size as
   every other card so the set still reads as one family. */
.feature-card--banner{ min-height:220px; }
.feature-card--banner .feature-card__icon{
  /* The banner spans the full row, so its illustration is vertically centred
     against the copy instead of dropped into the corner. `bottom` is cleared
     explicitly so it cannot fight the inherited bottom:0. */
  top:50%;
  bottom:auto;
  right:1.6rem;
  transform:translateY(-50%);
}
.feature-card--banner:hover .feature-card__icon{
  transform:translateY(-50%) scale(1.07) rotate(-4deg);
}
.feature-card--banner .feature-card__title{ max-width:60%; }
.feature-card--banner .feature-card__text{ max-width:48%; }


/* ==========================================================================
   10. HOW IT WORKS
   Dark band with its own generated background and shaped edges top and
   bottom so it reads as a distinct "process" chapter.
   ========================================================================== */
.how{
  /* Same construction as .platform — and, like .platform, NO tint on top.
     The dark gradient that used to cover this flattened the generated
     artwork into a plain green slab. A DIFFERENT source image is used so the
     two dark-green sections don't read as the same block repeated.
     The solid gradient below the photo is only the pre-decode fallback. */
  background:
    url("../img/deco/how-bg.png"),
    linear-gradient(155deg, var(--kb-primary-dark) 0%, var(--kb-primary) 100%);
  background-size:cover, auto;
  background-position:center, center;
  background-repeat:no-repeat;
  color:var(--kb-on-dark-soft);
  padding-block:calc(var(--kb-section-y) + 2.5rem);
}

/* Shaped top and bottom edges */
.how::before,
.how::after{
  content:"";
  position:absolute;
  left:0; right:0;
  height:60px;
  background:var(--kb-cream);
  z-index:1;
}
.how::before{
  top:-1px;
  border-radius:0 0 50% 50% / 0 0 100% 100%;
  transform:scaleX(1.5);
}
.how::after{
  bottom:-1px;
  border-radius:50% 50% 0 0 / 100% 100% 0 0;
  transform:scaleX(1.5);
}
.how .container{
  position:relative;
  z-index:2;
  /* The steps are bare text, not cards, so with the tint gone they sit
     straight on the photograph. The artwork was picked to carry that: its
     bands measure ~40-55 average luminance top to bottom, so white type
     already clears ~11:1 on it without any veil.
     The shadow below is therefore only an edge-separator for the few spots
     where mist lifts the background — tight and low-blur on purpose. An
     earlier, much heavier two-layer version was needed when this section ran
     a bright golden-hour photo; against a dark image that same shadow just
     smudges the glyphs, so it was dialled back when the art changed. */
  text-shadow:0 1px 3px rgb(6 16 10 / .7);
}

/* --- Steps as a connected journey, not four identical boxes -------------
   Every other section on this page is built from cards, so repeating that
   pattern here made the process read as "four more things" instead of
   "one flow with four stages". The boxes are gone: the steps now hang off a
   single dashed rail, each marked by a node dot and an oversized outlined
   numeral, so the eye travels left-to-right along the process.             */
.how__steps{
  /* The column gap is a variable because the rail below has to solve for it
     — see the right-hand inset calc. Hard-coding it twice would let the two
     drift apart the moment the clamp is retuned. */
  --how-gap:clamp(1.2rem, .4rem + 2vw, 2.6rem);
  display:grid;
  grid-template-columns:repeat(4,1fr);
  gap:var(--how-gap);
  position:relative;
}
/* The rail the node dots sit on. It must begin at the CENTRE of node 1 and
   stop at the CENTRE of node 4 — percentages were only ever an eyeball
   approximation and left a stub of dashes running past the last dot.

   The ends are derived instead. Each dot is 16px wide and pinned to
   `left:0` of its column, so its centre is 8px in. For 4 columns of width c
   with gap g in a track of width W:
       c            = (W - 3g) / 4
       node 4 start = 3c + 3g
   so the right inset, measured from the track's right edge, is
       W - (3c + 3g + 8px) = W/4 - 0.75g - 8px
   which is exactly the calc below (25% of the track = W/4).            */
.how__steps::before{
  content:"";
  position:absolute;
  top:11px;
  left:8px;
  right:calc(25% - (var(--how-gap) * .75) - 8px);
  height:2px;
  background:repeating-linear-gradient(
    90deg,
    var(--kb-on-dark-line) 0 10px,
    transparent 10px 20px
  );
}

.how-step{
  position:relative;
  padding-top:3.2rem;      /* clears the rail and the node dot */
  background:none;
  border:0;
  transition:transform var(--kb-t-base);
}
.how-step:hover{ transform:translateY(-6px); }

/* Node dot pinned onto the rail */
.how-step::before{
  content:"";
  position:absolute;
  top:4px;
  left:0;
  width:16px;
  height:16px;
  border-radius:var(--kb-r-pill);
  background:var(--kb-accent);
  box-shadow:0 0 0 5px rgba(141,198,63,.2);
  transition:box-shadow var(--kb-t-base);
}
.how-step:hover::before{ box-shadow:0 0 0 9px rgba(141,198,63,.26); }

/* Oversized outlined numeral instead of the filled pill badge used
   elsewhere — it reads as a stage marker rather than another chip. */
.how-step__num{
  display:block;
  margin-bottom:.4rem;
  font-size:clamp(2.6rem, 1.6rem + 2.4vw, 3.9rem);
  font-weight:700;
  line-height:1;
  color:transparent;
  -webkit-text-stroke:2px rgba(141,198,63,.85);
  /* The numeral is transparent-filled, so the container's `text-shadow` would
     paint the SOLID glyph silhouette behind it and turn the outline into a
     dark blob. Killed here; `drop-shadow` is used instead because it follows
     the painted stroke, not the glyph fill, so the hollow stays hollow. */
  text-shadow:none;
  filter:drop-shadow(0 1px 4px rgb(6 16 10 / .6));
  transition:-webkit-text-stroke-color var(--kb-t-base), color var(--kb-t-base);
}
.how-step:hover .how-step__num{
  color:rgba(141,198,63,.14);
  -webkit-text-stroke-color:var(--kb-accent);
}
.how-step__title{
  color:var(--kb-on-dark);
  font-size:1.14rem;
  margin-bottom:.55rem;
}
.how-step__text{ color:var(--kb-on-dark-soft); font-size:.96rem; }

/* --- Closing qualities, as chips --------------------------------------- */
.how__tags{
  display:flex;
  flex-wrap:wrap;
  justify-content:center;
  gap:.7rem;
  margin-top:3rem;
}
.how__tag{
  padding:.5rem 1.3rem;
  font-size:.9rem;
  font-weight:600;
  letter-spacing:.06em;
  color:var(--kb-on-dark);
  background:rgba(255,255,255,.08);
  border:1px solid var(--kb-on-dark-line);
  border-radius:var(--kb-r-pill);
  transition:background var(--kb-t-base), border-color var(--kb-t-base);
}
.how__tag:hover{ background:rgba(141,198,63,.18); border-color:var(--kb-accent); }

.how__deco{ width:170px; bottom:14%; left:-44px; opacity:.3; }


/* ==========================================================================
   11. AUDIENCE — For Farmers + For Buyers, side by side
   The 3D persona is absolutely positioned at the bottom-right of the card.
   ========================================================================== */
.audience{ position:relative; background:var(--kb-cream); }

/* Floating decorations framing the two-card block. --2 is mirrored so its
   stem grows in from the right edge rather than pointing out of the page. */
/* Mirrored so the stem reads as growing IN from the page edge rather than
   pointing back off it — same correction already applied to --2 below. */
.audience__deco--1{ width:150px; top:3%;  left:-44px; opacity:.55; --kb-deco-flip:-1; }
.audience__deco--2{ width:170px; bottom:6%; right:-50px; opacity:.5; --kb-deco-flip:-1; }

.audience-card{
  position:relative;
  height:100%;
  padding:clamp(2rem,1.4rem + 1.6vw,2.8rem);
  /* Extra room at the FOOT of the card, which is where the persona now
     stands. The old rule reserved the same space at the top instead. */
  padding-bottom:clamp(2.4rem,1.6rem + 2vw,3.4rem);
  border-radius:var(--kb-r-xl);
  border:1px solid var(--kb-line);
  overflow:hidden;
  transition:transform var(--kb-t-base), box-shadow var(--kb-t-base);
}
.audience-card:hover{ transform:translateY(-6px); box-shadow:var(--kb-shadow-lg); }

.audience-card--farmer{ background:linear-gradient(165deg,#EEF7E3 0%,#FFFFFF 62%); }
.audience-card--buyer { background:linear-gradient(165deg,#E6F1F8 0%,#FFFFFF 62%); }

/* Persona illustration, anchored to the BOTTOM-right of the card.

   It used to hang off the top-right with negative offsets, where the card's
   `overflow:hidden` sliced the top of the character's head off. Sitting on
   the bottom edge it can be noticeably larger, nothing is cropped, and it
   reads as standing on the card rather than floating past its corner.
   The copy is kept clear of it by `.audience-card__body` padding below. */
.audience-card__persona{
  position:absolute;
  bottom:0;
  right:0;
  /* Deliberately large. Removing the per-card download button freed a whole
     row at the foot of each card, and at the old 32% the persona left a wide
     empty strip down the right of the copy. */
  width:clamp(240px,42%,380px);
  z-index:0;
  filter:drop-shadow(0 20px 36px rgba(22,36,15,.22));
  transition:transform var(--kb-t-slow);
}
.audience-card:hover .audience-card__persona{ transform:translateY(-8px) scale(1.03); }

/* Copy sits above the persona in stacking order, but is also inset from the
   right so the two never actually overlap at desktop widths. */
.audience-card__body{
  position:relative;
  z-index:1;
  /* Right gutter tracks the enlarged persona above. The last list item is the
     one that sits level with the character's head, so the reserve only has to
     clear roughly the persona's upper half — a full-width reserve would
     squeeze the copy into a narrow ribbon. */
  padding-right:clamp(0rem, -7rem + 26%, 10.5rem);
}

.audience-card__title{
  font-size:clamp(1.4rem,1.1rem + 1vw,1.9rem);
  margin-bottom:.9rem;
  max-width:100%;
}
.audience-card__lead{ margin-bottom:1.4rem; }

.audience-card__list{
  display:grid;
  gap:.6rem;
  margin-bottom:1.9rem;
}
.audience-card__list li{
  position:relative;
  padding-left:2rem;
  font-weight:500;
  color:var(--kb-ink);
}
/* Tick bullet drawn in CSS */
.audience-card__list li::before{
  content:"";
  position:absolute;
  left:0; top:.55em;
  width:18px; height:18px;
  background:var(--kb-primary);
  border-radius:var(--kb-r-pill);
}
.audience-card__list li::after{
  content:"";
  position:absolute;
  left:6px; top:calc(.55em + 5px);
  width:5px; height:9px;
  border:2px solid #fff;
  border-top:0; border-left:0;
  transform:rotate(42deg);
}


/* ==========================================================================
   12. WHY KHEDUT BAZAR — sticky visual + scrolling reasons
   ========================================================================== */
.why{ position:relative; background:var(--kb-mint); }

/* Single floating leaf on the TOP-LEFT corner.
   It used to ride the top-right, but that put it directly over the reasons
   list; on the left it sits in the genuinely empty margin beside the sticky
   column instead. Moving sides means mirroring it too, otherwise the stem
   points back off the page — so the `--kb-deco-flip:-1` it carried for the
   right-hand placement is simply dropped, returning it to the default `1`.
   The second leaf cluster that sat low on the left was removed entirely; see
   the note in index.html. */
.why__deco--1{ width:160px; top:5%; left:-46px; opacity:.5; }

.why__sticky{
  position:sticky;
  top:calc(var(--kb-nav-h) + var(--kb-nav-gap) + 2rem);
}
.why__visual{
  position:relative;
  /* Deliberately tight. Every pixel here is added to the sticky column's
     height, and the column's height is what decides how early it can sit
     fully inside the viewport — see the note on the image cap below. */
  margin-top:1.1rem;
  padding:1rem;
}
.why__visual img{
  position:relative;
  z-index:1;
  width:100%;
  /* Capped so the whole sticky column (eyebrow + title + image + badge) still
     fits in the viewport below the sticky offset. If the column were taller
     than the free space the browser would have nothing to pin and the block
     would simply scroll away with the page.

     The cap used to be min(42vh, 380px), which on a ~780px viewport made the
     column 513px tall. The column only clears the fold once its top is above
     `100vh - 513` = 269px, and the list handed reason 01 over to reason 02 at
     top ≈ 262px — so reason 01 was active for 680px of scrolling and the image
     and badge were cut off the bottom of the screen for every one of them.
     Trimming the cap (together with the padding above and a higher activation
     line in main.js) buys back the headroom that gives reason 01 a settled,
     fully visible moment.

     The cap is now the only thing deciding the artwork's size. The five icons
     are all roughly square (the widest is 589x447), so under `object-fit:
     contain` the height limit binds before the width does in every case — the
     column never gets taller than this number regardless of which reason is
     active, which is exactly what the sticky maths above depends on. */
  max-height:min(38vh, 350px);
  object-fit:contain;
  /* The artwork is five transparent cut-outs, so there is no rectangle left to
     round off — the border-radius that used to sit here was clipping nothing.
     A drop-shadow replaces it, because `filter` follows the alpha channel and
     therefore traces the icon's actual silhouette instead of a box around it.
     Kept soft and green-tinted so it reads as the icon resting on the section
     rather than as a cut-out pasted onto it. */
  filter:drop-shadow(0 18px 24px rgb(31 58 9 / .22));
  /* Cross-fade for the per-reason artwork swap driven by main.js. The class
     is added, the src is changed one tick later, then the class is removed —
     so the old frame fades out and the new one fades in. */
  transition:opacity .18s ease, transform .18s ease;
}
.why__visual img.is-swapping{ opacity:0; transform:scale(.97); }
/* Counter badge that updates as the user scrolls the list */
.why__badge{
  position:absolute;
  right:0; bottom:0;
  z-index:2;
  display:grid; place-items:center;
  width:84px; height:84px;
  font-size:1.5rem;
  font-weight:700;
  color:#fff;
  background:var(--kb-primary);
  border:5px solid var(--kb-mint);
  border-radius:var(--kb-r-pill);
  box-shadow:var(--kb-shadow-md);
}

/* The list is deliberately TALLER than the sticky column next to it.
   `position:sticky` can only pin an element for as long as its containing
   block (this column's row partner) is still scrolling past, so the reasons
   need generous spacing — otherwise the left visual unpins almost
   immediately and the "scroll-stick" effect is never seen.               */
.why__list{
  display:grid;
  gap:clamp(1.25rem, 0.5rem + 2vw, 3.25rem);
  padding-block:clamp(1rem, 0.4rem + 1.6vw, 3rem);
}
.why-item{
  position:relative;
  padding:2.1rem 1.8rem 2.1rem 5.4rem;
  background:var(--kb-white);
  border:1px solid var(--kb-line);
  border-radius:var(--kb-r-lg);
  opacity:.62;
  transition:opacity var(--kb-t-base), transform var(--kb-t-base),
             box-shadow var(--kb-t-base), border-color var(--kb-t-base);
}
.why-item.is-active{
  opacity:1;
  transform:translateX(8px);
  border-color:var(--kb-primary);
  box-shadow:var(--kb-shadow-md);
}
.why-item__num{
  position:absolute;
  left:1.5rem; top:1.6rem;
  display:grid; place-items:center;
  width:48px; height:48px;
  font-weight:700;
  color:var(--kb-primary);
  background:var(--kb-mint);
  border-radius:var(--kb-r-pill);
  transition:background var(--kb-t-base), color var(--kb-t-base);
}
.why-item.is-active .why-item__num{ background:var(--kb-primary); color:#fff; }

.why-item__title{ font-size:var(--kb-fs-h3); margin-bottom:.4rem; }


/* ==========================================================================
   13. APP SHOWCASE
   Home screen centred and largest; the outer pair sits lower and is
   pushed further out from the inner pair.
   ========================================================================== */
.appshow{
  /* Generated dark-field artwork shown CLEAN — no tint layer over it.

     This section used to stack a green radial glow and a near-opaque dark
     gradient on top of the photo, because the earlier artwork was not dark
     enough on its own to carry white copy. That veil flattened the photo into
     a smear of green and was the reason the whole block read as muddy. The
     replacement image was generated to the contrast budget instead of being
     corrected afterwards: its heading band measures ~77 average luminance
     (white clears 8.5:1) and its bottom third is a near-flat ~20-23, which is
     what lets the phones dissolve into it without a milky edge.

     Only the solid gradient remains, and only as a fallback for the moment
     before the photo has loaded. */
  background:
    url("../img/deco/appshow-bg.png"),
    linear-gradient(170deg, var(--kb-primary-dark) 0%, var(--kb-primary) 48%, var(--kb-primary-darker) 100%);
  background-size:cover, auto;
  background-position:center, center;
  background-repeat:no-repeat;
  color:var(--kb-on-dark-soft);
  padding-bottom:0;
}
/* Same soft curved cut as .platform, so the two dark blocks on the page open
   the same way. Matching values on purpose — see .platform::before. */
.appshow::before{
  content:"";
  position:absolute;
  top:-1px; left:0; right:0;
  height:70px;
  /* MINT, not cream. The section directly above this one (.why) is mint, so a
     cream curve painted a pale band across the join — the white-looking gap
     between the two sections. The curve has to be the colour of whatever it
     is cutting into. */
  background:var(--kb-mint);
  border-radius:0 0 50% 50% / 0 0 100% 100%;
  transform:scaleX(1.5);
  z-index:1;
}
.appshow .container{ position:relative; z-index:2; }

/* The eyebrow chip sat hard against the curved top edge. Pushing the whole
   header down clears the curve instead of nudging the chip alone, which would
   have broken the chip/title rhythm used everywhere else. */
.appshow .kb-section-head{
  padding-top:clamp(1.2rem,.6rem + 1.6vw,2.6rem);
  /* With the tint gone the heading sits directly on the photograph. Across
     the band the type occupies that measures ~77 average luminance, so white
     already clears 8.5:1 — but about 4% of those pixels belong to the soft
     glow the artwork carries at the top centre, and white over THOSE is only
     ~2.7:1. Rather than bring back a full-width veil for a 4% problem, the
     separation is bought locally: a tight, low-blur shadow that only shows
     where a glyph actually meets a bright pixel. */
  text-shadow:0 1px 4px rgb(6 16 10 / .55);
}

/* BOTTOM DIVIDER. The phones are cut off by the section's bottom edge, and a
   hard cut looked like a mistake. An opaque cream shape is laid over their
   feet instead, so they simply disappear behind the next section rather than
   being sliced.

   This replaced a green dissolve gradient. The gradient had to fade, and a
   fade is the wrong tool here: the phone screenshots are near-white, so any
   partly-opaque band over them reads as a milky grey haze rather than as
   "dark green with a phone behind it". An opaque shape has no partial band at
   all, so there is nothing left to look washed out.

   The artwork is a solid cream slab whose TOP edge arcs upward at the centre;
   only the two top corners are transparent. Its fill is #F8FBF4, which is
   exactly `--kb-cream`, so it reads as .vision's background reaching up into
   the showcase — which is why the curve and the join are now one object
   instead of the two stacked pseudo-elements .vision used to carry.

   `background-size:100% 100%` stretches it to whatever height is set rather
   than preserving the source 1964x329 ratio. The shape is a single shallow
   arc, so stretching only changes how deep that arc is; in exchange the slab
   always spans the full width with no seam at any viewport size.

   THE HEIGHT IS A FIXED PIXEL VALUE, NOT A CLAMP, AND THAT IS THE POINT.
   In the source the arc occupies the top ~20% of the image, so under
   `100% 100%` the arc's DEPTH is always 20% of whatever height this is. A
   fluid height therefore made the curve a different depth on every screen —
   deep and obvious on a wide monitor, flattened to almost nothing on a narrow
   one, where it stopped reading as a curve at all. Pinning the height pins the
   depth: the arc is 36px deep everywhere, and only its horizontal spread
   follows the viewport, which is unavoidable for a full-bleed divider.

   `bottom:-40px` pushes the whole slab 40px past the section's foot. The arc
   rides down with it, so it sits lower over the phone row and hides more of
   it; the 40px that overhangs is cut by `.kb-section{overflow:clip}` and lands
   on .vision's cream, which is the same colour, so the cut is invisible.

   Sits above the phones (z-index 3 vs. the container's 2). */
.appshow::after{
  content:"";
  position:absolute;
  left:0; right:0; bottom:-40px;
  height:180px;
  z-index:3;
  pointer-events:none;
  background:url("../img/deco/appshow-divider.png") center bottom / 100% 100% no-repeat;
}

.appshow__stage{
  display:flex;
  align-items:flex-end;
  justify-content:center;
  /* One gap value for the whole row — every neighbouring pair of phones is
     now spaced identically. The outer pair used to carry extra margin, which
     made the two outer gaps visibly wider than the two inner ones. */
  gap:1.1rem;
  padding-top:1.5rem;
  perspective:2000px;
  /* The phones are pushed down past the foot of the section so they are cut
     off by its bottom edge, as if rising out of it. The stage itself must
     NOT clip them — `.kb-section{overflow:clip}` on the section does that. */
  margin-bottom:-70px;
}
.appshow__phone{
  flex:0 0 auto;
  transition:transform var(--kb-t-slow);
  /* Showcase phones are roughly a third of the hero's size, so the shared
     corner radius is scaled down to match (see .kb-phone). */
  --kb-phone-r:20px;
}
.appshow__phone:hover{ transform:translateY(-14px); }

/* Centre — biggest, lifted, in front */
.appshow__phone--center{ width:230px; z-index:5; transform:translateY(-34px); }
.appshow__phone--center:hover{ transform:translateY(-48px); }

/* Inner pair — slightly smaller, angled inward */
.appshow__phone--left { width:196px; z-index:4; transform:translateY(6px)  rotate(-4deg); }
.appshow__phone--right{ width:196px; z-index:4; transform:translateY(6px)  rotate(4deg); }
.appshow__phone--left:hover { transform:translateY(-8px) rotate(-4deg); }
.appshow__phone--right:hover{ transform:translateY(-8px) rotate(4deg); }

/* Outer pair — smallest and lowest. No extra margin: the gap is uniform. */
.appshow__phone--far-left {
  width:168px; z-index:3;
  transform:translateY(46px) rotate(-9deg);
}
.appshow__phone--far-right{
  width:168px; z-index:3;
  transform:translateY(46px) rotate(9deg);
}
.appshow__phone--far-left:hover { transform:translateY(32px) rotate(-9deg); }
.appshow__phone--far-right:hover{ transform:translateY(32px) rotate(9deg); }

.appshow__deco{ width:150px; top:18%; left:-38px; opacity:.3; }


/* ==========================================================================
   14. VISION + COMPANY INFORMATION (merged)
   ========================================================================== */
.vision{
  position:relative;
  overflow:hidden;
  background:var(--kb-cream);
  /* Deliberately smaller than the shared `--kb-section-y` rhythm. The divider
     above already ends in a wide band of this exact cream, so a full section's
     worth of padding on top of it stacked into a gap that looked like a
     mistake. The fixed 70px is not padding in the visual sense — it is the
     amount the showcase overhangs this section by, so it is dead space before
     the heading can start at all. Only the fluid part is spacing, and it is
     the part that was cut.

     The fixed term is 60px rather than the full 70px overhang, and shaving it
     is safe rather than sloppy: the divider's cream and this section's cream
     are the same colour with no boundary between them, so the heading is not
     sitting "under" anything it can collide with. The only hard floor is where
     the artwork still has DARK above it — the arc bottoms out around 34px
     ABOVE this section's top edge, so everything from there down is already
     solid cream and the heading clears it by a wide margin. */
  padding-top:calc(clamp(1.5rem,.75rem + 1.5vw,2.75rem) + 60px);
}
/* This section used to draw the join with .vision itself: a flat dark slab
   plus a cream lobe with rounded top corners, stacked so the cream appeared
   to rise into the showcase. That pair is gone — `.appshow::after` now carries
   a cream divider image that does the same job in one object, and inside the
   dark section where it belongs.

   Two layers were only ever needed because a CSS-drawn lobe can just rotate a
   border-radius, and a shape can only rise into its neighbour if the
   neighbour's colour is already painted beneath it. The artwork has the arc
   baked into its alpha channel, so there is nothing to paint underneath, and
   the offset bookkeeping between the two (`--kb-appshow-overlap`) disappears
   with them. */
.vision > .container{ position:relative; z-index:1; }
.vision__deco{ z-index:1; }

.vision__lead{
  font-size:clamp(1.1rem,1rem + .5vw,1.35rem);
  font-weight:500;
  color:var(--kb-ink);
  margin-bottom:1.2rem;
  padding-left:1.4rem;
  border-left:4px solid var(--kb-primary);
}
.vision__text{ font-size:var(--kb-fs-lead); }

/* Company Information card.

   This was a plain white box with a hairline under its title — correct, but
   it read as a form rather than as part of the page. The restyle gives it a
   solid brand-green header band instead, and moves the padding off the card
   and onto its children so the band and the row highlights can run edge to
   edge. `--kb-vinfo-pad` is the single inset every child re-applies, so the
   left margin of the title, the rows and the values all still line up. */
.vision__info{
  --kb-vinfo-pad:clamp(1.8rem,1.2rem + 1.6vw,2.6rem);
  position:relative;
  /* Clips the header band's square top corners to the card's radius. */
  overflow:hidden;
  padding:0 0 .75rem;
  /* Settles from white into the palette mint towards the foot, so the card
     has some depth instead of being a flat rectangle on a flat section. */
  background:linear-gradient(180deg, var(--kb-white) 58%, var(--kb-mint) 100%);
  border:1px solid var(--kb-line);
  border-radius:var(--kb-r-lg);
  /* Lifted further off the page than --kb-shadow-sm managed. Tinted green and
     offset downward so it reads as the card floating, not as a grey halo. */
  box-shadow:0 22px 45px -26px rgb(31 58 9 / .5);
}
.vision__info-title{
  display:flex;
  align-items:center;
  gap:.7rem;
  margin:0 0 .25rem;
  padding:clamp(1.05rem,.75rem + .6vw,1.45rem) var(--kb-vinfo-pad);
  font-size:var(--kb-fs-h3);
  color:var(--kb-white);
  background:linear-gradient(115deg,
    var(--kb-primary-darker) 0%,
    var(--kb-primary)        62%,
    var(--kb-primary-dark)  100%);
}
/* Accent tab in the band — the one spot of --kb-accent in this section, which
   is what stops the header from being an undifferentiated slab of green. */
.vision__info-title::before{
  content:"";
  flex:0 0 auto;
  width:9px;
  height:1.55em;
  border-radius:3px;
  background:var(--kb-accent);
}
.vision__table{ margin:0; padding:0 var(--kb-vinfo-pad); }
.vision__row{
  display:grid;
  grid-template-columns:11rem 1fr;
  gap:.5rem 1.2rem;
  padding:.95rem var(--kb-vinfo-pad);
  /* Pulled back out to the card's edges so the hover highlight below is a
     full-width band rather than a floating strip inset from the border. */
  margin-inline:calc(var(--kb-vinfo-pad) * -1);
  border-bottom:1px dashed var(--kb-line);
  transition:background var(--kb-t-fast);
}
.vision__row:hover{ background:rgb(141 198 63 / .12); }
.vision__row:last-child{ border-bottom:0; }
.vision__row dt{
  font-size:.78rem;
  font-weight:700;
  letter-spacing:.1em;
  text-transform:uppercase;
  color:var(--kb-muted);
  padding-top:.2rem;
}
.vision__row dd{
  margin:0;
  font-weight:600;
  color:var(--kb-ink);
  line-height:1.6;
}

.vision__deco{ width:140px; top:10%; right:-36px; }


/* ==========================================================================
   15. CONTACT US
   Intro and buttons on the left, three inline cards on the right.
   ========================================================================== */
.contact{ background:var(--kb-mint); }

.contact__text{ font-size:var(--kb-fs-lead); }

.contact__cards{ display:grid; gap:1rem; }

.contact-card{
  position:relative;
  display:flex;
  align-items:center;
  gap:1.2rem;
  padding:1.5rem 1.7rem 1.5rem 2.1rem;
  background:var(--kb-white);
  border:1px solid var(--kb-line);
  border-radius:var(--kb-r-lg);
  overflow:hidden;
  transition:transform var(--kb-t-base), box-shadow var(--kb-t-base),
             border-color var(--kb-t-base);
}
.contact-card:hover{
  transform:translateX(8px);
  border-color:var(--kb-primary);
  box-shadow:var(--kb-shadow-md);
}
.contact-card--static:hover{ transform:none; }

/* Decorative accent line down the left edge */
.contact-card__line{
  position:absolute;
  left:0; top:14%; bottom:14%;
  width:5px;
  background:linear-gradient(180deg,var(--kb-accent) 0%,var(--kb-primary) 100%);
  border-radius:0 var(--kb-r-pill) var(--kb-r-pill) 0;
}
/* Decorative leaf watermark in the corner of each card */
.contact-card::after{
  content:"";
  position:absolute;
  right:-22px; bottom:-26px;
  width:110px; height:110px;
  background:url("../img/deco/leaf-2.png") center/contain no-repeat;
  opacity:.12;
  pointer-events:none;
  transition:transform var(--kb-t-slow), opacity var(--kb-t-base);
}
.contact-card:hover::after{ transform:rotate(-12deg) scale(1.08); opacity:.2; }

.contact-card__icon{
  flex:0 0 auto;
  display:grid; place-items:center;
  width:54px; height:54px;
  color:#fff;
  background:var(--kb-primary);
  border-radius:var(--kb-r-pill);
  box-shadow:0 8px 20px rgba(48,87,17,.26);
}
.contact-card__body{ display:flex; flex-direction:column; gap:.1rem; min-width:0; }
.contact-card__label{
  font-size:.74rem;
  font-weight:700;
  letter-spacing:.12em;
  text-transform:uppercase;
  color:var(--kb-muted);
}
.contact-card__value{
  font-weight:600;
  color:var(--kb-ink);
  line-height:1.55;
  word-break:break-word;
}

.contact__deco--1{ width:140px; top:8%;  left:-38px; }
/* Mirrored so the stem grows in from the right edge (see .kb-deco) */
.contact__deco--2{ width:120px; bottom:6%; right:-32px; --kb-deco-flip:-1; }


/* ==========================================================================
   16. CLOSING — final CTA and footer share one continuous background
   ========================================================================== */
.closing{
  position:relative;
  overflow:hidden;
  /* Four layers, same recipe as .platform / .how / .appshow:
     glow -> colour tint -> generated photo -> solid gradient fallback.
     The tint is opaque enough that the photo only reads as texture, so the
     small white footer text keeps its contrast. */
  background:
    radial-gradient(900px 520px at 50% 0%, rgba(141,198,63,.2) 0%, transparent 62%),
    linear-gradient(180deg, rgb(48 87 17 / .86) 0%, rgb(31 58 9 / .90) 46%, rgb(20 39 6 / .95) 100%),
    url("../img/deco/footer-bg.png"),
    linear-gradient(180deg, var(--kb-primary) 0%, var(--kb-primary-dark) 46%, var(--kb-primary-darker) 100%);
  background-size:auto, auto, cover, auto;
  background-position:center, center, center bottom, center;
  /* The sized radial glow would otherwise tile and leave visible seams.
     Only the repeat is overridden — the authored gradient sizes are kept. */
  background-repeat:no-repeat;
  color:var(--kb-on-dark-soft);
}
/* Curved top edge, matching the cut used by .platform and .appshow so every
   dark block on the page opens the same way. Painted in --kb-mint because
   that is the colour of .contact directly above it — the curve has to be the
   colour of whatever it is cutting into, or it shows as a pale band. */
.closing::before{
  content:"";
  position:absolute;
  top:-1px; left:0; right:0;
  height:70px;
  background:var(--kb-mint);
  border-radius:0 0 50% 50% / 0 0 100% 100%;
  transform:scaleX(1.5);
  z-index:1;
}
.closing__deco{ width:190px; top:6%; right:-50px; opacity:.25; z-index:2; }

/* --- Final CTA --------------------------------------------------------- */
.cta{
  position:relative;
  z-index:2;
  /* Top value raised to clear the 70px curve now cut into .closing's top
     edge; without it the CTA heading started inside the curve. */
  padding-block:clamp(5.5rem,3.5rem + 5vw,8.5rem) clamp(2.5rem,1.5rem + 3vw,4rem);
  text-align:center;
}
.cta__inner{ max-width:760px; margin-inline:auto; }
.cta__title{
  font-size:var(--kb-fs-h2);
  color:var(--kb-on-dark);
  margin-bottom:1.1rem;
}
.cta__text{
  font-size:var(--kb-fs-lead);
  color:var(--kb-on-dark-soft);
  margin-bottom:2rem;
}

/* --- Store buttons ------------------------------------------------------
   Two badges side by side, each carrying its own store mark. They are built
   from markup rather than bitmap badges so they stay crisp, respond to the
   site's own colour tokens and keep real, selectable text for screen
   readers and search engines.                                            */
/* Store-button pair. Base layout only — it is used both in the closing CTA
   band and in the Audience section header, which want different alignment,
   so the centring lives on the CTA modifier rather than here. */
.kb-stores{
  display:flex;
  flex-wrap:wrap;
  gap:1rem;
}
.cta__stores{ justify-content:center; }
.kb-store{
  display:inline-flex;
  align-items:center;
  gap:.75rem;
  padding:.7rem 1.4rem .7rem 1.1rem;
  color:var(--kb-primary-dark);
  background:var(--kb-white);
  border:1px solid transparent;
  border-radius:var(--kb-r-pill);
  box-shadow:var(--kb-shadow-md);
  transition:transform var(--kb-t-base), box-shadow var(--kb-t-base),
             background var(--kb-t-base);
}
.kb-store:hover{
  transform:translateY(-3px);
  box-shadow:var(--kb-shadow-lg);
  background:#fff;
  color:var(--kb-primary-dark);
}
.kb-store__icon{ display:grid; place-items:center; flex:0 0 auto; }

/* Stacked caption: a small lead-in over the store name */
.kb-store__body{ display:grid; text-align:left; line-height:1.15; }
.kb-store__pre{
  font-size:.66rem;
  font-weight:600;
  letter-spacing:.1em;
  text-transform:uppercase;
  opacity:.72;
}
.kb-store__name{ font-size:1.02rem; font-weight:700; }

/* Compact variant, used in the App Showcase header.

   Everything is scaled down together — padding, gaps, both text sizes and the
   store marks — rather than only shrinking the box, which would have left
   oversized type crammed inside a small pill. The pair is centred here because
   that header is centred; the base class stays alignment-neutral.

   These sit immediately above the phone row, which is what the section is
   actually about, so at full size they pulled attention away from it. */
.kb-stores--sm{
  justify-content:center;
  gap:.75rem;
  margin-top:1.5rem;
}
.kb-stores--sm .kb-store{
  gap:.55rem;
  padding:.5rem 1.05rem .5rem .85rem;
}
.kb-stores--sm .kb-store__icon img{ width:20px; height:auto; }
.kb-stores--sm .kb-store__pre{ font-size:.58rem; }
.kb-stores--sm .kb-store__name{ font-size:.88rem; }

/* --- Footer ------------------------------------------------------------ */
.footer{ position:relative; z-index:2; padding-bottom:1.6rem; }

/* The hairline between the CTA's store buttons and the footer columns.

   It lives on the CONTAINER, not on .footer__grid, and that placement is the
   whole point. .footer__grid is a Bootstrap `.row` with `g-lg-5`, so it
   carries `margin-top:-48px` while each column carries `margin-top:+48px` —
   the standard gutter trick, where the row's negative margin cancels the
   gutter above the first line of columns.

   With the rule on the row itself, both of those landed on the wrong side of
   the border: the -48px dragged the line UP, leaving only 16px above it, and
   the columns' +48px pushed their content DOWN, leaving 112px below. Same
   declared padding, wildly lopsided result.

   On the container the gutter cancels out exactly as Bootstrap intends:
   padding-top opens the gap, the row pulls back 48px, the columns give 48px
   back, so the space below the line equals the padding — which is the same
   clamp .cta uses for its padding-bottom, making the two sides symmetric by
   construction rather than by a hand-tuned number. */
.footer > .container{
  padding-top:clamp(2.5rem,1.5rem + 3vw,4rem);
  border-top:1px solid var(--kb-on-dark-line);
}

/* The footer lock-up is the white-text variant of the logo, which carries the
   Gujarati wordmark and tagline under the roundel. At 62px the tagline was
   unreadable; this is the one place on the page with room to show it
   properly, so it gets the largest treatment of the mark anywhere. */
.footer__brand img{ height:clamp(78px,7vw,104px); width:auto; margin-bottom:1.1rem; }
.footer__legal-name{
  font-weight:700;
  letter-spacing:.05em;
  color:var(--kb-on-dark);
  margin-bottom:.6rem;
}
.footer__about{ color:var(--kb-on-dark-soft); font-size:.95rem; max-width:24rem; }

.footer__heading{
  font-size:.82rem;
  font-weight:700;
  letter-spacing:.14em;
  text-transform:uppercase;
  color:var(--kb-accent);
  margin-bottom:1.1rem;
}
.footer__list{ display:grid; gap:.55rem; }
.footer__list li,
.footer__list a{ color:var(--kb-on-dark-soft); font-size:.95rem; }
.footer__list a{ transition:color var(--kb-t-base), padding-left var(--kb-t-base); }
.footer__list a:hover{ color:var(--kb-accent); padding-left:5px; }
/* Items that are not links yet (legal pages are not published) */
.footer__list--plain li{ line-height:1.65; }

.footer__bottom{
  margin-top:clamp(2rem,1.2rem + 2vw,3rem);
  padding-top:1.4rem;
  border-top:1px solid var(--kb-on-dark-line);
  text-align:center;
  font-size:.88rem;
  color:var(--kb-on-dark-soft);
}


/* ==========================================================================
   17. SCROLL ANIMATION STATES
   JS adds .is-inview; anime.js handles the richer timelines. These rules
   are the no-JS / pre-animation resting state.
   ========================================================================== */
[data-anim]{ opacity:0; }
[data-anim].is-inview{ opacity:1; }

/* If JS never runs, nothing should stay invisible. */
.no-js [data-anim]{ opacity:1 !important; transform:none !important; }

/* --- Word-by-word heading reveal ------------------------------------------
   main.js splits [data-anim="title"] into .kb-word-wrap > .kb-word pairs.
   The wrapper is an overflow:hidden mask; anime.js slides .kb-word up from
   110% so each word appears to rise out of the line below it.            */
.kb-word-wrap{
  display:inline-block;
  overflow:hidden;
  vertical-align:bottom;
  /* Extra room so descenders (p, g, y) are not clipped by the mask. */
  padding-bottom:.12em;
  margin-bottom:-.12em;
}
.kb-word{
  display:inline-block;
  will-change:transform;
}

/* Masks must never hide text when motion is off or JS is absent. */
.no-js .kb-word-wrap,
.no-js .kb-word{ overflow:visible; transform:none !important; }

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


/* ==========================================================================
   18. RESPONSIVE
   ========================================================================== */

/* --- Large desktop and below ------------------------------------------- */
@media (max-width:1199.98px){
  .kb-nav__link{ padding:.5rem .7rem; font-size:.86rem; }
  .kb-nav__brand img{ height:48px; }
  /* Two rows of two, so the single horizontal rail no longer describes the
     flow — it is dropped and each step keeps only its own node dot. */
  .how__steps{ grid-template-columns:repeat(2,1fr); gap:2rem 1.6rem; }
  .how__steps::before{ display:none; }
  .how-step{ padding-top:2.4rem; }
  .how-step:not(:last-child)::after{ display:none; }
  .appshow__phone--center{ width:200px; }
  .appshow__phone--left,
  .appshow__phone--right{ width:172px; }
  .appshow__phone--far-left,
  .appshow__phone--far-right{ width:146px; }
}

/* --- Tablet: navbar becomes a floating card menu ------------------------ */
@media (max-width:991.98px){
  .kb-nav__toggle{ display:flex; }
  .kb-nav__cta{ display:none; }
  .kb-nav__cta-mobile{ display:inline-flex; width:100%; margin-top:.6rem; }

  .kb-nav__menu{
    position:absolute;
    top:calc(100% + 12px);
    left:0; right:0;
    flex-direction:column;
    align-items:stretch;
    gap:.2rem;
    padding:1rem;
    background:rgba(255,255,255,.97);
    backdrop-filter:blur(18px);
    -webkit-backdrop-filter:blur(18px);
    border:1px solid var(--kb-line);
    border-radius:var(--kb-r-lg);
    box-shadow:var(--kb-shadow-lg);

    opacity:0;
    visibility:hidden;
    transform:translateY(-12px);
    transition:opacity var(--kb-t-base), transform var(--kb-t-base), visibility var(--kb-t-base);
  }
  .kb-nav__menu.is-open{ opacity:1; visibility:visible; transform:translateY(0); }

  .kb-nav__list{ flex-direction:column; align-items:stretch; gap:0; }
  .kb-nav__link{
    padding:.85rem 1rem;
    font-size:1rem;
    border-bottom:1px solid var(--kb-line);
    border-radius:var(--kb-r-sm);
  }
  .kb-nav__link.is-active{ color:#fff; background:var(--kb-primary); }
  .kb-nav__indicator{ display:none; }   /* indicator is desktop-only */

  /* Hero stacks. `height` (not min-height) because the desktop rule sets a
     fixed height and the phones are sized from it — a min-height would be
     ignored and the mockup would keep its desktop proportions. */
  .hero__mockup{ height:clamp(340px, 62vw, 520px); max-width:560px; margin-inline:auto; }

  /* One card per row at tablet, so the persona can stay generous while the
     copy simply reserves a wider gutter for it. */
  .audience-card__persona{ width:clamp(180px,24%,260px); }
  .audience-card__body{ padding-right:clamp(0rem, -4rem + 20%, 7rem); }

  /* Sticky column releases on tablet */
  .why__sticky{ position:static; }
  .why-item{ opacity:1; }
  .why__badge{ display:none; }

  /* The desktop cap on this image is tight for one reason only: the column has
     to fit inside the viewport or there is nothing for `position:sticky` to
     pin. The rule directly above releases the sticky, so that constraint is
     gone from here down and the cap can be relaxed.

     It needs to be. The column is full-width at this breakpoint, and the icons
     are near-square, so `object-fit:contain` was sizing them off the 350px
     height into an 826px-wide box — a 288px icon marooned in the middle with
     roughly 270px of empty space on either side. Letting it grow closes most
     of that gap without the artwork ever exceeding its native 523px. */
  .why__visual img{ max-height:min(52vh, 440px); }
  /* The column stacks full-width here, so the heading starts at the container
     edge and the top-left leaf — comfortably clear of it on desktop — lands
     straight behind "શા માટે". Pushed further off-canvas and faded so the
     title stays the only thing being read in that corner. */
  .why__deco--1{ left:-92px; opacity:.3; }

  /* App showcase: five phones no longer fit side by side below 992px, and the
     section clips its own overflow, so the outer pair would simply be cut in
     half. Turn the stage into a snap scroller from here down instead. */
  .appshow__stage{
    justify-content:flex-start;
    gap:1rem;
    padding-inline:1rem;
    /* The desktop layout lets the phones bleed out of the bottom edge. A
       scroller cannot do that (its own overflow would clip them), so the
       negative pull is cancelled here. */
    margin-bottom:0;
    overflow-x:auto;
    scroll-snap-type:x mandatory;
    -webkit-overflow-scrolling:touch;
    scrollbar-width:none;
  }
  .appshow__stage::-webkit-scrollbar{ display:none; }
  .appshow__phone{ scroll-snap-align:center; }

  /* With that negative pull cancelled the showcase no longer overhangs this
     section at all, so the 70px of clearance the desktop heading needs is
     dead space here. */
  .vision{ padding-top:clamp(1rem,.5rem + 1vw,1.75rem); }

  .vision__row{ grid-template-columns:1fr; gap:.2rem; }

  .feature-card--banner .feature-card__title,
  .feature-card--banner .feature-card__text{ max-width:62%; }
}

/* --- Phone -------------------------------------------------------------- */
@media (max-width:767.98px){
  :root{ --kb-nav-h:68px; --kb-nav-gap:12px; }

  .kb-nav__brand img{ height:42px; }
  .kb-nav__shell{ padding:0 .5rem 0 .9rem; }

  .how__steps{ grid-template-columns:1fr; }
  .how::before,
  .how::after{ height:36px; }

  /* Only the size comes down — the icon stays fully inset on every card so
     it is never cropped, exactly as on desktop. */
  .feature-card{ min-height:0; padding:1.7rem 1.5rem; --kb-fcard-icon:96px; }
  .feature-card__title{ max-width:56%; }
  .feature-card--banner .feature-card__title,
  .feature-card--banner .feature-card__text{ max-width:60%; }

  .audience-card__persona{ width:150px; }
  .audience-card__body{ padding-right:0; }

  .why-item{ padding:1.4rem 1.4rem 1.4rem 4.6rem; }
  .why-item__num{ left:1.1rem; top:1.3rem; width:42px; height:42px; }

  /* Scroller already set up at the 992px breakpoint — only the phone sizes
     need to come down further on a real phone screen. */
  .appshow__phone--center{ width:180px; transform:translateY(-14px); }
  .appshow__phone--left,
  .appshow__phone--right{ width:160px; transform:translateY(4px); }
  .appshow__phone--far-left,
  .appshow__phone--far-right{ width:150px; transform:translateY(10px); margin:0; }

  .contact-card{ padding:1.3rem 1.3rem 1.3rem 1.7rem; gap:1rem; }
  .contact-card__icon{ width:46px; height:46px; }
  .contact-card:hover{ transform:none; }

  .kb-btn-row .kb-btn{ width:100%; }

  /* Keep decorations from pushing the layout around on small screens */
  .kb-deco{ opacity:.35; }
  .hero__deco--1,
  .hero__deco--3{ width:110px; }
}
