/* ══════════════════════════════════════════════════════════════════════════
   animalsss — depth and motion.

   Loads after theme.css and reads only its tokens, so nothing here knows what
   colour the site is. It is deliberately written against the class names that
   already exist — .lp-btn (224 uses), .mph-card, .mp-listing-card, .pf-panel,
   .cf-post, .mandi-table, .card, .btn — so 251 templates got depth without one
   of them being edited.

   ── What "3D" means here ──
   Not perspective transforms on everything: light from above. A raised thing
   gets a lighter top edge (--ring), a shadow below it (--e2), and a surface
   that is a hair lighter at the top than the bottom (--grad-surface). Those
   three together are what the eye reads as a physical object. The tilt on
   pointer move and the lift on hover are the small part; the constant part is
   the shading, and it costs nothing to paint.

   ── What it must not cost ──
   This site is opened on ₹6,000 Android phones on 3G. So: no box-shadow
   transitions (they repaint the whole layer — the lift is a transform, and the
   two shadow steps are swapped, not tweened), no filter: blur() below 900px,
   no animation that runs when nothing is happening, and every hover effect is
   inside @media (hover: hover) so a tap does not leave a card stuck in its
   hover state. Anything that moves is transform or opacity, both of which the
   compositor can do without the main thread.

   Content is never hidden by this file. The reveal-on-scroll classes are added
   by pages/jscript/theme-fx.js at runtime, which means a browser with
   JavaScript off — or a crawler — gets the page fully painted instead of a
   column of invisible divs waiting for an observer that never runs.
   ══════════════════════════════════════════════════════════════════════════ */

/* ── The ambient orbs ──
   Two soft green lights that drift behind the page. Desktop only: a fixed,
   blurred, animated layer is the single most expensive thing in this file and a
   phone gets the flat radial gradient from theme.css instead. */
@media (min-width: 900px) {
  body::before,
  body::after {
    content: '';
    position: fixed;
    z-index: -1;
    pointer-events: none;
    border-radius: 50%;
    filter: blur(70px);
    opacity: .5;
    will-change: transform;
  }
  body::before {
    width: 46vw; height: 46vw;
    top: -14vw; left: -10vw;
    background: radial-gradient(circle, var(--primary-glow) 0%, transparent 70%);
    animation: fx-drift-a 24s ease-in-out infinite;
  }
  body::after {
    width: 38vw; height: 38vw;
    right: -12vw; top: 22vh;
    background: radial-gradient(circle, rgba(var(--primary-rgb), .12) 0%, transparent 70%);
    animation: fx-drift-b 31s ease-in-out infinite;
  }
}

@keyframes fx-drift-a {
  0%, 100% { transform: translate3d(0, 0, 0) scale(1); }
  50%      { transform: translate3d(6vw, 4vh, 0) scale(1.12); }
}
@keyframes fx-drift-b {
  0%, 100% { transform: translate3d(0, 0, 0) scale(1.05); }
  50%      { transform: translate3d(-5vw, -6vh, 0) scale(.92); }
}

/* ── Falling leaves ──
   A light drift of leaves tumbling down the screen across EVERY page — the
   ambient motion that used to be soap bubbles. The placement reasoning is the
   same: the site is a wall of opaque section bands (--bg/--surface fills), so a
   layer *behind* the content would be hidden everywhere except the translucent
   top bar. The leaves therefore ride just ABOVE the page content — but only down
   the two side MARGINS, never through the middle: they used to be spread right
   across the width and fell over the text people were reading. The layer sits
   BELOW every piece of chrome (nav z-index:200, sticky filter bar 50,
   notif-panel 300, cookie 99999…) so those stay crisp, and `pointer-events:none`
   keeps it inert for clicks and screen readers.

   Two nested motions make it read as wind rather than falling confetti: the
   <span> is an invisible box that falls straight down at a steady rate
   (translateY, linear), while its ::before — the leaf itself — sways side to side
   and tumbles (translateX + rotate, ease-in-out, a shorter cycle), so each leaf
   wobbles several times on the way down. Both are transform/opacity only, so the
   compositor pays for the motion, not the main thread. Negative animation-delays
   start the leaves mid-fall, so the screen is already populated at first paint.
   The count is deliberately low — 10 where the margins are wide enough for
   them, 6 below 1331px — a gentle fall, not a storm.

   `body { isolation: isolate }` makes body its own stacking context so this
   ordering is deterministic: body's positioned children sort by z-index within
   it — nav(200)/filter(50) above the leaves(6), page content below. */
body { isolation: isolate; }
.fx-leaves {
  position: fixed;
  inset: 0;
  z-index: 6;                  /* above page content, below all chrome */
  overflow: hidden;
  pointer-events: none;
  contain: layout paint;       /* isolate its paint/layout; clip to the viewport */

  /* How wide a strip down each side the leaves are allowed to use — the whole
     reason they no longer cross the page. (100vw - 1280px)/2 is the gutter
     beside the widest content column on the site (.mp-layout's max-width;
     .mp-detail-wrap 1100, .mp-my-wrap 1000 and the mandi pages are narrower
     still), so from ~1332px up a leaf falls through empty margin and never
     touches text. Capped at 4.4vw because a 27" monitor does not need a
     300px-wide leaf shower in each margin, and floored at 26px because below
     ~1332px — every phone and most laptops — there is no gutter left to hide
     in, so the leaves simply hug the two borders instead. 26px is chosen
     against the narrow layout: .mp-layout drops to 16px of padding under
     900px and a card adds its own ~14px, so a leaf at full swing reaches the
     card's padding and stops short of the text inside it.
     vw, not %, because --fx-band is read inside a transform below, where a
     percentage would resolve against the leaf's own width instead. */
  --fx-band: max(26px, min(4.4vw, (100vw - 1280px) / 2));
}
/* The faller: an invisible box the leaf lives in, dropping top → bottom. It also
   carries the fade so leaves ease in at the top and out at the bottom instead of
   popping. The peak opacity is per-leaf (--op), read inside the keyframe.

   Two derived sizes keep everything proportional to the strip, so one --fx-band
   change moves the whole effect: --sz is the drawn size (the leaf's own --s, but
   never more than 58% of the band, so a narrow strip shrinks its leaves rather
   than letting them spill inward) and --sway is the drift distance as a fraction
   of the band (--swf), so a wide margin gets a breezy wobble and a phone's 30px
   strip a small one. */
