/**
 * e-flo — motion layer, v3 "Current".
 *
 * v2 moved everything the same way: every block faded in and rose 40px as it
 * crossed the viewport. Uniform entrances read as a slideshow — and one of
 * them hid content outright. The prerender baked data-reveal into the
 * nl/de/fr pages, v2 skipped anything already carrying it, and 22 blocks per
 * localised page stayed at opacity 0 for good.
 *
 * v3 rules:
 *   1. Content is visible at rest. Nothing is hidden by an attribute alone;
 *      a hidden starting state needs html.e-armed, which the script adds only
 *      after it has started observing the element.
 *   2. Motion reads as current: it has a source and a direction, arrives
 *      fast and settles. No bounce, no float, no idle wobble.
 *   3. Scroll is the throttle. The big moves are scrubbed to scroll progress
 *      with CSS scroll-driven animations (compositor-only). A browser without
 *      them gets the static layout, which is complete on its own.
 *   4. One signature moment per page; everything around it stays quiet.
 *   5. prefers-reduced-motion switches all of it off.
 *
 * Tesla-clean still holds: one accent, border-only cards, no new colours.
 */

:root {
  --e-out: cubic-bezier(.16, 1, .3, 1);        /* arrives fast, settles long */
  --e-soft: cubic-bezier(.22, .61, .36, 1);
  --e-snap: cubic-bezier(.65, 0, .35, 1);
  --e-green: #17C186;
  --e-deep: #0E7A5F;
  --e-ink: #121711;
}

/* ═══ 0. Pages hand over instead of reloading ═══════════════════════════════
   Cross-document view transitions: same-origin navigations cross-fade with a
   short lift, and the nav stays put, so the site behaves like one product
   rather than a stack of documents. Browsers without support navigate as
   before. */

@view-transition { navigation: auto; }
::view-transition-old(root) { animation: e-vt-out .22s var(--e-soft) both; }
::view-transition-new(root) { animation: e-vt-in .5s var(--e-out) both; }
@keyframes e-vt-out { to { opacity: 0; transform: translate3d(0, -6px, 0); } }
@keyframes e-vt-in { from { opacity: 0; transform: translate3d(0, 12px, 0); } }
nav.top, [data-screen-label="Nav"] { view-transition-name: e-nav; }
::view-transition-old(e-nav), ::view-transition-new(e-nav) { animation: none; }

/* ═══ 1. Legacy attributes are inert ════════════════════════════════════════
   The prerender baked v2's runtime attributes into static HTML. None of them
   may ever hide anything again. */

[data-reveal], [data-lift] { opacity: 1; transform: none; }
.eflo-rail-stale { display: none !important; }

/* ═══ 2. The nav turns to glass once you leave the top ══════════════════════
   Visual only — its height never changes, so nothing below it moves. */

nav.top, [data-screen-label="Nav"] {
  transition: background-color .45s var(--e-soft), box-shadow .45s var(--e-soft),
              border-color .45s var(--e-soft);
}
html.e-scrolled nav.top,
html.e-scrolled [data-screen-label="Nav"] {
  background: rgba(247, 247, 243, .72) !important;
  -webkit-backdrop-filter: saturate(1.6) blur(18px);
  backdrop-filter: saturate(1.6) blur(18px);
  border-bottom-color: rgba(18, 23, 17, .06) !important;
  box-shadow: 0 10px 30px -18px rgba(18, 23, 17, .22);
}

/* ═══ 3. Headlines arrive line by line, out of focus into focus ═════════════
   Each line sits in its own mask (.eflo-ln) and rises from fully below it.
   The blur settling at the same time is what makes it read as arrival. */

.eflo-ln { display: block; overflow: hidden; padding-bottom: .06em; margin-bottom: -.06em; }
.eflo-ln > i { display: block; font-style: inherit; }
html.motion .eflo-ln > i { transform: translate3d(0, 108%, 0); filter: blur(10px); }
html.motion .eflo-head-go .eflo-ln > i {
  animation: e-line 1.05s var(--e-out) forwards;
  animation-delay: calc(var(--i, 0) * 95ms + 80ms);
}
@keyframes e-line {
  60% { filter: blur(0); }
  to  { transform: translate3d(0, 0, 0); filter: blur(0); }
}

/* ═══ 4. Hero: the charger powers on ════════════════════════════════════════
   The signature moment on the homepage. The product is painted from the
   first frame (it is the LCP image — v2 kept it fully clipped for a second)
   and settles out of a lens: scale down, window open. A single line of
   current then runs along the hero's lower edge, and the field of light
   behind it leans towards the pointer. */

html.motion [data-atmos] { position: relative; isolation: isolate; }
html.motion [data-atmos]::before {
  content: '';
  position: absolute; inset: -180px -10%;           /* fixed insets: see CLS note in v2 */
  z-index: -1; pointer-events: none;
  background:
    radial-gradient(560px 420px at calc(18% + var(--e-px, 0) * 6%) calc(30% + var(--e-py, 0) * 6%), rgba(23, 193, 134, .17), transparent 62%),
    radial-gradient(520px 520px at calc(82% - var(--e-px, 0) * 4%) 68%, rgba(14, 122, 95, .11), transparent 60%);
  transition: background .9s var(--e-soft);
}
html.motion [data-atmos][data-dark]::before {
  background:
    radial-gradient(640px 480px at calc(22% + var(--e-px, 0) * 6%) calc(28% + var(--e-py, 0) * 6%), rgba(23, 193, 134, .24), transparent 64%),
    radial-gradient(560px 560px at 84% 72%, rgba(23, 193, 134, .12), transparent 60%);
}

