/* ═══════════════════════════════════════════════════════════════════════════
   ONE COST RED — the single definition, repeated here because this site has
   no stylesheet that every page loads. Values are identical everywhere; see
   polish.css for why there are three of them.

     --cost-red           text on a LIGHT surface      4.5:1
     --cost-red-on-dark   text on a DARK surface       4.5:1
     --cost-red-bar-on-dark   a BAR on a dark surface  3:1 is the bar
                              it must clear, and the looser bar buys a
                              deeper, truer red than the text one.

   The two *-auto tokens pick the right member of that set from the theme,
   so a badge on a card that goes dark stays readable without every rule
   having to say so twice.
   ═══════════════════════════════════════════════════════════════════════════ */
:root{
  --cost-red:#B3261E;
  --cost-red-on-dark:#F0776B;
  --cost-red-bar-on-dark:#E54B3E;
  --cost-red-auto:#B3261E;
  --cost-red-bar-auto:#B3261E;
}
:root[data-theme="dark"]{
  --cost-red-auto:var(--cost-red-on-dark);
  --cost-red-bar-auto:var(--cost-red-bar-on-dark);
}

/* ═══════════════════════════════════════════════════════════════════════════
   PRODUCT STORIES — each card acts out what the product does
   ═══════════════════════════════════════════════════════════════════════════

   Eleven cards all carried the same furniture: a Font Awesome glyph in a
   rounded square, a hover lift, nothing else. A house, a car and an umbrella
   are the easiest things in finance to draw, and the page was spending none
   of that.

   Every card now has a scene that plays once, when the card is reached:

     Home Loan            three courses of brick rise, then the roof lands
     Loan Against Property the house stays put while coins leave it
     Personal Loan        a note passes into an open hand
     Business Loan        bars grow and the arrow breaks past the top
     Car Loan             a new car pulls away from standing
     Car Refinance        the car turns around and cash comes back
     Used Car Loan        an older car, a dent, and the key handed over
     Credit Card          two cards fan, the front one taps a terminal
     Life Insurance       a shield closes over three people, the plus beats
     Health Insurance     a pulse runs across and through the cross
     General Insurance    rain falls, the umbrella opens and stops it

   Rules that keep eleven animations from becoming a fairground:
     - each plays ONCE on arrival, never loops. A looping card competes with
       the reader for attention forever.
     - nothing starts until the card is actually on screen.
     - the whole set collapses to a static, finished frame under
       prefers-reduced-motion — every scene's resting state is its last
       frame, so stillness still reads correctly.
   ═══════════════════════════════════════════════════════════════════════════ */