.fx-leaves span {
  position: absolute;
  top: 0;
  left: var(--x);
  --sz: min(var(--s), calc(var(--fx-band) * .58));
  --sway: calc(var(--fx-band) * var(--swf));
  width: var(--sz);
  height: var(--sz);
  will-change: transform, opacity;
  animation: fx-leaf-fall var(--dur) linear var(--delay) infinite;
}
/* Odd leaves ride the left strip, even ones the right — alternating rather than
   first-five/last-five so thinning the list on a phone (below) keeps both sides
   populated. --f is where in its own strip a leaf sits: 0 hard against the
   viewport edge, 1 against the content. The right-hand side measures from the
   leaf's own right edge (hence - var(--sz)), so the box stays inside the strip
   at both ends instead of hanging off the screen. */
.fx-leaves span:nth-child(odd)  { --x: calc((var(--fx-band) - var(--sz)) * var(--f)); }
.fx-leaves span:nth-child(even) { --x: calc(100% - var(--sz) - (var(--fx-band) - var(--sz)) * var(--f)); }
/* The leaf: a two-tone blade with a centre vein, swaying and tumbling. The
   border-radius makes a silhouette pointed at two opposite corners (top-left /
   bottom-right); the 45° vein runs along that same axis, and the 135° blade
   gradient lights it from one side. */
.fx-leaves span::before {
  content: '';
  display: block;
  width: 100%;
  height: 100%;
  border-radius: 0 100% 0 100%;
  background:
    linear-gradient(45deg, transparent 46%, rgba(0,0,0,.16) 47%, rgba(0,0,0,.16) 53%, transparent 54%),
    linear-gradient(135deg, rgba(var(--c), .92), rgba(var(--c2), .82));
  box-shadow: inset 1px -1px 3px rgba(0,0,0,.14);
  will-change: transform;
  animation: fx-leaf-sway var(--swaydur) ease-in-out var(--delay) infinite;
}
@media (min-width: 900px) {
  .fx-leaves span::before { filter: drop-shadow(0 2px 3px rgba(0,0,0,.12)); }
}
/* A 26px strip cannot hold five leaves at once without reading as a stream in a
   pipe. 1332px is where (100vw - 1280px)/2 passes the 26px floor, so at 1331px
   and below the strip is at its narrowest — there only the first three of each
   side stay, which is also every phone and most laptops. */
@media (max-width: 1331px) {
  .fx-leaves span:nth-child(n+7) { display: none; }
}

/* size / colour(R,G,B) / shade / fall-speed / start-offset / peak-opacity / sway-cycle / sway(×band) / tumble / where-in-band / rest-y */
.fx-leaves span:nth-child(1)  { --s: 27px; --c: 106,168,79;  --c2: 74,124,52;  --dur: 13s; --delay: -2s;  --op: .66; --swaydur: 4.5s; --swf: .16; --rot: 42deg; --f: .10; --ty: 12%; }
.fx-leaves span:nth-child(2)  { --s: 20px; --c: 150,162,58;  --c2: 108,120,42; --dur: 16s; --delay: -9s;  --op: .58; --swaydur: 5.6s; --swf: .12; --rot: 30deg; --f: .28; --ty: 55%; }
.fx-leaves span:nth-child(3)  { --s: 31px; --c: 214,164,66;  --c2: 176,124,44; --dur: 11s; --delay: -5s;  --op: .62; --swaydur: 3.8s; --swf: .18; --rot: 54deg; --f: .62; --ty: 40%; }
.fx-leaves span:nth-child(4)  { --s: 23px; --c: 138,184,62;  --c2: 98,148,44;  --dur: 15s; --delay: -12s; --op: .60; --swaydur: 5.0s; --swf: .14; --rot: 36deg; --f: .72; --ty: 8%;  }
.fx-leaves span:nth-child(5)  { --s: 29px; --c: 60,124,72;   --c2: 42,96,54;   --dur: 14s; --delay: -7s;  --op: .64; --swaydur: 4.2s; --swf: .17; --rot: 48deg; --f: .34; --ty: 68%; }
.fx-leaves span:nth-child(6)  { --s: 21px; --c: 212,130,54;  --c2: 172,94,40;  --dur: 12s; --delay: -3s;  --op: .58; --swaydur: 5.8s; --swf: .13; --rot: 32deg; --f: .12; --ty: 72%; }
.fx-leaves span:nth-child(7)  { --s: 33px; --c: 176,196,84;  --c2: 138,166,56; --dur: 16s; --delay: -18s; --op: .56; --swaydur: 4.6s; --swf: .18; --rot: 50deg; --f: .84; --ty: 26%; }
.fx-leaves span:nth-child(8)  { --s: 25px; --c: 92,156,84;   --c2: 64,120,60;  --dur: 13s; --delay: -10s; --op: .64; --swaydur: 3.6s; --swf: .15; --rot: 40deg; --f: .55; --ty: 34%; }
.fx-leaves span:nth-child(9)  { --s: 28px; --c: 178,108,54;  --c2: 140,80,42;  --dur: 15s; --delay: -6s;  --op: .60; --swaydur: 5.2s; --swf: .17; --rot: 46deg; --f: .48; --ty: 82%; }
.fx-leaves span:nth-child(10) { --s: 22px; --c: 80,164,120;  --c2: 54,128,92;  --dur: 12s; --delay: -15s; --op: .58; --swaydur: 4.9s; --swf: .12; --rot: 34deg; --f: .88; --ty: 90%; }

/* Straight, steady descent — the sway on ::before adds the horizontal drift and
   tumble. Fade in near the top, out near the bottom; peak at the leaf's own --op. */