/* The line of current along the hero's lower edge — once. */
html.motion [data-atmos]::after {
  content: '';
  position: absolute; left: 0; right: 0; bottom: 0; height: 1px;
  pointer-events: none;
  background: linear-gradient(90deg, transparent 0%, rgba(23, 193, 134, 0) 20%,
              var(--e-green) 50%, rgba(23, 193, 134, 0) 80%, transparent 100%);
  background-size: 50% 100%;
  background-repeat: no-repeat;
  background-position: -60% 0;
  animation: e-current 1.8s var(--e-snap) 1.1s forwards;
}
@keyframes e-current { to { background-position: 160% 0; } }

html.motion img[data-hero-img] {
  animation: e-poweron 1.5s var(--e-out) .1s backwards;
  transform-origin: 50% 60%;
}
@keyframes e-poweron {
  from {
    clip-path: inset(7% 7% 7% 7% round 32px);
    transform: scale(1.08);
    filter: saturate(.6) brightness(.96);
  }
  to {
    clip-path: inset(-140px round 24px);   /* wide enough to keep the drop shadow */
    transform: none;
    filter: none;
  }
}

/* Supporting hero pieces: short, sharp, in sequence. */
html.motion [data-load] {
  opacity: 0;
  transform: translate3d(0, 14px, 0);
  filter: blur(6px);
  animation: e-rise .8s var(--e-out) forwards;
  animation-delay: calc(var(--d, 0) * 1ms);
}
@keyframes e-rise { to { opacity: 1; transform: none; filter: blur(0); } }

html.motion [data-chip] {
  opacity: 0;
  transform: translate3d(0, 8px, 0) scale(.96);
  animation: e-chip .55s var(--e-out) forwards;
  animation-delay: calc(var(--d, 0) * 1ms);
}
@keyframes e-chip { to { opacity: 1; transform: none; } }

/* Depth: as the hero scrolls away the product falls back slower than the
   page. Scrubbed, so it answers the scroll wheel rather than a timer. */
@supports (animation-timeline: scroll()) {
  html.motion [data-e-depth] {
    animation: e-depth linear both;
    animation-timeline: scroll(root);
    animation-range: 0 90vh;
  }
  @keyframes e-depth {
    to { transform: translate3d(0, 70px, 0) scale(.94); opacity: .55; }
  }
}

/* ═══ 5. Section headings arrive through a mask ═════════════════════════════
   One arrival per section, and it is the heading's. Body copy and cards are
   already there — the eye lands on the heading because it is the only thing
   that moved. */

html.motion.e-armed [data-e-head] {
  clip-path: inset(0 0 100% 0);
  transform: translate3d(0, .45em, 0);
  filter: blur(8px);
}
html.motion.e-armed [data-e-head].e-in {
  clip-path: inset(-.2em -1em -.3em -1em);
  transform: none;
  filter: blur(0);
  transition: clip-path .9s var(--e-out), transform .9s var(--e-out), filter .7s var(--e-soft);
}

/* ═══ 6. Current runs through a grid ════════════════════════════════════════
   Cards never fade. When a grid enters, a line of light crosses each card's
   top edge in order — left to right, row by row — and the card lifts a
   fraction as it passes. The content was readable the whole time. */

html.motion [data-e-cell].e-in {
  /* No 0% / 100% frames and no fill: the animation starts from, and returns
     to, the card's own shadow and transform instead of overwriting them. */
  animation: e-energize 1.1s var(--e-soft);
  animation-delay: calc(var(--i, 0) * 110ms);
}
@keyframes e-energize {
  30% { box-shadow: inset 0 2px 0 rgba(23, 193, 134, 1), 0 14px 34px -18px rgba(23, 193, 134, .55); transform: translate3d(0, -4px, 0); }
}

@media (hover: hover) {
  [data-e-cell] { transition: border-color .35s var(--e-soft), transform .5s var(--e-out); }
  a[data-e-cell]:hover, [data-e-cell]:has(> a:only-child):hover {
    border-color: #9FD8C3 !important;
    transform: translate3d(0, -4px, 0);
  }
}

/* ═══ 7. Dark bands open like doors ═════════════════════════════════════════
   A dark section arrives as an inset panel with rounded corners and widens
   to full bleed as you scroll into it — the page opening onto the platform.
   Scrubbed and reversible. */