.px-scene{
  display:block;
  width:100%;
  margin:2px 0 14px;
  color:var(--brand-green,#1FA463);
}
.px-scene svg{width:100%;height:auto;max-height:76px;display:block;overflow:visible;}
[data-theme="dark"] .px-scene{color:#5FD9A0;}

/* The card keeps its own icon badge; the scene sits under it as the card's
   picture. On the gold insurance cards the stroke follows their accent. */
.prodx-card--gold .px-scene{color:#B8860B;}
[data-theme="dark"] .prodx-card--gold .px-scene{color:#E8B04B;}

/* ── How a scene runs ──────────────────────────────────────────────────
   Two classes, set by product-stories.js, and they mean different things.

   .px-go    the card has been reached once. Before it, every scene rests
             at its finished frame, which is also what a reduced-motion
             reader, a print view and a link preview get.
   .px-live  the card is on screen RIGHT NOW. Only then do the loops run.

   Every story below is one 3-second bar, looping for as long as the card
   is in view. The beats are written as percentages of that bar rather
   than as animation-delays, so eleven elements in a scene stay in step
   with each other forever instead of drifting apart.

   A loop that keeps running behind a reader who has scrolled past it is
   noise they cannot see and a battery they still pay for — which is why
   .px-live is removed as readily as it is added. On screen it never
   stops; off screen it never runs.                                      */

/* ── Shared ──────────────────────────────────────────────────────────── */
.px-ground,.px-road{opacity:.35;}
.px-scene svg g,.px-scene svg path,.px-scene svg rect,.px-scene svg circle{
  transform-box:fill-box;transform-origin:center;
}

/* The card itself breathes as it crosses the screen — bigger as it comes
   to rest in the middle, smaller as it leaves. This uses the `scale`
   property, not `transform`, because .prodx-card:hover already owns
   transform (translateY(-6px)) and the two would cancel each other.
   Without JS the fallback resolves to exactly 1. */
/* Measured through a real scroll, the previous range moved the card by
   under 4% end to end, which is not a zoom anybody can see. This is 9%:
   .94 out at the edges, 1.03 at rest in the middle.
   The .667 fallback is not arbitrary — it is the value that resolves to
   exactly 1.0, so a card renders at its natural size in the instant
   before the observer first writes --px-z, and if JS never runs. */
.prodx-card{scale:calc(.94 + .09 * var(--px-z, .667));}

/* The product's NAME carries the zoom, which is what was actually asked
   for: scaling the card alone moved the whole block a few percent and
   read as nothing. The name scales on top of the card, so "Home Loan"
   travels about 22% end to end while the card travels 9%.
   Origin is the left edge on both, because these sit in left-aligned
   text: growing from the centre would walk the first letter in and out
   of the card's padding and read as a layout bug.
   The fallbacks (.727, .75) are the values that resolve to exactly 1, so
   nothing is mis-sized before the first scroll frame or without JS. */
.prodx-name{transform-origin:left center;scale:calc(.92 + .11 * var(--px-z, .727));}
/* The section heading does NOT get the scroll-linked scale the cards
   get. A heading sits at the TOP of its section, so it never reaches
   the middle of the screen — measured, its --px-z peaked at 0.078,
   which left "Our Products" rendered at 0.88 permanently and simply
   looked like a styling mistake. It gets an entrance instead: one
   zoom as it arrives, then it rests at full size. */
.prodx-head{transform-origin:left center;}
.prodx-title,.prodx-eyebrow,.prodx-sub{transform-origin:left center;}
.prodx-head.px-in .prodx-eyebrow{animation:prodx-rise .5s cubic-bezier(.2,.8,.3,1.05) both;}
.prodx-head.px-in .prodx-title{animation:prodx-zoom .66s cubic-bezier(.2,.8,.3,1.08) .06s both;}
.prodx-head.px-in .prodx-sub{animation:prodx-rise .5s cubic-bezier(.2,.8,.3,1.05) .18s both;}
@keyframes prodx-zoom{from{opacity:0;scale:.86;translate:0 10px}to{opacity:1;scale:1;translate:0 0}}
@keyframes prodx-rise{from{opacity:0;translate:0 8px}to{opacity:1;translate:0 0}}
@media (prefers-reduced-motion:reduce){
  .prodx-name,.prodx-title{scale:1;}
  .prodx-head.px-in *{animation:none !important;opacity:1;}
}
@media (prefers-reduced-motion:reduce){.prodx-card{scale:1;}}

@keyframes px-draw{to{stroke-dashoffset:0}}
@keyframes px-spin{to{transform:rotate(360deg)}}
/* The things that are simply PRESENT for the whole story — the wallet
   the notes fall into, the building the new floor lands on, the car
   being refinanced. They come in at the top of the bar, hold, and
   leave with everything else. A plain 0-to-1 fade across 3s is not
   this: it leaves the object half-transparent for most of the loop,
   which is what it did before this keyframe existed. */
@keyframes px-hold{0%{opacity:0}6%,92%{opacity:1}100%{opacity:0}}

/* ── 1. Home Loan — it is built, then it is yours ─────────────────────
   Three courses of brick, the roof, the door. Then the key arrives and
   turns, and the door swings open: the moment the loan is actually for. */
.px-go.px-live .px-brick{animation:px-hl-brick 3s cubic-bezier(.2,.8,.3,1.1) infinite;}
.px-go.px-live .px-b1{animation-delay:0s}
.px-go.px-live .px-b2{animation-delay:0.13s}
.px-go.px-live .px-b3{animation-delay:0.26s}
.px-go.px-live .px-roof{animation:px-hl-roof 3s cubic-bezier(.2,.9,.3,1.1) .41s infinite;}
.px-go.px-live .px-door{transform-origin:left center;animation:px-hl-door 3s cubic-bezier(.4,0,.3,1) infinite;}
.px-go.px-live .px-key{animation:px-hl-key 3s cubic-bezier(.3,.7,.3,1) infinite;}
@keyframes px-hl-brick{
  0%{opacity:0;transform:translateY(12px)}
  7%,88%{opacity:1;transform:translateY(0)}
  96%,100%{opacity:0;transform:translateY(12px)}}
@keyframes px-hl-roof{
  0%{opacity:0;transform:translateY(-18px)}
  7%,82%{opacity:1;transform:translateY(0)}
  92%,100%{opacity:0;transform:translateY(-18px)}}
@keyframes px-hl-door{
  0%,20%{opacity:0;transform:scaleX(1)}
  27%,50%{opacity:1;transform:scaleX(1)}
  60%,86%{opacity:1;transform:scaleX(.1)}   /* the gate opens */
  95%{opacity:1;transform:scaleX(1)}
  100%{opacity:0;transform:scaleX(1)}}
/* The key stops BESIDE the door, not on it. Landing it over the door
   put one set of strokes across another in the same colour and the
   whole corner turned to mush — the turn was invisible. Held clear of
   the wall at door height it reads at a glance, and the door swinging
   on the next beat says the rest. */
@keyframes px-hl-key{
  0%,30%{opacity:0;transform:translate(22px,-14px) rotate(-30deg)}
  42%,50%{opacity:1;transform:translate(-2px,12px) rotate(0deg)}
  58%,76%{opacity:1;transform:translate(-2px,12px) rotate(100deg)}  /* turns */
  88%,100%{opacity:0;transform:translate(14px,4px) rotate(100deg)}}

/* ── 2. Loan Against Property — the house you already own, built onto ──
   The base house never leaves; what the loan adds is the floor on top,
   raised under a crane, and the money that comes out of it. */
.px-go.px-live .px-lap-base{animation:px-hold 3s linear infinite;}
.px-go.px-live .px-lap-crane{animation:px-lap-crane 3s ease infinite;}
.px-go.px-live .px-lap-new{transform-origin:center bottom;animation:px-lap-floor 3s cubic-bezier(.2,.8,.3,1.08) infinite;}
.px-go.px-live .px-coin{animation:px-lap-coin 3s cubic-bezier(.2,.8,.3,1.05) infinite;}
.px-go.px-live .px-c2{animation-delay:0.19s}
@keyframes px-lap-crane{
  0%,6%{opacity:0}14%,80%{opacity:.5}92%,100%{opacity:0}}
@keyframes px-lap-floor{
  0%,20%{opacity:0;transform:translateY(18px) scaleY(.15)}
  36%,86%{opacity:1;transform:translateY(0) scaleY(1)}
  96%,100%{opacity:0;transform:translateY(18px) scaleY(.15)}}
@keyframes px-lap-coin{
  0%,46%{opacity:0;transform:translate(-16px,16px) scale(.5)}
  60%,78%{opacity:1;transform:translate(0,0) scale(1)}
  90%,100%{opacity:0;transform:translate(8px,-12px) scale(.85)}}

/* ── 3. Personal Loan — money in your pocket, then it is closed ───────
   Notes fall in one after another and the flap folds over them. The fold
   is a real fold: scaleY(-1) about the hinge line mirrors the flap down
   across the wallet body. */
.px-go.px-live .px-wallet{animation:px-hold 3s linear infinite;}
.px-go.px-live .px-flap{transform-origin:50% 100%;animation:px-pl-flap 3s cubic-bezier(.4,0,.3,1) infinite;}
.px-go.px-live .px-note{animation:px-pl-note 3s cubic-bezier(.4,0,.5,1) infinite;}
.px-go.px-live .px-n1{animation-delay:0s}
.px-go.px-live .px-n2{animation-delay:0.24s}
.px-go.px-live .px-n3{animation-delay:0.47s}
@keyframes px-pl-flap{
  0%,4%{opacity:0;transform:scaleY(1)}
  11%,58%{opacity:1;transform:scaleY(1)}
  70%,88%{opacity:1;transform:scaleY(-1)}   /* snaps shut */
  96%{opacity:1;transform:scaleY(1)}
  100%{opacity:0;transform:scaleY(1)}}
@keyframes px-pl-note{
  0%,5%{opacity:0;transform:translateY(-12px) rotate(-10deg)}
  12%{opacity:1;transform:translateY(-2px) rotate(-6deg)}
  30%{opacity:1;transform:translateY(28px) rotate(4deg)}
  37%,100%{opacity:0;transform:translateY(36px) rotate(6deg)}}

/* ── 4. Business Loan — one becomes two, and the machines run ─────────
   The gear is the only thing here on its own clock. Machinery that stops
   to wait for a 3-second bar is machinery that is switched off, so it
   turns continuously for as long as the card is on screen. */
.px-go.px-live .px-bl-b1{transform-origin:center bottom;animation:px-bl-rise 3s cubic-bezier(.2,.8,.3,1.08) infinite;}
.px-go.px-live .px-bl-b2{transform-origin:center bottom;animation:px-bl-rise 3s cubic-bezier(.2,.8,.3,1.08) .36s infinite;}
.px-go.px-live .px-gear{animation:px-spin 4.5s linear infinite,px-hold 3s linear infinite;}
@keyframes px-bl-rise{
  0%{opacity:0;transform:translateY(10px) scaleY(.1)}
  14%,84%{opacity:1;transform:translateY(0) scaleY(1)}
  95%,100%{opacity:0;transform:translateY(10px) scaleY(.1)}}

/* ── 5. Car Loan — fast, and the road goes past ───────────────────────
   The trees carry the speed. They run on a 2.3-second loop of their own,
   staggered, so the scenery never stops arriving while the car is there. */
.px-go.px-live .px-fast{animation:px-cl-car 3s cubic-bezier(.3,0,.4,1) infinite;}
.px-go.px-live .px-fast .px-wheel{animation:px-spin .42s linear infinite;}
.px-go.px-live .px-tree{animation:px-cl-tree 2.3s linear infinite;}
.px-go.px-live .px-t2{animation-delay:1.15s}
.px-go.px-live .px-speed{animation:px-cl-speed .75s linear infinite;}
.px-go.px-live .px-s2{animation-delay:.3s}
@keyframes px-cl-car{
  0%{opacity:0;transform:translateX(-54px)}
  14%,78%{opacity:1;transform:translateX(0)}
  96%,100%{opacity:0;transform:translateX(60px)}}
@keyframes px-cl-tree{
  0%{opacity:0;transform:translateX(126px)}
  12%,84%{opacity:.22}
  100%{opacity:0;transform:translateX(-16px)}}
@keyframes px-cl-speed{
  0%{opacity:0;transform:translateX(12px)}
  40%{opacity:.55}
  100%{opacity:0;transform:translateX(-18px)}}

/* ── 6. Car Refinance — the key comes back to you, and so does cash ───
   Wheels deliberately still. Nothing is being driven here; a loan is
   being replaced, and what moves is the money. */
.px-go.px-live .px-parked{animation:px-hold 3s linear infinite;}
.px-go.px-live .px-rf-key{animation:px-rf-key 3s cubic-bezier(.2,.8,.3,1.05) infinite;}
.px-go.px-live .px-cash{animation:px-rf-cash 3s cubic-bezier(.2,.8,.3,1.05) infinite;}
.px-go.px-live .px-k2{animation-delay:0.21s}
.px-go.px-live .px-rf-down{animation:px-rf-down 3s ease-in-out infinite;}
@keyframes px-rf-down{
  0%,20%{opacity:0;transform:translateY(-7px)}
  38%,72%{opacity:.85;transform:translateY(0)}
  88%,100%{opacity:0;transform:translateY(7px)}}
@keyframes px-rf-key{
  0%,16%{opacity:0;transform:translate(22px,-12px) rotate(-26deg)}
  30%,56%{opacity:1;transform:translate(0,0) rotate(0deg)}
  70%,100%{opacity:0;transform:translate(-10px,8px) rotate(10deg)}}
@keyframes px-rf-cash{
  0%,14%{opacity:0;transform:translate(-26px,9px) scale(.5)}
  30%,74%{opacity:1;transform:translate(0,0) scale(1)}
  88%,100%{opacity:0;transform:translate(14px,-13px) scale(.85)}}

/* ── 7. Used Car Loan — it takes two turns to catch ───────────────────
   Everything here is slower than the new-car scene on purpose: the wheel
   spin is four times the period, and the ignition misses once before it
   fires. The smoke is what an older engine does on a cold start. */
.px-go.px-live .px-slow{animation:px-uc-car 3s cubic-bezier(.4,0,.5,1) infinite;}
.px-go.px-live .px-wheel-slow{animation:px-spin 1.3s linear infinite;}
.px-go.px-live .px-uc-key{animation:px-uc-key 3s cubic-bezier(.3,.7,.3,1) infinite;}
.px-go.px-live .px-smoke{animation:px-uc-smoke 1.35s ease-out infinite;}
.px-go.px-live .px-m2{animation-delay:.42s}
.px-go.px-live .px-m3{animation-delay:.84s}
@keyframes px-uc-car{
  0%{opacity:0;transform:translateX(-32px)}
  18%,44%{opacity:1;transform:translateX(0)}
  46%{transform:translateX(-1.6px)}         /* the shudder of not starting */
  48%{transform:translateX(1.6px)}
  50%{transform:translateX(-1.4px)}
  52%{transform:translateX(1px)}
  55%{transform:translateX(0)}
  86%{opacity:1;transform:translateX(26px)}
  97%,100%{opacity:0;transform:translateX(40px)}}
@keyframes px-uc-key{
  0%,18%{opacity:0;transform:translate(16px,-10px) rotate(-20deg)}
  30%,42%{opacity:1;transform:translate(0,0) rotate(0deg)}
  47%{opacity:1;transform:translate(0,0) rotate(85deg)}   /* turn */
  52%{opacity:1;transform:translate(0,0) rotate(35deg)}   /* it dies */
  58%,78%{opacity:1;transform:translate(0,0) rotate(85deg)}  /* and again */
  90%,100%{opacity:0;transform:translate(10px,-8px) rotate(85deg)}}
@keyframes px-uc-smoke{
  0%{opacity:0;transform:translate(9px,3px) scale(.45)}
  28%{opacity:.5}
  100%{opacity:0;transform:translate(-13px,-11px) scale(1.5)}}

/* ── 8. Credit Card — tap, and it goes through ────────────────────────
   The card reaches the terminal, bumps it once, two rings leave the
   contactless mark, and the terminal ticks. Then the card comes back:
   the whole point of a tap is that you keep hold of it. */
.px-go.px-live .px-cc-card{animation:px-cc-card 3s cubic-bezier(.3,.7,.3,1) infinite;}
.px-go.px-live .px-term{animation:px-cc-term 3s linear infinite;}
.px-go.px-live .px-wave{stroke-dasharray:17;animation:px-cc-wave 3s ease-out infinite;}
.px-go.px-live .px-w2{animation-delay:0.15s}
.px-go.px-live .px-tick{stroke-dasharray:18;animation:px-cc-tick 3s ease infinite;}
@keyframes px-cc-card{
  0%{opacity:0;transform:translate(-28px,8px) rotate(-8deg)}
  13%{opacity:1;transform:translate(0,0) rotate(0deg)}
  26%{transform:translate(14px,-2px) rotate(-3deg)}
  31%{transform:translate(19px,-2px) rotate(-3deg)}   /* the tap */
  36%,64%{transform:translate(14px,-2px) rotate(-3deg)}
  80%{opacity:1;transform:translate(0,0) rotate(0deg)}
  95%,100%{opacity:0;transform:translate(-28px,8px) rotate(-8deg)}}
@keyframes px-cc-term{0%,4%{opacity:0}12%,88%{opacity:1}97%,100%{opacity:0}}
@keyframes px-cc-wave{
  0%,32%{opacity:0;stroke-dashoffset:17}
  41%{opacity:1;stroke-dashoffset:0}
  58%{opacity:.2;stroke-dashoffset:0}
  62%,100%{opacity:0;stroke-dashoffset:17}}
@keyframes px-cc-tick{
  0%,44%{opacity:0;stroke-dashoffset:18}
  57%,82%{opacity:1;stroke-dashoffset:0}
  92%,100%{opacity:0;stroke-dashoffset:18}}

/* ── 9-11. Insurance — cover is not a one-off, so it re-validates ─────
   The three insurance scenes were asked to keep re-checking themselves
   rather than finish, which is exactly what a policy does: the shield is
   redrawn, the heart does not stop, the rain keeps coming and the canopy
   keeps holding it. */
.px-go.px-live .px-shield{stroke-dasharray:178;animation:px-ins-shield 3s ease infinite;}
.px-go.px-live .px-plus{animation:px-ins-plus 1.8s ease-in-out infinite;}
.px-go.px-live .px-kin{animation:px-ins-kin 3s cubic-bezier(.2,.8,.3,1.1) infinite;}
.px-go.px-live .px-kin.px-k2{animation-delay:0.08s}
.px-go.px-live .px-kin.px-k3{animation-delay:0.15s}
@keyframes px-ins-shield{
  0%{opacity:0;stroke-dashoffset:178}
  18%,86%{opacity:1;stroke-dashoffset:0}
  97%,100%{opacity:0;stroke-dashoffset:178}}
@keyframes px-ins-plus{
  0%,100%{transform:scale(1)}
  45%{transform:scale(1.14)}}
@keyframes px-ins-kin{
  0%,14%{opacity:0;transform:translateY(10px)}
  24%,84%{opacity:1;transform:translateY(0)}
  95%,100%{opacity:0;transform:translateY(10px)}}

/* Health — the ECG sweeps on its own 3.4s clock so the trace is always
   arriving, while the heart keeps its own lub-DUB rhythm underneath. */
.px-go.px-live .px-ecg{
  stroke-dasharray:142;
  animation:px-hi-ecg 3.4s linear infinite;
}
.px-go.px-live .px-heart{
  transform-origin:60px 30px;transform-box:view-box;
  animation:px-beat .95s ease-in-out infinite;
}
.px-go.px-live .px-heart-shape{stroke-dasharray:none;stroke-dashoffset:0;}
@keyframes px-hi-ecg{
  0%{stroke-dashoffset:142;opacity:0}
  10%{opacity:.9}
  62%{stroke-dashoffset:0;opacity:.9}
  88%{stroke-dashoffset:0;opacity:.3}
  100%{stroke-dashoffset:0;opacity:0}}
/* A heart goes lub-DUB: two contractions close together, then a longer
   rest. One pulse per cycle reads as a throb, not a heartbeat. */
@keyframes px-beat{
  0%{transform:scale(1)}
  7%{transform:scale(1.15)}    /* lub */
  15%{transform:scale(1.01)}
  23%{transform:scale(1.10)}   /* DUB */
  34%,100%{transform:scale(1)}}

/* General — rain on a 1.4s loop, four drops out of phase. */
.px-go.px-live .px-rain{animation:px-gi-rain 1.4s ease-in infinite;}
.px-go.px-live .px-r2{animation-delay:.35s}
.px-go.px-live .px-r3{animation-delay:.7s}
.px-go.px-live .px-r4{animation-delay:1.05s}
.px-go.px-live .px-brolly{stroke-dasharray:188;animation:px-gi-brolly 3s ease infinite;}
.px-go.px-live .px-brolly-stem{animation:px-gi-stem 3s linear infinite;}
@keyframes px-gi-rain{
  0%{opacity:0;transform:translateY(-12px)}
  30%{opacity:.85}
  100%{opacity:0;transform:translateY(16px)}}
@keyframes px-gi-brolly{
  0%{opacity:0;stroke-dashoffset:188}
  20%,86%{opacity:1;stroke-dashoffset:0}
  97%,100%{opacity:0;stroke-dashoffset:188}}
@keyframes px-gi-stem{0%,16%{opacity:0}26%,86%{opacity:1}97%,100%{opacity:0}}

/* ── Stillness is a finished frame, not a blank one ───────────────────
   Two readers never see a loop: someone who has asked for reduced
   motion, and anyone looking at a card before it has been reached —
   which includes a link preview and a print. Left alone they would get
   the raw drawing, where banknotes hang in mid-air above a wallet that
   never closes, because those positions only make sense mid-flight.

   So the still frame is composed deliberately: the story at its end.
   House built and unlocked, wallet shut, no exhaust and no speed lines
   on a car that is not moving. Everything in flight is simply not
   there.                                                              */
.px-scene:not(.px-go) .px-note,.px-scene:not(.px-go) .px-smoke,
.px-scene:not(.px-go) .px-speed,.px-scene:not(.px-go) .px-cash,
.px-scene:not(.px-go) .px-tree{opacity:0;}
.px-scene:not(.px-go) .px-door{transform:scaleX(.1);transform-origin:left center;}
.px-scene:not(.px-go) .px-flap{transform:scaleY(-1);transform-origin:50% 100%;}

@media (prefers-reduced-motion:reduce){
  .px-go *,.px-go.px-live *{animation:none !important;}
  .px-scene [stroke-dasharray]{stroke-dasharray:none !important;stroke-dashoffset:0 !important;}
  .px-scene .px-note,.px-scene .px-smoke,.px-scene .px-speed,
  .px-scene .px-cash,.px-scene .px-tree{opacity:0;}
  .px-scene .px-door{transform:scaleX(.1);transform-origin:left center;}
  .px-scene .px-flap{transform:scaleY(-1);transform-origin:50% 100%;}
}

/* ═══════════════════════════════════════════════════════════════════════════
   COST, EVERYWHERE — one class, one colour, one meaning
   ═══════════════════════════════════════════════════════════════════════════

   Interest and tax are money that leaves. Across the six calculators they
   were showing up in three different colours — gold for the EMI calculator's
   total interest, brand green for the new tax regime, a stray #ff3b30 for
   the old one — and brand green is the colour this site uses for money the
   customer KEEPS. A reader scanning two screens learned opposite things from
   the same kind of number.

   var(--cost-red-auto, #B3261E) is the same red as the rate spread, the repayment split bar and
   the loan explainer, so "this is what it costs you" now looks identical
   wherever it appears. A saving stays green, because a saving is not a cost:
   the part-payment figure is deliberately left alone.

   The tax screen loses nothing by having both regimes red. Which one is
   cheaper is the recommendation banner's job, and it says so in words —
   colour was doing that work twice and contradicting itself once.
   ═══════════════════════════════════════════════════════════════════════════ */

.is-cost,
.is-cost i { color: var(--cost-red-auto, #B3261E) !important; }
[data-theme="dark"] .is-cost,
[data-theme="dark"] .is-cost i { color: #F0776B !important; }

/* ═══════════════════════════════════════════════════════════════════════════
   THE ELIGIBILITY GATE — a running list of what is still missing
   ═══════════════════════════════════════════════════════════════════════════

   Same discipline as the dashboard: amber while something is outstanding,
   green only when the form can actually produce a true answer. The list is
   not a warning — it is the shortest path to the result — so it reads as a
   checklist rather than an error.
   ═══════════════════════════════════════════════════════════════════════════ */

.eg-panel{
  max-width:800px;
  margin:26px auto -6px;
  padding:16px 18px 18px;
  border-radius:16px;
  border:1px solid rgba(184,110,10,.28);
  background:rgba(243,167,18,.08);
}
.eg-panel.is-ready{
  border-color:rgba(31,164,99,.3);
  background:rgba(31,164,99,.08);
}
.eg-k{
  margin:0 0 5px;font-size:14.5px;font-weight:800;
  color:#8A5207;display:flex;align-items:center;gap:8px;
}
.eg-panel.is-ready .eg-k{color:var(--brand-green,#0E7C4A);}
.eg-tick{
  display:inline-flex;align-items:center;justify-content:center;
  width:19px;height:19px;border-radius:50%;
  background:var(--brand-green,#1FA463);color:#fff;font-size:11px;font-weight:900;
}
.eg-v{margin:0;font-size:12.5px;line-height:1.6;color:var(--text-muted,#5b6b63);max-width:62ch;}

.eg-list{
  list-style:none;margin:13px 0 0;padding:0;
  display:flex;flex-wrap:wrap;gap:8px;
}
.eg-jump{
  appearance:none;cursor:pointer;
  border:1px solid rgba(184,110,10,.34);
  background:#fff;color:#8A5207;
  font:700 12.5px/1 var(--font-sans),sans-serif;
  min-height:38px;padding:0 13px;border-radius:19px;
  display:inline-flex;align-items:center;gap:7px;
  touch-action:manipulation;-webkit-tap-highlight-color:transparent;
  transition:background .2s ease, transform .18s cubic-bezier(.2,.8,.3,1.1);
}
.eg-jump::before{content:"+";font-size:15px;font-weight:900;opacity:.6;}
.eg-jump:hover{background:rgba(243,167,18,.14);}
.eg-jump:active{transform:scale(.97);}
.eg-jump:focus-visible{outline:3px solid #B86E0A;outline-offset:3px;}

.eg-pre{
  margin:12px 0 0;font-size:11.5px;line-height:1.55;
  color:var(--text-muted,#5b6b63);font-style:italic;
}

/* A field we filled from their own profile, so it is obvious what came from
   us and what they typed. */
.eg-prefilled{
  background:rgba(31,164,99,.06) !important;
  border-color:rgba(31,164,99,.3) !important;
}
/* Where the list sends you. */
.eg-flash{
  animation:eg-flash 1.2s ease both;
}
@keyframes eg-flash{
  0%,100%{box-shadow:0 0 0 0 rgba(243,167,18,0)}
  25%{box-shadow:0 0 0 4px rgba(243,167,18,.35)}
  60%{box-shadow:0 0 0 4px rgba(243,167,18,.35)}
}

[data-theme="dark"] .eg-panel{border-color:rgba(232,176,75,.3);background:rgba(232,176,75,.1);}
[data-theme="dark"] .eg-panel.is-ready{border-color:rgba(24,201,121,.3);background:rgba(24,201,121,.1);}
[data-theme="dark"] .eg-k{color:#E8B04B;}
[data-theme="dark"] .eg-panel.is-ready .eg-k{color:#5FD9A0;}
[data-theme="dark"] .eg-jump{background:rgba(255,255,255,.05);color:#E8B04B;border-color:rgba(232,176,75,.34);}

@media (prefers-reduced-motion:reduce){
  .eg-jump{transition:none;}
  .eg-flash{animation:none;}
}

/* ═══════════════════════════════════════════════════════════════════════════
   BALANCE TRANSFER — the worth-it block
   ═══════════════════════════════════════════════════════════════════════════

   Three stats and a verdict that changes colour with the answer. The verdict
   is allowed to say "do not switch" in red, because on this screen that is
   the most valuable thing the page can tell someone.
   ═══════════════════════════════════════════════════════════════════════════ */

.btv{
  margin-top:20px;padding-top:20px;
  border-top:1px solid rgba(8,92,58,.14);
}
.btv-head h4{margin:0 0 5px;font-size:15px;font-weight:800;color:var(--text-color);}
.btv-head p{margin:0 0 14px;font-size:12.5px;line-height:1.6;color:var(--text-muted);max-width:58ch;}
.btv-rbi{
  margin:6px 0 16px;padding:10px 12px;border-radius:10px;
  background:rgba(31,164,99,.07);border:1px solid rgba(31,164,99,.2);
  font-size:11.5px;line-height:1.6;color:var(--text-muted);
}

.btv-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:10px;margin-bottom:14px;}
@media(max-width:520px){ .btv-grid{grid-template-columns:1fr;} }
.btv-stat{
  padding:12px;border-radius:12px;
  background:rgba(8,92,58,.04);border:1px solid rgba(8,92,58,.1);
  display:grid;gap:3px;
}
.btv-lbl{font-size:10.5px;font-weight:700;letter-spacing:.6px;text-transform:uppercase;color:var(--text-muted);}
.btv-val{font-size:19px;font-weight:800;color:var(--text-color);font-variant-numeric:tabular-nums;}
.btv-val.is-good{color:var(--brand-green,#0E7C4A);}
.btv-stat small{font-size:10.5px;line-height:1.45;color:var(--text-muted);}

.btv-verdict{
  padding:14px 15px;border-radius:12px;
  border:1px solid rgba(8,92,58,.14);background:rgba(8,92,58,.04);
  font-size:13px;line-height:1.6;color:var(--text-color);
}
.btv-verdict p{margin:0 0 8px;}
.btv-verdict p:last-child{margin:0;}
.btv-verdict.is-good{border-color:rgba(31,164,99,.3);background:rgba(31,164,99,.08);}
.btv-verdict.is-warn{border-color:rgba(184,110,10,.3);background:rgba(243,167,18,.09);}
.btv-verdict.is-bad {border-color:rgba(179,38,30,.3); background:rgba(179,38,30,.07);}

/* ── NDI ─────────────────────────────────────────────────────────────── */
.btv-ndi{margin-top:16px;}
.btv-ndi-k{margin:0 0 10px;font-size:12px;font-weight:800;letter-spacing:.5px;text-transform:uppercase;color:var(--text-muted);}
.btv-ndi-row{display:grid;grid-template-columns:48px 1fr auto;align-items:center;gap:10px;margin-bottom:8px;font-size:11.5px;color:var(--text-muted);}
.btv-ndi-bar{height:12px;border-radius:6px;background:rgba(8,92,58,.1);overflow:hidden;}
.btv-ndi-bar i{
  display:block;height:100%;width:0;border-radius:6px;background:var(--cost-red-bar-auto, #B3261E);
  transition:width .3s cubic-bezier(.2,.7,.2,1);
}
.btv-ndi-bar i.is-good{background:var(--brand-green,#1FA463);}
.btv-ndi-row b{font-size:12px;font-weight:800;color:var(--text-color);font-variant-numeric:tabular-nums;}
.btv-ndi-note{margin:8px 0 0;font-size:12px;line-height:1.6;color:var(--text-color);font-weight:600;}
.btv-ndi-ask{margin:14px 0 0;font-size:11.5px;line-height:1.55;color:var(--text-muted);font-style:italic;}

[data-theme="dark"] .btv{border-top-color:rgba(255,255,255,.1);}
[data-theme="dark"] .btv-stat{background:rgba(255,255,255,.04);border-color:rgba(255,255,255,.08);}
[data-theme="dark"] .btv-verdict{background:rgba(255,255,255,.04);border-color:rgba(255,255,255,.1);}
[data-theme="dark"] .btv-ndi-bar{background:rgba(255,255,255,.1);}

@media (prefers-reduced-motion:reduce){ .btv-ndi-bar i{transition:none;} }

/* ═══════════════════════════════════════════════════════════════════════════
   COMPANY MATCH — autocomplete on the employer, no category question
   ═══════════════════════════════════════════════════════════════════════════ */

.cmx-wrap{position:relative;}
.cmx-list{
  position:absolute;left:0;right:0;top:calc(100% + 6px);z-index:40;
  max-height:264px;overflow:auto;
  background:var(--card-bg,#fff);
  border:1px solid rgba(8,92,58,.18);
  border-radius:12px;
  box-shadow:0 14px 34px rgba(8,92,58,.14);
  padding:5px;
}
.cmx-opt{
  display:block;width:100%;text-align:left;
  appearance:none;border:0;background:none;cursor:pointer;
  padding:10px 11px;border-radius:9px;
  font-size:13px;line-height:1.35;color:var(--text-color);
  touch-action:manipulation;
}
.cmx-opt:hover,.cmx-opt.is-on{background:rgba(31,164,99,.11);}
.cmx-empty{padding:12px;font-size:12px;line-height:1.55;color:var(--text-muted);}

.cmx-note{
  margin:8px 0 0;padding:10px 12px;border-radius:10px;
  font-size:11.5px;line-height:1.6;
  background:rgba(8,92,58,.05);border:1px solid rgba(8,92,58,.12);
  color:var(--text-muted);
}
.cmx-note.is-ok{background:rgba(31,164,99,.08);border-color:rgba(31,164,99,.24);}
.cmx-note.is-warn{background:rgba(243,167,18,.09);border-color:rgba(184,110,10,.26);}
.cmx-note strong{color:var(--brand-green,#0E7C4A);}

/* The employer-category question, retired. Kept in the DOM because other
   code reads its value; taken off the screen because asking a customer to
   grade their own employer is asking them to guess. */
.cmx-retired{
  position:absolute !important;
  width:1px;height:1px;overflow:hidden;
  clip:rect(0 0 0 0);clip-path:inset(50%);
  white-space:nowrap;
}

[data-theme="dark"] .cmx-list{background:#16211c;border-color:rgba(255,255,255,.12);}
[data-theme="dark"] .cmx-opt{color:#eef5f0;}
[data-theme="dark"] .cmx-opt:hover,[data-theme="dark"] .cmx-opt.is-on{background:rgba(24,201,121,.16);}
[data-theme="dark"] .cmx-note{background:rgba(255,255,255,.05);border-color:rgba(255,255,255,.1);}

/* ═══════════════════════════════════════════════════════════════════════════
   IDENTITY — what came from the account, and what is already proven
   ═══════════════════════════════════════════════════════════════════════════ */

.idx-filled{
  background:rgba(31,164,99,.06) !important;
  border-color:rgba(31,164,99,.3) !important;
}
.idx-badge{
  display:flex;align-items:center;gap:7px;flex-wrap:wrap;
  margin:7px 0 0;font-size:11.5px;line-height:1.5;color:var(--text-muted);
}
.idx-dot{
  width:7px;height:7px;border-radius:50%;flex-shrink:0;
  background:var(--brand-green,#1FA463);
}
.idx-change{
  appearance:none;border:0;background:none;cursor:pointer;padding:0;
  font:700 11.5px/1 var(--font-sans),sans-serif;
  color:var(--brand-green,#0E7C4A);
  text-decoration:underline;text-underline-offset:3px;
}
.idx-verified{
  display:inline-flex;align-items:center;gap:5px;
  margin-top:7px;padding:4px 10px;border-radius:14px;
  background:rgba(31,164,99,.12);
  color:var(--brand-green,#0E7C4A);
  font:700 11px/1 var(--font-sans),sans-serif;
}
[data-theme="dark"] .idx-verified{background:rgba(24,201,121,.16);color:#5FD9A0;}
[data-theme="dark"] .idx-change{color:#5FD9A0;}

/* ═══════════════════════════════════════════════════════════════════════════
   EMI DATES AND THE PRE-EMI GAP
   ═══════════════════════════════════════════════════════════════════════════ */

.emi-disb-hint{
  margin:6px 0 0;font-size:11.5px;line-height:1.45;color:var(--text-muted,#4A6358);
}

.emi-start-panel{
  margin:14px 0 4px;padding:12px 14px;border-radius:12px;text-align:left;
  background:rgba(31,164,99,.07);border:1px solid rgba(31,164,99,.2);
}
.emi-start-panel[hidden]{display:none;}
.esp-row{display:flex;justify-content:space-between;align-items:baseline;gap:12px;}
.esp-row + .esp-row{margin-top:6px;}
.esp-k{font-size:12px;font-weight:600;color:var(--text-muted,#4A6358);}
.esp-v{font-size:15px;font-weight:800;color:var(--brand-deep,#085C3A);font-variant-numeric:tabular-nums;}
.esp-note{margin:8px 0 0;font-size:11.5px;line-height:1.5;color:var(--text-muted,#4A6358);}
[data-theme="dark"] .emi-start-panel{background:rgba(31,164,99,.1);border-color:rgba(95,217,160,.26);}
[data-theme="dark"] .esp-v{color:#5FD9A0;}

/* The due date is reference, not a figure to compare — it stays quieter
   than the money columns beside it. */
.schedule-table .sch-date{
  white-space:nowrap;font-size:11.5px;color:var(--text-muted,#4A6358);
  font-variant-numeric:tabular-nums;
}

/* Row zero. Tinted so it reads as a charge that sits outside the
   instalment run rather than as the first instalment. */
.schedule-table tr.sch-pre > td{
  background:rgba(179,38,30,.055);font-weight:600;
}
[data-theme="dark"] .schedule-table tr.sch-pre > td{background:rgba(255,138,128,.1);}

/* ── Scene Lab (?lab=1 only; see scene-lab.js) ────────────────────────── */
#lab-bar{
  position:fixed;left:50%;transform:translateX(-50%);bottom:12px;z-index:99999;
  display:flex;align-items:center;gap:10px;flex-wrap:wrap;justify-content:center;
  max-width:calc(100vw - 20px);padding:9px 14px;border-radius:12px;
  background:#0A1A12;color:#E8F5EE;border:1px solid #1FA463;
  font:12px/1.2 ui-monospace,SFMono-Regular,Menlo,monospace;
  box-shadow:0 10px 30px -8px rgba(0,0,0,.5);
}
#lab-bar strong{color:#5FD9A0;letter-spacing:.04em;}
#lab-bar label{display:flex;align-items:center;gap:5px;}
#lab-bar select,#lab-bar button{
  background:#15291F;color:#E8F5EE;border:1px solid #2E5A45;border-radius:7px;
  padding:4px 9px;font:inherit;cursor:pointer;
}
#lab-bar button:hover{border-color:#5FD9A0;}
#lab-bar input[type=range]{width:170px;accent-color:#1FA463;}
#lab-bar input[type=range]:disabled{opacity:.4;}
#lab-pct{min-width:40px;color:#5FD9A0;font-variant-numeric:tabular-nums;}

.lab-tag{
  position:absolute;top:6px;left:6px;z-index:5;pointer-events:none;
  padding:3px 7px;border-radius:6px;
  background:rgba(10,26,18,.86);color:#9FE3C0;
  font:10px/1.3 ui-monospace,SFMono-Regular,Menlo,monospace;
  font-variant-numeric:tabular-nums;white-space:nowrap;
}
.lab-tag.is-live{color:#5FD9A0;}


/* The reason a field is being asked for again, beside its name. Without it
   the list says "Mobile number" and the reader has to guess what is wrong
   with the mobile number they already typed. */
.eg-list .eg-why {
  display: inline; font-size: 12px; font-weight: 500;
  color: var(--cost-red-auto, #B3261E);
}
.eg-list li { line-height: 1.6; }