@keyframes fx-leaf-fall {
  0%   { transform: translate3d(0, -14vh, 0); opacity: 0; }
  6%   { opacity: var(--op); }
  94%  { opacity: var(--op); }
  100% { transform: translate3d(0, 114vh, 0); opacity: 0; }
}
/* The flutter: sway from one side to the other while rocking through --rot. Start
   and end match so the infinite loop is seamless. */
@keyframes fx-leaf-sway {
  0%   { transform: translateX(calc(var(--sway) * -0.5)) rotate(calc(var(--rot) * -1)); }
  50%  { transform: translateX(var(--sway))              rotate(var(--rot)); }
  100% { transform: translateX(calc(var(--sway) * -0.5)) rotate(calc(var(--rot) * -1)); }
}

/* Motion-sensitive visitors keep the leaves, lose the fall: they rest scattered
   down the two margins (--x puts them there, --ty sets the height) instead of
   dropping. The --ty values are staggered within each side, so the three that
   survive on a phone are still spread down the screen rather than stacked.
   Lower opacity, because a still leaf sits in the same spot indefinitely. */
@media (prefers-reduced-motion: reduce) {
  .fx-leaves span {
    animation: none;
    top: var(--ty);
    opacity: calc(var(--op) * .7);
  }
  .fx-leaves span::before { animation: none; }
}

/* ══════════════════════════════════════════════════════════════════════════
   SURFACES
   One rule for every card-shaped thing on the site. The selector list is long
   because the names are: five apps named the same object five ways.
   ══════════════════════════════════════════════════════════════════════════ */
.fx-card,
.card, .stat-card, .feature-card, .table-card, .input-card, .highlight-box,
.mp-card, .mp-listing-card, .mp-cat-card, .mp-related-card, .mp-seller-card,
.mp-detail-section, .mp-comment,
.mph-card, .mph-livestock-card, .mph-cat-card, .mph-seller-card,
.cat-card, .wholesale-card, .affiliate-card,
.lp-stat-card, .lp-form-card, .lp-delete-card, .lp-section, .lp-card,
.pf-panel, .pf-card, .pf-chat,
.cf-post, .cf-card,
.mandi-card, .mandi-table-wrap,
.tips-card, .detail-card,
/* Found by census_depth.py, which asks the question the other gates cannot: not
   "does this page load fx.css" but "does anything on it end up raised". These were
   the outer surfaces left flat — every one of them a tile whose whole job is to look
   like an object, on a page that was already loading all four assets. The accent
   variants (.lp-summary-card.income, .accent-green) colour their value text and not
   the card, so a background here does not fight them. */
.lp-summary-card, .lp-detail-card, .lp-table-card, .lp-info-box, .ai-card,
.step-card, .mph-step-card, .tip-card, .mph-tip-card, .hero-metric,
.mph-hero-stat, .mp-detail-card, .mp-loc-card, .mp-price-box,
.comment-box, .detail-box, .info-box, .preview-box, .afl_card {
  background-color: var(--surface);
  background-image: var(--grad-surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--ring), var(--e2);
  /* Only transform and border-colour move. A box-shadow transition is a
     full-layer repaint on every frame of the hover, which is exactly the sort
     of thing that makes a cheap phone drop to 12fps on a grid of forty cards. */
  transition: transform var(--t), border-color var(--t);
  will-change: auto;
}

@media (hover: hover) and (pointer: fine) {
  .fx-card:hover,
  .card:hover, .stat-card:hover, .feature-card:hover, .table-card:hover,
  .mp-card:hover, .mp-listing-card:hover, .mp-cat-card:hover,
  .mp-related-card:hover,
  .mph-card:hover, .mph-livestock-card:hover, .mph-cat-card:hover,
  .cat-card:hover, .wholesale-card:hover, .affiliate-card:hover,
  .lp-stat-card:hover, .pf-card:hover,
  .cf-post:hover, .mandi-card:hover, .tips-card:hover,
  /* The tiles that are grids of many get the lift; a detail panel or a form section
     is one thing on the page and lifting it on hover just makes the layout twitch. */
  .lp-summary-card:hover, .ai-card:hover, .step-card:hover, .mph-step-card:hover,
  .tip-card:hover, .mph-tip-card:hover, .hero-metric:hover, .mph-hero-stat:hover,
  .afl_card:hover {
    transform: translate3d(0, -4px, 0);
    border-color: var(--line-2);
    box-shadow: var(--ring), var(--e3);
  }
}

/* A card that is a link gets a green edge on hover, so the whole tile reads as
   pressable rather than just the text inside it. */
@media (hover: hover) and (pointer: fine) {
  a > .fx-card:hover, a.fx-card:hover,
  a > .mph-card:hover, a.mph-card:hover,
  a > .mp-listing-card:hover, a.mp-listing-card:hover {
    border-color: var(--primary);
    box-shadow: var(--ring), var(--e3), 0 0 0 3px var(--primary-glow);
  }
}

/* ── Tilt ──
   theme-fx.js sets --rx/--ry from the pointer and adds .fx-tilt-on. Without the
   script the element is a plain card, and on a touch screen the script never
   arms it. */
.fx-tilt {
  transform-style: preserve-3d;
  transition: transform var(--t-slow);
}
.fx-tilt-on {
  transform: perspective(900px)
             rotateX(var(--rx, 0deg))
             rotateY(var(--ry, 0deg))
             translate3d(0, -4px, 0);
  transition: transform .08s linear;
}
/* The image inside a tilting card is pushed forward, which is what sells the
   depth — the layers separate instead of the whole tile leaning. */
.fx-tilt-on > img,
.fx-tilt-on > .mph-card-img,
.fx-tilt-on > .mp-card-img { transform: translateZ(22px); }

/* ══════════════════════════════════════════════════════════════════════════
   BUTTONS
   A lit pill: gradient top-to-bottom, white inset along the top edge, shadow
   under it, and it goes *down* when pressed.
   ══════════════════════════════════════════════════════════════════════════ */
