/* ============================================================
 * dll-lusion.css — animation layer for
 * dealer-application-and-virtual-dms-lusion.html
 *
 *   1. the hero scene is rebuilt as a glass cloud composition: four
 *      dealer nodes feeding a central Virtual DMS cloud, with
 *      illuminated streams locking into the SFA, DMS and BI panels
 *   2. the "how it works" row cards move onto the brand gradient and
 *      pick up the CTA band's dotted corners
 *   3. the USP grid becomes a sticky deck with content and an
 *      animated illustration per card
 *   4. the module band runs two to a row on a brand-tinted ground,
 *      with the about page's card entrance
 *
 * Sections 2-4 are carried over from van-lusion.css so the two pages
 * behave identically; only the prefix changes (dl- rather than vl-).
 * The hero is this page's own, since its subject is not a van.
 *
 * Purely additive. Every rule is scoped under a class the script
 * adds, or under an id only this stylesheet targets, so nothing
 * outside those sections is touched and no copy changes. Loaded last,
 * so two-class selectors win over the page's own rules without
 * !important.
 * ========================================================== */

/* ============================================================
 * 1. Hero scene
 *
 * One loop, 8s, shared by every part so the beat lines up:
 *
 *   continuous   dealer parcels climb the feeds into the cloud
 *   0.0-8.0s     each of the four nodes lifts in turn
 *   per stream   SFA, then DMS, then BI light as the stream reaches
 *
 * Everything is driven off --dlh-cyc, so retiming the whole scene is
 * one number. Each element's own delay is a fraction of it.
 *
 * The feed motes run on SMIL animateMotion rather than CSS, because
 * they follow curved paths; their 2.8s period is deliberately
 * independent of the cycle, so the stream never visibly loops in step
 * with the node lift.
 * ========================================================== */

.dlr-scene{--dlh-cyc:8s;}

/* The rebuilt scene carries four dealer nodes, a cloud and three core
   panels where the page had one diagram, so it is given the full width
   of its column rather than the 460px cap. The stage then hugs whatever
   the scene measures, instead of holding a fixed height with a dead
   band under it. */
.dlr-scene{width:min(540px,100%);}
.dlr-stage{height:auto;min-height:360px;padding:16px 0;}
@media (max-width:900px){.dlr-stage{min-height:300px;}}
@media (max-width:480px){.dlr-stage{min-height:240px;}}

/* ---------- glass panels ---------- */
.dlr-scene .dlh-glass{
  fill:rgba(255,255,255,.10);
  stroke:rgba(255,255,255,.26);
  stroke-width:1.4;
}

/* ---------- the cloud at the centre ---------- */
.dlr-scene .dlh-cloud{
  transform-box:fill-box;transform-origin:50% 50%;
  animation:dlhFloat 7s ease-in-out infinite;
}
@keyframes dlhFloat{
  0%,100%{transform:translateY(0);}
  50%{transform:translateY(-8px);}
}
.dlr-scene .dlh-halo{
  transform-box:fill-box;transform-origin:50% 50%;
  animation:dlhHalo 4.4s ease-in-out infinite;
}
@keyframes dlhHalo{
  0%,100%{transform:scale(1);opacity:.75;}
  50%{transform:scale(1.08);opacity:1;}
}

/* ---------- the four dealer nodes, lifting in turn ---------- */
.dlr-scene .dlh-node{
  transform-box:fill-box;transform-origin:50% 50%;
  animation:dlhNode var(--dlh-cyc) ease-in-out infinite;
}
.dlr-scene .dlh-node.n2{animation-delay:calc(var(--dlh-cyc) * -0.75);}
.dlr-scene .dlh-node.n3{animation-delay:calc(var(--dlh-cyc) * -0.5);}
.dlr-scene .dlh-node.n4{animation-delay:calc(var(--dlh-cyc) * -0.25);}
@keyframes dlhNode{
  0%{transform:translateY(0) scale(1);}
  8%{transform:translateY(-8px) scale(1.04);}
  22%,100%{transform:translateY(0) scale(1);}
}

/* node 2 — the live stock count ticking between two values */
.dlr-scene .dlh-qty{animation:dlhQty 2.6s steps(1,end) infinite;}
.dlr-scene .dlh-qty.q2{animation-name:dlhQty2;}
@keyframes dlhQty{0%,49%{opacity:1;}50%,100%{opacity:0;}}
@keyframes dlhQty2{0%,49%{opacity:0;}50%,100%{opacity:1;}}