@supports (animation-timeline: view()) {
  html.motion [data-e-band] {
    animation: e-doors linear both;
    animation-timeline: view();
    animation-range: entry 0% entry 70%;
  }
  @keyframes e-doors {
    from { clip-path: inset(0 4.5% round 36px); }
    /* Vertical headroom so anything overhanging the band is never cut. */
    to   { clip-path: inset(-300px 0 -300px 0 round 0); }
  }

  /* Large images settle out of a lens as they cross the viewport. */
  html.motion [data-e-lens] {
    animation: e-lens linear both;
    animation-timeline: view();
    animation-range: entry 0% cover 45%;
  }
  @keyframes e-lens {
    from { clip-path: inset(9% round 28px); transform: scale(1.1); }
    to   { clip-path: inset(-140px round 0); transform: none; }
  }
}

/* ═══ 8. Calls to action answer the pointer ═════════════════════════════════
   Primary buttons lean towards the cursor and a band of light crosses them
   on hover. Only where a person is about to act. */

[data-e-cta] { transition: transform .45s var(--e-out), box-shadow .35s var(--e-soft); will-change: transform; }
@media (hover: hover) {
  [data-e-cta]:hover {
    background-image: linear-gradient(105deg, transparent 38%, rgba(255, 255, 255, .42) 50%, transparent 62%) !important;
    background-size: 260% 100% !important;
    background-repeat: no-repeat !important;
    animation: e-sweep .85s var(--e-soft) forwards;
  }
  [data-e-cta][data-e-green]:hover { box-shadow: 0 16px 36px -12px rgba(23, 193, 134, .65); }
}
@keyframes e-sweep { from { background-position: 130% 0; } to { background-position: -30% 0; } }
[data-e-cta]:active { transform: scale(.97) !important; }

@media (hover: hover) {
  a[data-arrow] > .eflo-arrow { display: inline-block; transition: transform .4s var(--e-out); }
  a[data-arrow]:hover > .eflo-arrow { transform: translate3d(5px, 0, 0); }
}

/* Nav links: an underline that charges left to right. */
.navlinks a, [data-i18n="t000"] > a:not(:last-child) { position: relative; transition: color .25s var(--e-soft); }
.navlinks a::after, [data-i18n="t000"] > a:not(:last-child)::after {
  content: '';
  position: absolute; left: 0; bottom: -7px;
  width: 100%; height: 2px; border-radius: 2px;
  background: var(--e-green);
  transform: scaleX(0); transform-origin: right;
  transition: transform .45s var(--e-out);
}
@media (hover: hover) {
  .navlinks a:hover::after, [data-i18n="t000"] > a:not(:last-child):hover::after { transform: scaleX(1); transform-origin: left; }
  .navlinks a:hover, [data-i18n="t000"] > a:not(:last-child):hover { color: var(--e-ink) !important; }
}

/* ═══ 9. The charge rail ════════════════════════════════════════════════════
   The page takes on charge as you read it. Scrubbed by CSS where supported;
   the script only drives it in browsers that cannot. */

#eflo-rail {
  position: fixed; left: 0; top: 0; bottom: 0;
  width: 2px; z-index: 999; pointer-events: none;
  background: rgba(18, 23, 17, .05);
}
#eflo-rail i {
  position: absolute; inset: 0;
  transform: scaleY(0); transform-origin: top;
  background: linear-gradient(180deg, var(--e-deep), var(--e-green));
}
#eflo-rail i::after {
  content: '';
  position: absolute; left: 50%; bottom: 0;
  width: 6px; height: 6px; margin: 0 0 -3px -3px;
  border-radius: 50%;
  background: var(--e-green);
  box-shadow: 0 0 12px 3px rgba(23, 193, 134, .75);
}
@supports (animation-timeline: scroll()) {
  #eflo-rail i { animation: e-rail linear both; animation-timeline: scroll(root); }
  @keyframes e-rail { to { transform: scaleY(1); } }
}

/* ═══ 10. Numbers ═══════════════════════════════════════════════════════════ */

.eflo-counting { font-variant-numeric: tabular-nums; }
@keyframes e-pulse {
  0%   { color: inherit; }
  25%  { color: var(--e-green); }
  100% { color: inherit; }
}
.eflo-changed { animation: e-pulse .8s var(--e-soft); }

/* ═══ 11. Details ═══════════════════════════════════════════════════════════ */

details summary { transition: color .25s var(--e-soft); }
@media (hover: hover) { details summary:hover { color: var(--e-deep); } }
details[open] > summary ~ * { animation: e-open .5s var(--e-out) both; }
@keyframes e-open { from { opacity: 0; transform: translate3d(0, -6px, 0); } }

:focus-visible { outline: 2px solid var(--e-green); outline-offset: 3px; }

/* ═══ Respect the setting — everything above becomes inert ═════════════════ */

@media (prefers-reduced-motion: reduce) {
  html.motion *, html.motion *::before, html.motion *::after,
  [data-e-cta], [data-e-cell], #eflo-rail i, details[open] > summary ~ * {
    animation: none !important;
    transition: none !important;
  }
  html.motion .eflo-ln > i,
  html.motion [data-load], html.motion [data-chip],
  html.motion.e-armed [data-e-head] {
    opacity: 1 !important; transform: none !important; filter: none !important; clip-path: none !important;
  }
  #eflo-rail { display: none; }
  @view-transition { navigation: none; }
}
