/* ==========================================================================
   EasyFranceNow — MOTION layer  ·  efn-motion.css
   --------------------------------------------------------------------------
   Loaded LAST, after efn-design.css and efn-shell.css. Presentation only:
   it never changes a layout, a colour, or a piece of logic.

   THE RULE THIS LAYER FOLLOWS
   efn-design.css §22(d) deliberately killed every hover transform — the app
   is calm on purpose. So motion here is never decoration on hover. It only
   ever does one of three jobs:

     1 · ARRIVAL   — say "the page is ready", once, in the order you read it.
     2 · CHANGE    — say "this number / this bar / this box just moved",
                     at the moment it actually moves.
     3 · PLACE     — say "you are here" in the rail.

   THE SAFETY CONTRACT
   Every animated property lives INSIDE its @keyframes, and every animation
   uses `backwards`, never `forwards`. The resting state of every element is
   therefore its original, untouched design. If an animation never runs, the
   page looks exactly as it did before this file existed.

   To retune the whole app's motion: edit the tokens in section 1.
   ========================================================================== */

/* ---- 1 · TOKENS -------------------------------------------------------- */
:root{
  --m-1:.16s;                              /* a control answering a press   */
  --m-2:.34s;                              /* an element arriving           */
  --m-3:.62s;                              /* something travelling a distance */
  --m-ease:cubic-bezier(.4,0,.2,1);        /* matches --ease in the design layer */
  --m-out:cubic-bezier(.16,.84,.44,1);     /* decelerating: things settle, never bounce */
  --m-pop:cubic-bezier(.34,1.26,.5,1);     /* the ONE springy curve, spent on the checkmark */
  --m-step:52ms;                           /* one beat of the arrival stagger */
  --m-rise:9px;                            /* how far an arriving block travels */
}

/* ---- 2 · KEYFRAMES ----------------------------------------------------- */
@keyframes efn-rise{
  from{ opacity:0; transform:translate3d(0,var(--m-rise),0) }
  to  { opacity:1; transform:none }
}
@keyframes efn-fade{
  from{ opacity:0 }
  to  { opacity:1 }
}
@keyframes efn-pop{
  from{ opacity:0; transform:scale(.72) }
  to  { opacity:1; transform:scale(1) }
}
/* the checkmark writes itself, short arm first */
@keyframes efn-draw{
  from{ stroke-dasharray:24; stroke-dashoffset:-24 }
  to  { stroke-dasharray:24; stroke-dashoffset:0 }
}
/* a bar grows into the width the number already says it is */
@keyframes efn-bar{
  from{ transform:scaleX(0) }
  to  { transform:scaleX(1) }
}
/* the seven-stop journey line draws downward */
@keyframes efn-thread{
  from{ transform:scaleY(0) }
  to  { transform:scaleY(1) }
}
/* the "you are here" marker on the rail */
@keyframes efn-mark{
  from{ transform:scaleY(0); opacity:0 }
  to  { transform:scaleY(1); opacity:1 }
}
/* one ring off the current stop, then gone */
@keyframes efn-ring{
  from{ transform:scale(.6); opacity:.55 }
  to  { transform:scale(1.9); opacity:0 }
}
/* the hero photograph settles into place instead of snapping in */
@keyframes efn-settle{
  from{ opacity:0; transform:scale(1.045) }
  to  { opacity:1; transform:scale(1) }
}

/* ==========================================================================
   3 · ARRIVAL — the one orchestrated moment
   The page assembles top to bottom, in the order you read it. Only the
   direct children of the page container are touched: everything a tool
   re-renders on a keystroke lives INSIDE those children, so nothing here
   ever replays while someone is typing.
   ========================================================================== */
.wrap > header,
.wrap > .sec,
.wrap > .pgroup,
.wrap > .card,
.wrap > .panel,
.wrap > .result,
.wrap > .official,
.wrap > .caveat,
.wrap > .options,
.wrap > div[id]{
  animation:efn-rise var(--m-2) var(--m-out) backwards;
}
.wrap > *:nth-child(1){ animation-delay:0ms }
.wrap > *:nth-child(2){ animation-delay:calc(var(--m-step) * 1) }
.wrap > *:nth-child(3){ animation-delay:calc(var(--m-step) * 2) }
.wrap > *:nth-child(4){ animation-delay:calc(var(--m-step) * 3) }
.wrap > *:nth-child(5){ animation-delay:calc(var(--m-step) * 4) }
.wrap > *:nth-child(n+6){ animation-delay:calc(var(--m-step) * 5) }
/* The dashboard is NOT staggered this way: it nests .shell > .layout > .main
   and rebuilds .main on every hash change, so its arrival is handled piece
   by piece in section 8 instead. */

/* ==========================================================================
   4 · THE SIGNATURE — the verification badge proves itself
   Every tool page carries one line: "checked against official French
   government sources". That claim is the product. So it is the one thing
   that gets a real gesture: the dot lands, then the check writes itself.
   ========================================================================== */
.verified{ animation:efn-rise var(--m-2) var(--m-out) 260ms backwards }
.verified .dot{ animation:efn-pop var(--m-2) var(--m-pop) 380ms backwards }
.verified .dot svg polyline{
  animation:efn-draw 520ms var(--m-out) 520ms backwards;
}

/* ==========================================================================
   5 · CHANGE — bars, meters and rings move visibly
   Two mechanisms, on purpose:
     · the grow-in animation fires when a bar is first painted;
     · the width transition carries every later change, so a bar that is
       recalculated on a keystroke slides instead of jumping.
   ========================================================================== */