/* node 3 — the scheme plus, pulsing as it applies */
.dlr-scene .dlh-plus{
  transform-box:fill-box;transform-origin:50% 50%;
  animation:dlhPlus 2.2s ease-in-out infinite;
}
@keyframes dlhPlus{
  0%,100%{transform:scale(1);opacity:.85;}
  50%{transform:scale(1.25);opacity:1;}
}

/* node 4 — offline, flashing briefly back to synced */
.dlr-scene .dlh-offx{animation:dlhOff 3.4s steps(1,end) infinite;}
.dlr-scene .dlh-onx{opacity:0;animation:dlhOn 3.4s steps(1,end) infinite;}
@keyframes dlhOff{0%,72%{opacity:1;}73%,100%{opacity:0;}}
@keyframes dlhOn{0%,72%{opacity:0;}73%,100%{opacity:1;}}

/* ---------- the feeds from the dealers into the cloud ---------- */
.dlr-scene .dlh-feed{animation:dlhFeedDash 1.4s linear infinite;}
@keyframes dlhFeedDash{to{stroke-dashoffset:-14;}}
/* the motes are moved by SMIL; this only fades each one in and out so
   neither end of the feed pops */
.dlr-scene .dlh-up{animation:dlhUp 2.8s linear infinite;}
@keyframes dlhUp{0%{opacity:0;}14%,80%{opacity:1;}100%{opacity:0;}}

/* ---------- the streams out to the core ---------- */
.dlr-scene .dlh-stream{
  stroke-dasharray:18 150;
  animation:dlhStream 2.6s linear infinite;
}
.dlr-scene .dlh-stream.s2{animation-delay:-.87s;}
.dlr-scene .dlh-stream.s3{animation-delay:-1.73s;}
@keyframes dlhStream{
  0%{stroke-dashoffset:168;opacity:0;}
  10%{opacity:1;}
  70%{opacity:1;}
  100%{stroke-dashoffset:0;opacity:0;}
}

/* each core panel lights as its stream lands — a third of a stream
   period apart, so the order reads SFA -> DMS -> BI */
.dlr-scene .dlh-sys-pulse{
  transform-box:fill-box;transform-origin:50% 50%;
  opacity:0;
  animation:dlhSysPulse 2.6s ease-out infinite;
}
.dlr-scene .dlh-sys.s2 .dlh-sys-pulse{animation-delay:-.87s;}
.dlr-scene .dlh-sys.s3 .dlh-sys-pulse{animation-delay:-1.73s;}
@keyframes dlhSysPulse{
  0%,62%{opacity:0;transform:scale(1);}
  70%{opacity:.9;transform:scale(1.04);}
  88%,100%{opacity:0;transform:scale(1.1);}
}

@media (prefers-reduced-motion:reduce){
  .dlr-scene .dlh-cloud,.dlr-scene .dlh-halo,.dlr-scene .dlh-node,
  .dlr-scene .dlh-qty,.dlr-scene .dlh-plus,.dlr-scene .dlh-offx,
  .dlr-scene .dlh-onx,.dlr-scene .dlh-feed,.dlr-scene .dlh-up,
  .dlr-scene .dlh-stream,.dlr-scene .dlh-sys-pulse{
    animation:none !important;transform:none !important;
  }
  /* the finished state: synced, streams drawn, nothing mid-flight */
  .dlr-scene .dlh-stream{stroke-dasharray:none !important;opacity:1 !important;}
  .dlr-scene .dlh-onx,.dlr-scene .dlh-qty.q1{opacity:1 !important;}
  .dlr-scene .dlh-offx,.dlr-scene .dlh-qty.q2,
  .dlr-scene .dlh-up,.dlr-scene .dlh-sys-pulse{opacity:0 !important;}
}
/* ============================================================
 * 3. The sticky deck (USP grid)
 * ========================================================== */

/* ---------- vortex backdrop ----------
 * The same swirl the van-sales and integration pages run behind their
 * decks. isolation:isolate keeps the canvas's z-index local to this
 * section, so it can sit under the cards without reaching past the
 * section. Deliberately NOT overflow:hidden — that would make this a
 * scroll container and kill the sticky canvas and the sticky cards
 * with it. */
.dl-stage{
  position:relative;
  background:#fff;
  isolation:isolate;
}