.fx-btn,
.btn-post, .cta-btn, .mp-submit, .mp-apply, .mp-contact-btn,
.lp-btn-primary, .pf-btn.is-primary, .mph-btn-primary, .mandi-btn-primary,
.btn-primary, .w3-button.w3-green,
button[type="submit"]:not(.fx-plain),
input[type="submit"]:not(.fx-plain) {
  position: relative;
  background-image: var(--grad-primary);
  background-color: var(--primary);
  color: var(--primary-ink);
  border: 1px solid color-mix(in srgb, var(--primary-strong) 70%, black);
  border-radius: var(--radius-sm);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.28),
              0 1px 2px rgba(6,42,22,.20),
              0 6px 16px var(--primary-glow);
  font-weight: 700;
  transition: transform var(--t-fast), filter var(--t);
  overflow: hidden;
  isolation: isolate;
}

@media (hover: hover) and (pointer: fine) {
  .fx-btn:hover,
  .btn-post:hover, .cta-btn:hover, .mp-submit:hover, .mp-apply:hover,
  .mp-contact-btn:hover, .lp-btn-primary:hover, .mph-btn-primary:hover,
  .btn-primary:hover,
  button[type="submit"]:not(.fx-plain):hover,
  input[type="submit"]:not(.fx-plain):hover {
    filter: brightness(1.06) saturate(1.05);
    transform: translate3d(0, -1px, 0);
  }
}

.fx-btn:active,
.btn-post:active, .cta-btn:active, .mp-submit:active, .mp-apply:active,
.mp-contact-btn:active, .lp-btn-primary:active, .mph-btn-primary:active,
.btn-primary:active,
button[type="submit"]:not(.fx-plain):active,
input[type="submit"]:not(.fx-plain):active {
  transform: translate3d(0, 1px, 0);
  box-shadow: var(--e-press);
  filter: brightness(.97);
}

/* The sheen. One pass across the face on hover — a pseudo-element sliding on
   transform, not a background-position animation, which would repaint. */
.fx-btn::after,
.btn-post::after, .cta-btn::after, .lp-btn-primary::after,
.mph-btn-primary::after {
  content: '';
  position: absolute;
  inset: 0;
  background: var(--grad-sheen);
  transform: translateX(-120%);
  pointer-events: none;
  z-index: -1;
}
@media (hover: hover) and (pointer: fine) {
  .fx-btn:hover::after,
  .btn-post:hover::after, .cta-btn:hover::after, .lp-btn-primary:hover::after,
  .mph-btn-primary:hover::after {
    transform: translateX(120%);
    transition: transform .7s cubic-bezier(.22,.61,.36,1);
  }
}

/* Secondary and outline buttons: the same geometry, no fill. */
.fx-btn-ghost,
.lp-btn, .pf-btn, .lp-btn-outline, .btn-secondary, .btn-outline {
  border-radius: var(--radius-sm);
  transition: transform var(--t-fast), background-color var(--t), border-color var(--t), color var(--t);
}
@media (hover: hover) and (pointer: fine) {
  .lp-btn:hover, .pf-btn:hover, .lp-btn-outline:hover, .btn-outline:hover {
    transform: translate3d(0, -1px, 0);
    border-color: var(--primary);
    color: var(--primary-strong);
  }
}
.lp-btn:active, .pf-btn:active, .lp-btn-outline:active { transform: translate3d(0, 1px, 0); }

/* The ripple theme-fx.js drops at the click point. */
.fx-ripple {
  position: absolute;
  border-radius: 50%;
  transform: scale(0);
  background: rgba(255,255,255,.45);
  pointer-events: none;
  animation: fx-ripple .55s cubic-bezier(.22,.61,.36,1) forwards;
}
@keyframes fx-ripple { to { transform: scale(2.6); opacity: 0; } }

/* ══════════════════════════════════════════════════════════════════════════
   FIELDS
   Inset rather than raised — a hole you type into, next to buttons that stand
   up out of the page.
   ══════════════════════════════════════════════════════════════════════════ */
input:not([type="checkbox"]):not([type="radio"]):not([type="range"]):not([type="submit"]):not([type="button"]):not(.fx-plain),
textarea:not(.fx-plain),
select:not(.fx-plain),
.form-control, .lp-input, .pf-input {
  background-color: var(--surface);
  color: var(--ink);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  box-shadow: inset 0 1px 2px rgba(6,42,22,.06);
  transition: border-color var(--t), box-shadow var(--t), background-color var(--t);
}
input:not([type="checkbox"]):not([type="radio"]):not(.fx-plain):focus,
textarea:not(.fx-plain):focus,
select:not(.fx-plain):focus,
.form-control:focus, .lp-input:focus, .pf-input:focus {
  border-color: var(--primary);
  box-shadow: inset 0 1px 2px rgba(6,42,22,.05), 0 0 0 4px var(--primary-glow);
  outline: none;
}
::placeholder { color: var(--dim); opacity: 1; }

/* Native controls in the brand colour, which also fixes the dark-mode
   checkbox that used to render as a white square on a dark card. */
input[type="checkbox"], input[type="radio"], input[type="range"], progress {
  accent-color: var(--primary);
}

/* ══════════════════════════════════════════════════════════════════════════
   THE SHELL
   ══════════════════════════════════════════════════════════════════════════ */
.mp-nav, .lp-topbar, .mandi-header {
  background-image: var(--grad-header);
  box-shadow: 0 1px 0 rgba(255,255,255,.06), var(--e2);
}
/* Frosted, but only where the browser can do it cheaply. */
@supports (backdrop-filter: blur(10px)) {
  @media (min-width: 900px) {
    .mp-nav {
      background-color: color-mix(in srgb, var(--header) 82%, transparent);
      backdrop-filter: blur(12px) saturate(1.3);
    }
  }
}
.mp-nav-links a, .mp-dropdown-toggle { transition: background-color var(--t), color var(--t), transform var(--t-fast); }
@media (hover: hover) and (pointer: fine) {
  .mp-nav-links a:hover, .mp-dropdown-toggle:hover { transform: translate3d(0, -1px, 0); }
}

/* A dropdown, the notification panel and the drawer all arrive rather than
   appear. */