.prog .fill,
.bar .fill,
.meter .fill,
.qprog .fill,
.yearbar .fill{
  transform-origin:left center;
  animation:efn-bar var(--m-3) var(--m-out) 120ms backwards;
  transition:width var(--m-3) var(--m-ease), background-color var(--m-2) var(--m-ease);
}

/* the count that sits under a bar follows the bar, not the keystroke */
.prog .lbl{ transition:color var(--m-2) var(--m-ease) }

/* ==========================================================================
   6 · CHANGE — a task, a document, a step becomes done
   The check is redrawn by the page's own render() on click, so this fires
   exactly once per real state change, and never while typing.
   ========================================================================== */
.chk{ transition:background-color var(--m-1) var(--m-ease), border-color var(--m-1) var(--m-ease) }
.task[data-state=done] .chk svg{ animation:efn-pop var(--m-2) var(--m-pop) backwards }

.doc,.task,.ci,.stamp,.docitem{
  transition:border-color var(--m-2) var(--m-ease), background-color var(--m-2) var(--m-ease);
}
.done-banner.show{ animation:efn-rise var(--m-2) var(--m-out) backwards }

/* DELIBERATELY NOT ANIMATED: .insight, .rcard and the other result blocks.
   Their pages call render() on every `input` event, so any entry animation
   on them would restart on each keystroke and flicker. Their static parent
   is animated once on arrival in section 3 instead, and the numbers inside
   change instantly — which, while someone is dragging a value, is the
   honest behaviour anyway. */

/* ==========================================================================
   7 · PLACE — the rail
   The journey line draws itself down the seven stops, the stops fade in in
   order, and the current one is marked. This is the app's own map: motion
   here is the only place it is allowed to be a little expressive.
   ========================================================================== */
.efn-s-side{ animation:efn-fade var(--m-2) var(--m-ease) backwards }
.efn-s-brand img{ animation:efn-rise var(--m-2) var(--m-out) 60ms backwards }

.efn-s-nav .efn-s-item,
.efn-s-rail .efn-s-item{ animation:efn-fade var(--m-2) var(--m-ease) backwards }
.efn-s-rail .efn-s-item:nth-child(1){ animation-delay:80ms }
.efn-s-rail .efn-s-item:nth-child(2){ animation-delay:112ms }
.efn-s-rail .efn-s-item:nth-child(3){ animation-delay:144ms }
.efn-s-rail .efn-s-item:nth-child(4){ animation-delay:176ms }
.efn-s-rail .efn-s-item:nth-child(5){ animation-delay:208ms }
.efn-s-rail .efn-s-item:nth-child(6){ animation-delay:240ms }
.efn-s-rail .efn-s-item:nth-child(7){ animation-delay:272ms }

.efn-s-rail::before{
  transform-origin:top center;
  animation:efn-thread 900ms var(--m-out) 60ms backwards;
}

/* "you are here": the accent bar wipes in from the middle */
.efn-s-item.on::before{
  animation:efn-mark var(--m-2) var(--m-out) backwards;
}
/* and the numbered stop sends out exactly one ring */
.efn-s-rail .efn-s-item.on .efn-s-node::after{
  content:""; position:absolute; inset:-2px; border-radius:50%;
  border:2px solid var(--nav-accent); pointer-events:none;
  animation:efn-ring 900ms var(--m-out) 120ms backwards;
}
/* the count badge picks up the change with the row */
.efn-s-item .efn-s-n{ transition:background-color var(--m-1) var(--m-ease), color var(--m-1) var(--m-ease) }

/* ==========================================================================
   8 · ARRIVAL — the dashboard welcome
   The photograph is the thesis of the product, so it settles rather than
   snapping in, and the copy arrives over it.
   ========================================================================== */
.efn-s-hero img{ animation:efn-settle 1.1s var(--m-out) backwards }
.efn-s-hero .efn-s-h1{ animation:efn-rise var(--m-2) var(--m-out) 180ms backwards }
.efn-s-hero .efn-s-hin p{ animation:efn-rise var(--m-2) var(--m-out) 260ms backwards }
.efn-s-hero .efn-s-acts{ animation:efn-rise var(--m-2) var(--m-out) 340ms backwards }
.pcard{ animation:efn-rise var(--m-2) var(--m-out) 180ms backwards }

/* the module grid deals itself out when you switch phase */
.tool{ animation:efn-rise var(--m-2) var(--m-out) backwards }
.tool:nth-child(2){ animation-delay:36ms }
.tool:nth-child(3){ animation-delay:72ms }
.tool:nth-child(4){ animation-delay:108ms }
.tool:nth-child(n+5){ animation-delay:144ms }

/* ==========================================================================
   9 · CONTROLS — feedback on press, not on hover
   §22(d) of the design layer forbids hover transforms, and that stands.
   A press is different: it is a thing the person did, and it should answer.
   ========================================================================== */
.btn:active,.go:active,.calbtn:active,.seg button:active,.opt:active,.fbtn:active{
  opacity:.84;
}
.btn,.go,.calbtn,.opt,.fbtn,.tag,.chip{
  transition:background-color var(--m-1) var(--m-ease),
             border-color var(--m-1) var(--m-ease),
             opacity var(--m-1) var(--m-ease);
}
input,select,textarea{
  transition:border-color var(--m-1) var(--m-ease), box-shadow var(--m-1) var(--m-ease);
}
.efn-s-mini,.efn-s-back{ transition:background-color var(--m-1) var(--m-ease), border-color var(--m-1) var(--m-ease) }

/* ==========================================================================
   10 · THE OFF SWITCH
   Anyone who has asked their system to stop moving things gets a completely
   static app — not a faster one. Print gets the same.
   ========================================================================== */
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{
    animation:none !important;
    transition:none !important;
  }
}
@media print{
  *,*::before,*::after{ animation:none !important; transition:none !important }
}