/* Pinned to the viewport while the section scrolls past, so the viewer
   stays inside the swirl instead of watching a slice of one enormous
   circle. The negative margin takes it back out of flow, so it adds no
   layout height; without it a 100vh block would push the deck down.
   It also keeps the canvas viewport-sized rather than as tall as the
   whole deck — far fewer pixels a frame. */
.dl-vortex{
  position:sticky;
  top:0;
  height:100vh;
  margin-bottom:-100vh;
  z-index:0;
  pointer-events:none;
  opacity:0;
  transition:opacity 1.3s var(--dl-ease,ease);
}
.dl-stage.dl-on-stage .dl-vortex{opacity:1;}
.dl-vortex canvas{display:block;width:100%;height:100%;}

/* On a white ground the arcs need lifting off the page rather than
   darkening down — a white veil, falling off toward the centre where
   the deck sits, so the strokes stay strongest at the margins. */
.dl-vortex::after{
  content:"";
  position:absolute;inset:0;z-index:1;pointer-events:none;
  background:radial-gradient(118% 78% at 50% 45%,
    rgba(255,255,255,.88), rgba(255,255,255,.52) 62%, rgba(255,255,255,.18) 100%);
}
.dl-stage > .container{position:relative;z-index:2;}

@media (prefers-reduced-motion:reduce){.dl-vortex{display:none;}}

.dl-stack.bento{display:block;margin-top:8px;}

/* A real in-flow spacer. A sticky box is constrained by its
   containing block's CONTENT box, so padding-bottom on .bento would
   not extend it and a margin on the last card collapses out of the
   parent entirely. Without this the final card has exactly zero
   stick room, never pins, and the cards above release early. */
.dl-stack-tail{
  display:block;
  height:var(--dl-tail,22vh);
  pointer-events:none;
}