.mp-dropdown-menu.open, .notif-panel.open, .lang-switcher .mp-dropdown-menu.open {
  animation: fx-pop .22s var(--spring) both;
  border-radius: var(--radius-sm);
  box-shadow: var(--ring), var(--e4);
}
@keyframes fx-pop {
  from { opacity: 0; transform: translate3d(0, -8px, 0) scale(.97); }
  to   { opacity: 1; transform: none; }
}

.sidebar-drawer { box-shadow: var(--e4); }
.mobile-nav-mini {
  background-color: color-mix(in srgb, var(--surface) 92%, transparent);
  border-top: 1px solid var(--line);
  box-shadow: 0 -2px 20px rgba(6,42,22,.10);
}
@supports (backdrop-filter: blur(10px)) {
  .mobile-nav-mini { backdrop-filter: blur(14px); }
}
.mobile-nav-mini-item { transition: color var(--t), transform var(--t-fast); }
.mobile-nav-mini-item:active { transform: scale(.92); }

/* ══════════════════════════════════════════════════════════════════════════
   TABLES, BADGES, CHIPS, AVATARS
   ══════════════════════════════════════════════════════════════════════════ */
.lp-table, .mp-table, .detail-table, .mandi-table, table.table {
  border-collapse: separate;
  border-spacing: 0;
}
.lp-table th, .mp-table th, .detail-table th, .mandi-table th, table.table th {
  background-image: linear-gradient(180deg, var(--surface-2), var(--surface-3));
  color: var(--ink-2);
  border-bottom: 1px solid var(--line);
  position: sticky; top: 0; z-index: 2;
}
.lp-table tbody tr, .mp-table tbody tr, .mandi-table tbody tr {
  transition: background-color var(--t);
}
@media (hover: hover) and (pointer: fine) {
  .lp-table tbody tr:hover, .mp-table tbody tr:hover, .mandi-table tbody tr:hover {
    background-color: var(--primary-wash);
  }
}

.badge, .lp-badge, .pf-badge, .mph-section-badge, .cf-tag, .pf-chip {
  border-radius: var(--radius-pill);
  box-shadow: var(--ring), var(--e1);
  font-weight: 700;
}

.pf-avatar, .cf-avatar, .mph-seller-avatar, .lp-avatar, .mp-avatar {
  box-shadow: 0 0 0 2px var(--surface), 0 2px 8px rgba(6,42,22,.18);
}

/* ══════════════════════════════════════════════════════════════════════════
   ENTRANCE
   The page settles in once, and blocks rise as they are scrolled to. Both are
   opt-in from the script — see the note at the top about JavaScript being off.
   ══════════════════════════════════════════════════════════════════════════ */
.fx-in { animation: fx-rise .5s var(--t-slow) both; }
@keyframes fx-rise {
  from { opacity: 0; transform: translate3d(0, 14px, 0); }
  to   { opacity: 1; transform: none; }
}

/* rotateX is what makes this read as a card tipping up into place rather than
   a div sliding. 6 degrees; more and text goes soft on low-DPI screens. */
.fx-reveal { opacity: 0; transform: translate3d(0, 26px, 0) rotateX(6deg); transform-origin: 50% 100%; }
.fx-reveal.fx-seen {
  opacity: 1;
  transform: none;
  transition: opacity .5s var(--t-slow), transform .6s var(--t-slow);
  transition-delay: var(--fx-delay, 0ms);
}

/* Staggered children, for a grid of cards under one heading. */
.fx-stagger > * { animation: fx-rise .5s var(--t-slow) both; }
.fx-stagger > :nth-child(1) { animation-delay: .02s }
.fx-stagger > :nth-child(2) { animation-delay: .06s }
.fx-stagger > :nth-child(3) { animation-delay: .10s }
.fx-stagger > :nth-child(4) { animation-delay: .14s }
.fx-stagger > :nth-child(5) { animation-delay: .18s }
.fx-stagger > :nth-child(6) { animation-delay: .22s }
.fx-stagger > :nth-child(7) { animation-delay: .26s }
.fx-stagger > :nth-child(8) { animation-delay: .30s }
.fx-stagger > :nth-child(n+9) { animation-delay: .34s }

/* ══════════════════════════════════════════════════════════════════════════
   LOADING
   ══════════════════════════════════════════════════════════════════════════ */
.fx-skeleton,
/* The mandi page loads its rate table over ajax and shows these while it waits.
   They were the one placeholder on the site not shimmering — a static grey block
   reads as a failed load rather than a pending one. */
.mandi-skel-card, .mandi-skel-row, .mandi-skel {
  background-color: var(--surface-2);
  background-image: linear-gradient(90deg, transparent 0%, rgba(var(--primary-rgb), .10) 45%, transparent 90%);
  background-size: 240px 100%;
  background-repeat: no-repeat;
  border-radius: var(--radius-xs);
  animation: fx-shimmer 1.3s linear infinite;
}
@keyframes fx-shimmer {
  from { background-position: -240px 0; }
  to   { background-position: calc(100% + 240px) 0; }
}

/* ── Alerts ──
   A wash, an edge in the same family, and no lift. An alert is not a card: it is a
   message, and raising it off the page makes it compete with the content it is
   about. These four names were the ones left carrying no surface at all. */
.mp-error-box, .danger-box, .lp-alert-error, .alert-danger {
  background-color: var(--bad-soft);
  border: 1px solid var(--bad);
  border-left-width: 3px;
  border-radius: var(--radius-sm);
  color: var(--bad-strong);
}
.lp-alert-ok, .alert-success, .success-box {
  background-color: var(--ok-soft);
  border: 1px solid var(--ok);
  border-left-width: 3px;
  border-radius: var(--radius-sm);
  color: var(--ok-strong);
}
.lp-alert-warn, .alert-warning, .warning-box {
  background-color: var(--warn-soft);
  border: 1px solid var(--warn);
  border-left-width: 3px;
  border-radius: var(--radius-sm);
  color: var(--warn-strong);
}

.fx-spin { animation: fx-spin 1s linear infinite; }
@keyframes fx-spin { to { transform: rotate(360deg); } }

/* An unread badge or a live pill breathing, so it is noticed without a colour
   change doing the shouting. */
.fx-pulse { animation: fx-pulse 2.4s ease-in-out infinite; }
@keyframes fx-pulse {
  0%, 100% { box-shadow: 0 0 0 0 var(--primary-glow); }
  50%      { box-shadow: 0 0 0 8px transparent; }
}

/* ══════════════════════════════════════════════════════════════════════════
   HEADINGS AND HERO TYPE
   ══════════════════════════════════════════════════════════════════════════ */
.fx-gradient-text {
  background: var(--grad-primary-h);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: var(--primary-strong);   /* the fallback that shows if text-fill is ignored */
}
/* The ramp above is palette-level and only points one way, so in the LIGHT theme it
   opens on --a-400 (#e5af7b in brown) — 1.8:1 clipped to glyphs on the light page.
   Light-only, same hue, --primary → --primary-strong: 4.9:1 at the head.
   Note background-IMAGE, not the `background` shorthand: the shorthand resets every
   longhand it omits, background-clip included, which turns the gradient from
   letter-shaped into a solid block sitting behind the words. That exact slip on
   .mph-grad is what made the home page headline read dark-on-dark. */
html.theme-light .fx-gradient-text {
  background-image: linear-gradient(135deg, var(--primary) 0%, var(--primary-strong) 100%);
  color: var(--primary-strong);
}

/* A green underline that draws itself under a section heading. */
.fx-underline { position: relative; }
.fx-underline::after {
  content: '';
  position: absolute;
  left: 0; bottom: -6px;
  height: 3px; width: 0;
  border-radius: 3px;
  background: var(--grad-primary-h);
  transition: width .6s var(--t-slow);
}
.fx-underline.fx-seen::after { width: 56px; }

/* ══════════════════════════════════════════════════════════════════════════
   THE TOGGLE
   ══════════════════════════════════════════════════════════════════════════ */
.theme-toggle-btn {
  position: relative;
  width: 38px; height: 38px;
  border-radius: 50%;
  border: 1px solid rgba(255,255,255,.14);
  background: rgba(255,255,255,.08);
  color: var(--header-ink);
  display: inline-flex; align-items: center; justify-content: center;
  transition: transform var(--t), background-color var(--t);
}
.theme-toggle-btn:hover { background: rgba(255,255,255,.16); transform: rotate(-18deg) scale(1.06); }
.theme-toggle-btn:active { transform: scale(.92); }
/* The whole page crossfades on the switch rather than snapping. Only colours
   are transitioned, and only for a moment — a permanent transition on * would
   make every hover on the site feel laggy. */
html.fx-theming, html.fx-theming * {
  transition: background-color .28s ease, color .28s ease, border-color .28s ease !important;
}

/* ── Search wrappers ──
   A card surface would be wrong here: these hold an inline form, not content, and
   giving them a shadow puts a raised slab in the middle of a toolbar. What they were
   missing is the thing every other input on the site has — a green ring when the
   field inside them takes focus. :focus-within is what carries it out to the box. */
.search-box, .searchbox, .search_bar, .mp-search-box {
  border-radius: var(--radius-pill);
  transition: box-shadow var(--t), border-color var(--t);
}
.search-box:focus-within, .searchbox:focus-within,
.search_bar:focus-within, .mp-search-box:focus-within {
  border-color: var(--primary);
  box-shadow: 0 0 0 3px var(--primary-glow);
}

/* ══════════════════════════════════════════════════════════════════════════
   W3.CSS BRIDGE
   The five Q&A pages — answers, quesans, quest_ctg, quest_search and
   trending_quest — are built on W3.CSS pulled from a w3schools.com CDN, and each
   one loaded a *different* accent file on top of it: black, brown, blue, pink and
   yellow. So the Q&A section was five colours, none of them the site's, and no
   amount of recolouring the templates could change it because the literals live
   in a remote stylesheet this project does not own.

   The accent files are gone from the templates now. W3.CSS itself stays, because
   its layout utilities are doing real work — w3-container, w3-row, w3-col,
   w3-padding, w3-round, 36 uses of the first alone — and reimplementing those to
   change a colour would be a rewrite in the wrong place. What is bridged here is
   only the part that carries colour.

   Everything below is !important, which is not the usual answer. W3.CSS declares
   `.w3-white{background-color:#fff!important}` and an override without the same
   weight loses no matter where it sits in the cascade or how specific it is.
   ══════════════════════════════════════════════════════════════════════════ */

/* The one surface class. Treated like every other card on the site, so a Q&A
   answer tile reads the same as a listing tile. */
.w3-card, .w3-card-2, .w3-card-4 {
  background-color: var(--surface) !important;
  background-image: var(--grad-surface);
  border: 1px solid var(--line) !important;
  border-radius: var(--radius);
  box-shadow: var(--ring), var(--e2) !important;
  transition: transform var(--t), border-color var(--t);
}
@media (hover: hover) and (pointer: fine) {
  .w3-card:hover, .w3-card-2:hover, .w3-card-4:hover {
    transform: translate3d(0, -4px, 0);
    border-color: var(--line-2) !important;
    box-shadow: var(--ring), var(--e3) !important;
  }
}

/* `w3-white` is on 29 of the 29 cards. Left alone it pins them to #fff, which is
   the single reason the Q&A pages stayed light in dark mode. */
.w3-white, .w3-light-grey, .w3-lightgrey {
  background-color: var(--surface) !important;
  color: var(--ink) !important;
}

/* The accent ramp. W3.CSS names these by distance from the theme colour — l5 is
   the palest, d1 and d2 the darkest — so they map onto the green scale directly
   rather than needing a decision per page. */
.w3-theme, .w3-theme-black, .w3-theme-brown, .w3-theme-blue,
.w3-theme-pink, .w3-theme-yellow {
  background-color: var(--primary) !important;
  color: var(--primary-ink) !important;
}
.w3-theme-l5 { background-color: var(--primary-wash) !important; color: var(--ink) !important; }
.w3-theme-l4 { background-color: var(--primary-soft) !important; color: var(--ink) !important; }
.w3-theme-l1 { background-color: var(--primary-bright) !important; color: var(--primary-ink) !important; }
.w3-theme-d1 { background-color: var(--primary-strong) !important; color: var(--primary-ink) !important; }
.w3-theme-d2 { background-color: var(--header) !important; color: var(--header-ink) !important; }
.w3-text-theme { color: var(--primary-strong) !important; }
.w3-border-theme { border-color: var(--primary) !important; }