.dl-stack > .feat{
  position:sticky;
  top:var(--dl-top,104px);
  margin-bottom:var(--dl-gap,15vh);
  min-height:var(--dl-min,52vh);
  width:100%;
  display:flex;
  flex-direction:column;
  justify-content:center;
  grid-column:auto;
  padding:38px 44px;
  background:var(--white,#fff);
  border:1px solid #EDF1F7;
  border-radius:var(--radius,18px);

  /* The pin IS the entrance, so the page's own .reveal offset has to
     be cleared: a transform on a sticky box fights the pin. */
  opacity:1;
  transform:none;
  transition:none;

  box-shadow:
    0 1px 2px rgba(16,31,56,.030),
    0 4px 10px rgba(16,31,56,.032),
    0 12px 26px rgba(16,31,56,.038),
    0 28px 58px rgba(16,31,56,.045);
}
.dl-stack > .feat:hover{transform:none;border-color:#E2D7F2;}
.dl-stack > .feat.dl-last{margin-bottom:0;}
.dl-stack > .feat.span2,
.dl-stack > .feat.span3,
.dl-stack > .feat.span6{grid-column:auto;}

/* The heading scrolls away with the page like any other section head,
   matching the other two decks. Pinning it makes it hang over the
   cards passing beneath, so it stays plain flow content, with no
   background band — nothing travels under it. The first card simply
   rises over it, which is what the deck is meant to look like.

   .section-head also carries the page's .reveal, which would fade the
   whole block in on top of the per-element entrances this layer gives
   the pill, the h2 and the lede. Cleared, so those play alone. */
.dl-stage .section-head{
  margin-bottom:26px;
  opacity:1;
  transform:none;
  transition:none;
}

/* ---------- card layout: copy left, illustration right ---------- */
.dl-stack > .feat.dl-has-vec{
  display:grid;
  grid-template-columns:minmax(0,1.04fr) minmax(0,.96fr);
  gap:46px;
  align-items:center;
}
.dl-card-text{min-width:0;}
.dl-card-vec{min-width:0;display:flex;align-items:center;justify-content:center;}
.dl-card-vec svg{width:100%;height:auto;max-height:290px;overflow:visible;}

.dl-points{list-style:none;margin:18px 0 0;padding:0;}
.dl-points .dl-point{
  position:relative;
  padding:11px 0 11px 26px;
  margin:0;
  border-top:1px solid var(--line-soft,#EDF1F6);
  font-size:14.5px;line-height:1.55;font-weight:600;
  color:var(--ink-soft,#5B6675);
}
.dl-points .dl-point::before{
  content:"";position:absolute;left:3px;top:19px;
  width:8px;height:8px;border-radius:50%;
  background:var(--grad,linear-gradient(135deg,#701893,#1308AD));
}

/* ---------- card entrance — one class plays the sequence ---------- */
.dl-stack .dl-noanim,
.dl-stack .dl-noanim *{transition:none !important;animation:none !important;}

.dl-stack > .feat .feat-ico{
  opacity:0;transform:scale(.66) rotate(-10deg);
  transition:opacity .5s var(--dl-ease), transform .62s var(--dl-back);
  transition-delay:60ms;
}
.dl-stack > .feat.dl-in .feat-ico{opacity:1;transform:none;}

.dl-stack > .feat h3{
  opacity:0;transform:translateY(16px);clip-path:inset(0 0 100% 0);
  transition:opacity .55s var(--dl-ease), transform .7s var(--dl-ease), clip-path .7s var(--dl-ease);
  transition-delay:150ms;
}
.dl-stack > .feat.dl-in h3{opacity:1;transform:none;clip-path:inset(0 0 0 0);}

.dl-stack > .feat .tag{
  opacity:0;clip-path:inset(0 100% 0 0 round 999px);
  transition:opacity .35s var(--dl-ease), clip-path .65s var(--dl-ease);
  transition-delay:320ms;
}
.dl-stack > .feat.dl-in .tag{opacity:1;clip-path:inset(0 0 0 0 round 999px);}

.dl-stack > .feat > p{
  opacity:0;transform:translateY(10px);
  transition:opacity .5s var(--dl-ease), transform .6s var(--dl-ease);
  transition-delay:260ms;
}
.dl-stack > .feat.dl-in > p{opacity:1;transform:none;}

.dl-stack > .feat .dl-points .dl-point{
  opacity:0;transform:translateY(12px);
  transition:opacity .5s var(--dl-ease), transform .6s var(--dl-ease);
  transition-delay:calc(420ms + var(--i,0) * 95ms);
}
.dl-stack > .feat.dl-in .dl-points .dl-point{opacity:1;transform:none;}

/* ---------- illustration animations ---------- */
.dl-card-vec [data-dl-draw]{
  stroke-dashoffset:var(--len,0);
  transition:stroke-dashoffset 1.3s var(--dl-ease);
  transition-delay:var(--dd,0ms);
}
.dl-in .dl-card-vec [data-dl-draw]{stroke-dashoffset:0;}

.dl-card-vec .dl-pop{
  opacity:0;transform:scale(.68);
  transform-box:fill-box;transform-origin:50% 50%;
  transition:opacity .5s var(--dl-ease), transform .62s var(--dl-back);
  transition-delay:calc(260ms + var(--p,0) * 100ms);
}
.dl-in .dl-card-vec .dl-pop{opacity:1;transform:none;}

.dl-card-vec .dl-bar{
  transform:scaleY(0);
  transform-box:fill-box;transform-origin:50% 100%;
  transition:transform .8s var(--dl-ease);
  transition-delay:calc(320ms + var(--p,0) * 95ms);
}
.dl-in .dl-card-vec .dl-bar{transform:none;}

.dl-card-vec .dl-flow{opacity:0;transition:opacity .5s ease .7s;}
.dl-in .dl-card-vec .dl-flow{opacity:1;}

.dl-card-vec .dl-float,
.dl-card-vec .dl-ring,
.dl-card-vec .dl-spin{animation-play-state:paused;}
.dl-in .dl-card-vec .dl-float,
.dl-in .dl-card-vec .dl-ring,
.dl-in .dl-card-vec .dl-spin{animation-play-state:running;}

.dl-card-vec .dl-float{
  animation:dlFloat 4.4s ease-in-out infinite;
  transform-box:fill-box;transform-origin:50% 50%;
}
@keyframes dlFloat{0%,100%{transform:translateY(0)}50%{transform:translateY(-7px)}}

.dl-card-vec .dl-ring{
  fill:none;animation:dlRing 3s ease-out infinite;
  transform-box:fill-box;transform-origin:50% 50%;
}

.dl-card-vec .dl-spin{
  transform-box:view-box;animation:dlSpin 24s linear infinite;
}
@keyframes dlSpin{to{transform:rotate(360deg)}}

/* the scan bar sweeping the QR on the verification card */
.dl-card-vec .dl-scanbar{
  animation:dlScanbar 2.8s ease-in-out infinite;
}
@keyframes dlScanbar{
  0%{transform:translateY(0);opacity:0;}
  8%{opacity:.95;}
  48%{transform:translateY(108px);opacity:.95;}
  56%,100%{transform:translateY(108px);opacity:0;}
}

/* ============================================================
 * 4. Smaller screens — the deck unstacks into a normal column
 * ========================================================== */
@media (max-width:991px){
  .dl-stack.bento{display:grid;grid-template-columns:1fr;gap:26px;}
  .dl-stack > .feat{position:relative;min-height:0;margin-bottom:0;padding:28px 26px;}
  .dl-stack > .feat.dl-last{margin-bottom:0;}
  .dl-stack-tail{display:none;}
  .dl-stack > .feat.dl-has-vec{grid-template-columns:1fr;gap:24px;}
  .dl-card-vec{order:2;}
  .dl-card-vec svg{max-height:210px;}
  .dl-stage .section-head{margin-bottom:34px;}
}
@media (max-width:575px){
  .dl-stack > .feat{padding:24px 22px;}
  .dl-points .dl-point{font-size:13.5px;padding:9px 0 9px 22px;}
  .dl-points .dl-point::before{top:16px;width:7px;height:7px;}
  .dl-card-vec{display:none;}   /* copy wins the space on a phone */
}

/* ============================================================
 * 5. Reduced motion
 * ========================================================== */
@media (prefers-reduced-motion:reduce){
  .dl-stack > .feat{position:relative;min-height:0;margin-bottom:26px;}
  .dl-stack-tail{display:none;}
  .dl-stack > .feat .feat-ico,
  .dl-stack > .feat h3,
  .dl-stack > .feat .tag,
  .dl-stack > .feat > p,
  .dl-stack > .feat .dl-points .dl-point,
  .dl-card-vec .dl-pop,.dl-card-vec .dl-flow{
    opacity:1 !important;transform:none !important;
    clip-path:none !important;transition:none !important;
  }
  .dl-card-vec .dl-bar{transform:none !important;transition:none !important;}
  .dl-card-vec [data-dl-draw]{stroke-dashoffset:0 !important;transition:none !important;}
  .dl-card-vec .dl-float,.dl-card-vec .dl-ring,.dl-card-vec .dl-spin,
  .dl-card-vec .dl-scanbar{animation:none !important;}
}
/* ============================================================
 * 2. The "how it works" band
 * ========================================================== */

/* ---------- the row cards, on the brand gradient ----------
 * The page ships these white. On --grad they have to carry their own
 * contents: everything inside was coloured for a white card, and left
 * alone the ink, the faint sub-labels and the gradient-filled bars
 * would all but disappear. Each is restated below against the dark
 * ground, so only the surface changes and no copy moves. */
.dl-flow-sec .flow-visual{
  background:var(--grad,linear-gradient(135deg,#701893,#1308AD));
  border-color:rgba(255,255,255,.16);
  box-shadow:
    0 2px 6px rgba(32,10,70,.14),
    0 14px 34px rgba(32,10,70,.20),
    0 30px 64px rgba(32,10,70,.16);

  /* the dot corners below are absolutely positioned and bleed past the
     edges, so the card has to position and clip them itself — the page
     sets neither on .flow-visual */
  position:relative;
  overflow:hidden;
}

/* ---------- the CTA band's dotted corners, on these cards ----------
 * Same recipe the page uses for .cta: a 16px grid of 1.5px dots, laid
 * in two patches and masked to a soft blob so the texture fades out
 * rather than stopping at a hard edge. One patch top-left, one
 * bottom-right, exactly as the band does it.
 *
 * Dot size, spacing, colour and mask shape are the band's own values,
 * so the texture matches across the page. Only the patch offsets are
 * pulled in, because these cards are a fraction of the band's width
 * and the band's -30/-40px would push most of the pattern out of
 * sight. The percentages size themselves. */
.dl-flow-sec .flow-visual::before,
.dl-flow-sec .flow-visual::after{
  content:"";
  position:absolute;
  width:min(52%,260px);
  height:84%;
  z-index:0;
  pointer-events:none;
  background-image:radial-gradient(circle,
    rgba(255,255,255,.32) 1.5px, transparent 1.6px);
  background-size:16px 16px;
}
.dl-flow-sec .flow-visual::before{
  left:-18px;top:-22px;
  -webkit-mask-image:radial-gradient(circle at 22% 30%, #000 0%, #000 40%, transparent 70%);
          mask-image:radial-gradient(circle at 22% 30%, #000 0%, #000 40%, transparent 70%);
}
.dl-flow-sec .flow-visual::after{
  right:-18px;bottom:-22px;
  -webkit-mask-image:radial-gradient(circle at 78% 70%, #000 0%, #000 40%, transparent 70%);
          mask-image:radial-gradient(circle at 78% 70%, #000 0%, #000 40%, transparent 70%);
}

/* the rows ride above the texture. .flow-visual is a flex container,
   so this also keeps the pseudo-elements from being treated as items —
   they are absolutely positioned, which takes them out of flow. */
.dl-flow-sec .flow-visual > *{position:relative;z-index:1;}

/* the icon tile was a pale lavender chip with purple glyph — invisible
   logic on a purple card, so it becomes a frosted chip instead */
.dl-flow-sec .flow-visual .fv-ico{
  background:rgba(255,255,255,.16);
  color:#fff;
  box-shadow:inset 0 0 0 1px rgba(255,255,255,.18);
}

.dl-flow-sec .flow-visual .fv-txt{color:#fff;}
.dl-flow-sec .flow-visual .fv-txt small{color:rgba(255,255,255,.68);}

/* the track was light grey on white; the fill was --grad, which would
   now be gradient on gradient. They swap roles: a translucent well
   with a bright fill. */
.dl-flow-sec .flow-visual .fv-bar{background:rgba(255,255,255,.18);}
.dl-flow-sec .flow-visual .fv-bar > i{
  background:linear-gradient(90deg,#ffffff,#d9c6ff);
}

/* ============================================================

 * 6. The module band — two cards to a row, on brand colour
 *
 * Scoped to #modules, which only this stylesheet targets, so the id
 * selector outranks the page's own .mod-list / .mod-card / .stats-band
 * rules without needing !important and without touching them.
 * ========================================================== */

/* The page ships this band as neutral grey (--bg-alt: #F5F7FA).
   Replaced with the brand's own light tints, running purple into
   indigo in the same direction as --grad, so the strip reads as part
   of the theme instead of generic page furniture. */
#modules.stats-band{
  background:linear-gradient(180deg,#F8F3FD 0%,#F0E7F9 52%,#E9E7FB 100%);
}

/* Two to a row. The page's rule is a bare single-column grid, so only
   the column track and the gap need stating. Six cards divide into
   three even rows, and stretch keeps the pair in each row level. */
#modules .mod-list{
  grid-template-columns:repeat(2,minmax(0,1fr));
  gap:22px;
  align-items:stretch;
}

/* Each card carries its bullets in two columns. At half width those
   columns come out near 150px and most items wrap to a second line,
   so the list runs single column here and the card grows taller
   instead. */
#modules .mod-card ul{columns:1;}

/* White cards need a slightly warmer edge against a tinted ground
   than they do against grey. */
#modules .mod-card{border-color:#E7DCF3;}

/* The eyebrow pill's own background is --red-soft (#F2E9F8), which is
   inside the range of the new band — it would melt into it, so it
   gets a white chip here and keeps its brand-purple text. */
#modules .section-head .eyebrow{background:var(--white,#fff);}

/* Below this the pair would be too narrow to carry a heading, a badge
   and the bullets, so the band goes back to one card per row. */
@media (max-width:900px){
  #modules .mod-list{grid-template-columns:1fr;}
}

/* ---------- the about page's card entrance, on these cards ----------
 * Lifted from lusion-hero.css rather than reinvented, so the two pages
 * share the same easings and durations. Scoped to .dl-mods, a class the
 * script adds, so none of it reaches the deck or the hero.
 * The script strips these classes ~1.5s after a card lands, which is
 * what hands :hover back to the page's own rule. */
.dl-mods{
  --dlm-ease:cubic-bezier(.22,.8,.3,1);
  --dlm-pop:cubic-bezier(.34,1.32,.44,1);
}

/* rewinding must not play the entrance backwards */
.dl-mods .dl-noanim,
.dl-mods .dl-noanim *{transition:none !important;animation:none !important;}

/* the ghost number needs a positioned card, the sheen needs a clipped
   one — neither is true of .mod-card by default */
.dl-mods .mod-card{position:relative;overflow:hidden;}

/* --- card: hinges up from its bottom edge in perspective --- */
.dl-mods .dl-mcard{
  opacity:0;
  transform:perspective(1300px) rotateX(11deg) translateY(50px) scale(.955);
  transform-origin:50% 100%;
  transition:opacity .8s var(--dlm-ease), transform 1.05s var(--dlm-ease);
  transition-delay:var(--d,0ms);
  will-change:opacity,transform;
}
.dl-mods .dl-mcard.dl-min{opacity:1;transform:none;}

/* --- sheen sweeping across as the card lands --- */
.dl-mods .dl-mcard::before{
  content:"";position:absolute;inset:0;z-index:3;pointer-events:none;
  background:linear-gradient(115deg,transparent 38%,rgba(104,60,220,.16) 50%,transparent 62%);
  transform:translateX(-130%);opacity:0;
}
.dl-mods .dl-mcard.dl-min::before{
  animation:dlSheen 1.15s var(--dlm-ease) forwards;
  animation-delay:calc(var(--d,0ms) + 260ms);
}
@keyframes dlSheen{
  0%  {transform:translateX(-130%);opacity:0;}
  28% {opacity:1;}
  100%{transform:translateX(130%);opacity:0;}
}

/* --- icon: pops in --- */
.dl-mods .dl-mico{
  opacity:0;transform:scale(.42) rotate(-24deg);
  transition:opacity .5s var(--dlm-ease), transform .75s var(--dlm-pop);
  transition-delay:var(--d,0ms);
}
.dl-mods .dl-mico.dl-min{opacity:1;transform:none;}

/* --- badge: wipes in from the left without distorting its text --- */
.dl-mods .dl-mtag{
  opacity:0;clip-path:inset(0 100% 0 0 round 999px);
  transition:opacity .35s var(--dlm-ease), clip-path .7s var(--dlm-ease);
  transition-delay:var(--d,0ms);
}
.dl-mods .dl-mtag.dl-min{opacity:1;clip-path:inset(0 0 0 0 round 999px);}

/* --- the ghost index, dropping in out of focus --- */
.dl-mods .dl-num{
  position:absolute;right:26px;bottom:18px;
  font-size:34px;font-weight:900;letter-spacing:-.03em;line-height:1;
  color:var(--bg-alt-2,#EEF2F7);
  pointer-events:none;user-select:none;
}
.dl-mods .dl-mnum{
  opacity:0;transform:translateY(-16px) scale(1.35);filter:blur(7px);
  transition:opacity .75s var(--dlm-ease), transform .9s var(--dlm-ease),
             filter .75s var(--dlm-ease);
  transition-delay:var(--d,0ms);
}
.dl-mods .dl-mnum.dl-min{opacity:1;transform:none;filter:blur(0);}

/* --- heading: each word hinges up out of a clip mask in 3D. The
       padding/margin pair keeps descenders (g, y, p) off the mask. --- */
.dl-mods .dl-w{
  display:inline-block;overflow:hidden;vertical-align:bottom;
  padding-bottom:.2em;margin-bottom:-.2em;
  perspective:680px;
}
.dl-mods .dl-w > i{
  display:inline-block;font-style:inherit;
  transform:translateY(116%) rotateX(-68deg);
  transform-origin:50% 0%;
  opacity:0;filter:blur(5px);
  transition:transform 1.05s var(--dlm-ease),
             opacity .62s var(--dlm-ease),
             filter .62s var(--dlm-ease);
  transition-delay:var(--d,0ms);
  will-change:transform,opacity,filter;
}
.dl-mods .dl-split.dl-min .dl-w > i{transform:none;opacity:1;filter:blur(0);}

/* --- bullets: follow the heading, one after another --- */
.dl-mods .dl-mli{
  opacity:0;transform:translateY(10px);
  transition:opacity .5s var(--dlm-ease), transform .6s var(--dlm-ease);
  transition-delay:var(--d,0ms);
}
.dl-mods .dl-mli.dl-min{opacity:1;transform:none;}

@media (prefers-reduced-motion:reduce){
  .dl-mods .dl-mcard,.dl-mods .dl-mico,.dl-mods .dl-mtag,
  .dl-mods .dl-mnum,.dl-mods .dl-mli,.dl-mods .dl-w > i{
    opacity:1 !important;transform:none !important;filter:none !important;
    clip-path:none !important;transition:none !important;
  }
  .dl-mods .dl-mcard::before{display:none !important;}
}

/* ============================================================
 * 6b. The connected-ecosystem tiles, on the brand gradient
 *
 * Scoped to #ecosystem, which only this stylesheet targets, so the id
 * outranks the page's own .eco-tile rules without !important and
 * without touching them.
 *
 * These tiles are links, and everything in them was coloured for a
 * white card: a teal kicker, navy heading and grey body. Left alone on
 * --grad the teal would muddy and the rest would all but vanish, so
 * each is restated against the dark ground. Only colour changes — no
 * copy, no layout, and the hover lift still works.
 * ========================================================== */
#ecosystem .eco-tile{
  background:var(--grad,linear-gradient(135deg,#701893,#1308AD));
  border-color:rgba(255,255,255,.16);
  box-shadow:
    0 2px 6px rgba(32,10,70,.14),
    0 12px 30px rgba(32,10,70,.18);
}

/* the page lifts the tile and turns its border --red on hover, which
   is the card's own purple and so invisible here — a light edge reads
   the lift instead */
#ecosystem .eco-tile:hover{
  border-color:rgba(255,255,255,.5);
  box-shadow:
    0 4px 10px rgba(32,10,70,.18),
    0 18px 42px rgba(32,10,70,.26);
}

/* teal at --teal is too dark to sit on this gradient; the lighter mint
   the page already uses on its dark hero chips carries over */
#ecosystem .eco-tile .k{color:#8fe9d5;}
#ecosystem .eco-tile h4{color:#ffffff;}
#ecosystem .eco-tile p{color:rgba(255,255,255,.72);}

/* ============================================================
 * 6c. Responsiveness repair
 *
 * This one is the page's own, not this layer's: it measures
 * identically on the untouched dealer-application-and-virtual-dms.html
 * — 88px of horizontal overflow at 768. Corrected here as an override,
 * so the original file stays byte-for-byte unchanged.
 * ========================================================== */

/* The stats band runs FIVE across from 761px up — set by an inline
   <style> further down the page, tucked into a block for the clients
   carousel, which is why it is not where you would look for it. A
   .stat's min-content width is about 167px (38px bold numerals plus
   26px padding each side), so five tracks plus four 20px gaps need
   ~915px of container and there is nowhere near that until ~992px.
   The grid pushes past the viewport and the WHOLE PAGE gains a
   horizontal scrollbar. Three across fits the same band at 541px and
   reflows 5 items as 3 + 2.

   The selector needs the element name: that five-column rule sits
   AFTER this stylesheet is linked, so a matching .stats-band
   .stats-grid would tie on specificity and lose on order. */
@media (min-width:761px) and (max-width:991px){
  section.stats-band .stats-grid{grid-template-columns:repeat(3,minmax(0,1fr));}
}

/* Same cause at the bottom end: two-up needs ~154px a column and a
   320px viewport leaves 138px. 375px still fits two. */
@media (max-width:374px){
  section.stats-band .stats-grid{grid-template-columns:1fr;}
}

/* ============================================================

 * 7. Support for lusion-motion.js
 *
 * That script is shared across the demo pages, where these rules
 * live in lusion-hero.css. This page does not load that file, so the
 * three things it depends on are repeated here. They are not
 * optional: without the .lx-roll rules the letter-roll leaves BOTH
 * copies of every character in the flow and the nav reads doubled.
 * ========================================================== */

/* The page stylesheet sets html{scroll-behavior:smooth}. Left in
   place it makes every scrollTo() in the lerp start a NEW native
   smooth animation that the next frame cancels — the page stalls,
   then lurches. */
html.lx-smooth{scroll-behavior:auto !important;}

.lx-roll{
  display:inline-block;
  overflow:hidden;
  vertical-align:top;
  line-height:inherit;
}
.lx-roll__c{
  display:inline-block;
  position:relative;
  white-space:pre;
  transition:transform .52s cubic-bezier(.22,.61,.36,1);
  transition-delay:calc(var(--i) * 18ms);
  will-change:transform;
}
.lx-roll__c span{display:block;}
.lx-roll__c span:last-child{position:absolute;left:0;top:100%;}
.lx-roll:hover .lx-roll__c,
a:hover .lx-roll .lx-roll__c,
button:hover .lx-roll .lx-roll__c{transform:translateY(-100%);}

.lx-mag{will-change:transform;}
.lx-mag__inner{display:inline-flex;align-items:center;gap:inherit;will-change:transform;}

@media (prefers-reduced-motion:reduce){
  .lx-roll__c{transition:none;}
}