.w3-border, .w3-bordered { border-color: var(--line) !important; }

/* Buttons and inputs, matched to the ones fx.css already restyles by element so a
   w3-button next to a bare <button> does not read as a different site. */
.w3-button:not(.w3-theme):not(.w3-theme-d1):not(.w3-theme-d2) {
  background-color: var(--surface-2) !important;
  color: var(--ink) !important;
  border-radius: var(--radius-pill);
  transition: background-color var(--t), color var(--t), transform var(--t-fast);
}
@media (hover: hover) and (pointer: fine) {
  .w3-button:hover {
    background-color: var(--primary) !important;
    color: var(--primary-ink) !important;
    transform: translate3d(0, -1px, 0);
  }
}
.w3-button:active { transform: translate3d(0, 0, 0) scale(.98); }

.w3-input {
  background-color: var(--surface) !important;
  color: var(--ink) !important;
  border-bottom: 1px solid var(--line) !important;
  transition: border-color var(--t), box-shadow var(--t);
}
.w3-input:focus {
  border-color: var(--primary) !important;
  box-shadow: 0 1px 0 var(--primary) !important;
  outline: none;
}

/* ══════════════════════════════════════════════════════════════════════════
   SITE CHROME
   The footer, the cookie strip and the install banner. All three used to carry
   their colours in inline style attributes, which is the one place a theme can
   never reach — they stayed navy and grey no matter what the rest of the page
   did. The markup now only says what each part is; the look is here.
   ══════════════════════════════════════════════════════════════════════════ */
.fx-footer {
  background-image: var(--grad-surface);
  background-color: var(--surface-2);
  border-top: 1px solid var(--line);
  padding: 26px 16px;
  margin-top: 40px;
  text-align: center;
  box-shadow: inset 0 1px 0 var(--surface);
}
.fx-footer-links {
  display: flex; flex-wrap: wrap; justify-content: center;
  gap: 20px; margin-bottom: 12px;
}
.fx-footer-links a {
  color: var(--ink-2);
  text-decoration: none;
  font-size: 14px; font-weight: 600;
  padding: 6px 10px;
  border-radius: var(--radius-pill);
  transition: color var(--t), background-color var(--t), transform var(--t-fast);
}
@media (hover: hover) and (pointer: fine) {
  .fx-footer-links a:hover {
    color: var(--primary-strong);
    background-color: var(--primary-wash);
    transform: translate3d(0, -1px, 0);
  }
}
.fx-footer-copy { color: var(--ink-3); font-size: 12px; margin-bottom: 4px; }
.fx-footer-note { color: var(--dim); font-size: 11px; }

/* The cookie strip. Dark in both themes on purpose — it sits over the page as a
   system message rather than as part of it, and a pale strip on a pale page just
   reads as content that failed to load. */
.fx-cookie {
  position: fixed; bottom: 0; left: 0; right: 0;
  z-index: 99999;
  display: flex; align-items: center; justify-content: space-between;
  flex-wrap: wrap; gap: 12px;
  padding: 16px 24px;
  background-image: var(--grad-header);
  background-color: var(--header);
  color: var(--header-ink);
  border-top: 1px solid rgba(255,255,255,.10);
  box-shadow: 0 -6px 26px rgba(3,20,11,.34);
  font-size: 14px; line-height: 1.5;
  animation: fx-cookie-up .45s var(--spring) both;
}
@keyframes fx-cookie-up { from { transform: translate3d(0, 100%, 0); } to { transform: none; } }
.fx-cookie-text { flex: 1 1 300px; min-width: 200px; }
.fx-cookie-text strong { font-size: 15px; }
.fx-cookie-text span { display: block; margin-top: 4px; color: var(--header-dim); }
/* --d-primary-bright, spelled out, in BOTH themes — the one place on the site where
   that is the right thing to write. This strip is deliberately dark in light mode too
   (see the note above it), so its ink has to come from the dark side of the palette
   whatever the theme is doing; a theme-following token gets it backwards exactly half
   the time. --accent-ink is theme-following, and its light face is --l-primary-strong,
   a dark-on-pale ink: on this dark strip it measured 2.04-2.22:1 across the nine
   palettes. (--accent, which was here before, was no better at 2.82-3.12 — this line
   has never passed.) --d-primary-bright is 8.29-10.75 here in light and 9.37-12.12 in
   dark. Raw --d-* tokens are palette DATA, defined in palette.css in both themes, so
   naming one is safe; --header-ink and --header-dim beside it work the same way. */
.fx-cookie-text a { color: var(--d-primary-bright); text-decoration: underline; }
.fx-cookie-actions { display: flex; gap: 10px; flex-shrink: 0; }
.fx-cookie .fx-btn, .fx-cookie .fx-btn-ghost {
  padding: 10px 20px; font-size: 14px; cursor: pointer;
}
.fx-cookie .fx-btn-ghost {
  background: transparent;
  color: var(--header-ink);
  border: 1px solid rgba(255,255,255,.28);
}
@media (hover: hover) and (pointer: fine) {
  .fx-cookie .fx-btn-ghost:hover {
    background: rgba(255,255,255,.10);
    border-color: rgba(255,255,255,.45);
    color: #fff;
  }
}

/* The install banner. */
.fx-pwa {
  position: fixed; bottom: 80px; left: 16px; right: 16px;
  z-index: 99998;
  max-width: 420px; margin: 0 auto;
  padding: 16px 20px;
  border-radius: var(--radius);
  background-image: var(--grad-header);
  background-color: var(--header);
  color: var(--header-ink);
  border: 1px solid rgba(255,255,255,.10);
  box-shadow: var(--e4);
  animation: fx-pop .3s var(--spring) both;
}
.fx-pwa-close {
  position: absolute; top: 8px; right: 12px;
  background: none; border: none;
  color: var(--header-dim);
  font-size: 18px; line-height: 1; padding: 4px;
  cursor: pointer;
  transition: color var(--t), transform var(--t-fast);
}
.fx-pwa-close:hover { color: #fff; transform: rotate(90deg); }
.fx-pwa-row { display: flex; align-items: center; gap: 14px; }
.fx-pwa-row img {
  width: 48px; height: 48px; flex-shrink: 0;
  border-radius: 12px;
  box-shadow: 0 2px 10px rgba(0,0,0,.3);
}
.fx-pwa-copy { flex: 1; min-width: 0; }
.fx-pwa-title { font-weight: 700; font-size: 15px; margin-bottom: 3px; }
.fx-pwa-sub { font-size: 12px; color: var(--header-dim); line-height: 1.35; }
.fx-pwa-cta {
  display: block; width: 100%;
  margin-top: 12px; padding: 12px;
  font-size: 15px;
  cursor: pointer;
}

/* ══════════════════════════════════════════════════════════════════════════
   APPEARANCE PICKER
   The one place the request asked for — "ek hi jagh se … dark light theme dono
   … bas mujhe colour select karna rahe". theme-fx.js drops a trigger beside
   every navbar quick-toggle, and a single floating one on pages that have no
   toggle at all; the trigger opens .fx-appear, the popover that carries both
   the light/dark switch and the five palette swatches.
   ══════════════════════════════════════════════════════════════════════════ */

/* The trigger. Beside a navbar toggle it borrows that button's look (the header
   is dark in both themes, so white-alpha reads right); as a FAB it floats over
   page content and takes a surface look instead. Either way it shows a dot in
   the live --primary, so the current colour is visible before the panel opens. */
.fx-appear-trigger {
  position: relative;
  width: 38px; height: 38px;
  padding: 0;
  border-radius: 50%;
  border: 1px solid rgba(255,255,255,.14);
  background: rgba(255,255,255,.08);
  display: inline-flex; align-items: center; justify-content: center;
  cursor: pointer;
  transition: transform var(--t), background-color var(--t);
}
.fx-appear-trigger:hover { background: rgba(255,255,255,.16); transform: scale(1.08); }
.fx-appear-trigger:active { transform: scale(.92); }
.fx-appear-dot {
  width: 18px; height: 18px;
  border-radius: 50%;
  background: linear-gradient(135deg, var(--primary-bright), var(--primary));
  box-shadow: 0 0 0 2px rgba(255,255,255,.18), inset 0 1px 1px rgba(255,255,255,.4);
}

/* FAB form — the whole appearance control on shells with no navbar slot.
   Positioned above the mobile tab bar so it never covers it. */
.fx-appear-fab {
  position: fixed; right: 14px; bottom: 76px; z-index: 9990;
  width: 44px; height: 44px;
  border: 1px solid var(--line);
  background: var(--surface);
  box-shadow: var(--e3);
}
.fx-appear-fab:hover { background: var(--surface); }
.fx-appear-fab .fx-appear-dot {
  width: 22px; height: 22px;
  box-shadow: 0 0 0 2px var(--line), inset 0 1px 1px rgba(255,255,255,.4);
}
@media (max-width: 900px) {
  .fx-appear-fab { bottom: 92px; }
}

/* The popover. JS sets its fixed left/top inline near the trigger; this styles
   the box and its open/close fade. */
.fx-appear {
  position: fixed; z-index: 9995;
  padding: 12px;
  border-radius: var(--radius-lg);
  border: 1px solid var(--line);
  background: var(--surface);
  box-shadow: var(--e4);
  display: flex; flex-direction: column; gap: 12px;
  min-width: 184px;
  opacity: 0; transform: translateY(-6px) scale(.98);
  transform-origin: top right;
  transition: opacity .16s ease, transform .16s ease;
}
.fx-appear.fx-appear-open { opacity: 1; transform: none; }

/* light / dark — two big targets, icon only (a sun and a moon translate
   themselves); the active one is ringed in the live --primary */
.fx-appear-modes { display: flex; gap: 8px; }
.fx-appear-mode {
  flex: 1;
  height: 40px;
  border-radius: 11px;
  border: 1px solid var(--line);
  background: var(--surface-2);
  color: var(--ink);
  font-size: 17px; line-height: 1;
  display: flex; align-items: center; justify-content: center;
  cursor: pointer;
  transition: transform var(--t), background-color var(--t), border-color var(--t), box-shadow var(--t);
}
.fx-appear-mode:hover { transform: translateY(-1px); }
.fx-appear-mode[aria-pressed="true"] {
  border-color: var(--primary);
  background: var(--primary-glow);
  color: var(--primary-strong);
  box-shadow: 0 0 0 2px var(--primary-glow);
}

/* the five palettes, each dot painted from its own --sw-*/--sw-*-2 preview
   stops in palette.css; the chosen one grows and takes a neutral ring so it
   reads against any colour */
.fx-appear-swatches { display: flex; gap: 10px; justify-content: space-between; }
.fx-swatch {
  width: 30px; height: 30px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: linear-gradient(135deg, var(--sw), var(--sw2));
  box-shadow: inset 0 1px 1px rgba(255,255,255,.35), 0 1px 2px rgba(0,0,0,.15);
  cursor: pointer;
  transition: transform var(--t), box-shadow var(--t);
}
.fx-swatch:hover { transform: scale(1.14); }
.fx-swatch[aria-pressed="true"] {
  transform: scale(1.14);
  box-shadow: 0 0 0 2px var(--surface), 0 0 0 4px var(--ink);
}

/* ══════════════════════════════════════════════════════════════════════════
   RESPECT
   Someone who has asked their system for less motion gets none of it. The
   shading, gradients and depth all stay — those are not motion.
   ══════════════════════════════════════════════════════════════════════════ */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }
  .fx-reveal { opacity: 1 !important; transform: none !important; }
  body::before, body::after { animation: none !important; }
  .fx-tilt-on { transform: none !important; }
}

/* Printing: no depth, no ground, no orbs, no leaves. */
@media print {
  body::before, body::after, .fx-leaves { display: none !important; }
  * { box-shadow: none !important; background-image: none !important; }
}
