/* arete-motion.css
 * The shared motion system for every Arete surface.
 *
 * WHAT THIS IS FOR. The product felt inert — correct, polished, and dead. The
 * fix is not playfulness. Arete sells calm to people who are anxious about
 * their house, and confetti would cheapen a judgment product. What makes
 * premium software feel alive is RESPONSIVENESS: the interface notices what
 * you did and reacts proportionally.
 *
 * THE RULES, in order of importance:
 *
 * 1. Motion acknowledges, it never performs. Something moves because YOU did
 *    something. Nothing loops, nothing idles, nothing demands attention.
 * 2. Under 250ms, always. Past that a transition stops reading as response and
 *    starts reading as waiting.
 * 3. Transform and opacity only. Those are the two properties a browser can
 *    animate on the compositor without re-laying-out the page — animating
 *    height, top, or width would cost real frames on a mid-range phone.
 * 4. Nothing moves more than a few pixels. Big travel is theatre.
 * 5. `prefers-reduced-motion` removes the motion and keeps the meaning. Every
 *    animation here is decoration on a state change that is already visible
 *    some other way — colour, position, content — so honouring the preference
 *    never costs information. For a product about calm, ignoring that setting
 *    would be its own kind of failure.
 *
 * COST. Pure CSS, no library, no dependency, no build step, no JavaScript
 * required for anything except the staggered reveal (which degrades to
 * "everything is simply visible" if the script never runs). It is a few
 * hundred bytes gzipped and there is nothing here to maintain when a framework
 * releases a major version, because there is no framework.
 */

/* ── Easing ───────────────────────────────────────────────────────────────
 * One curve, used everywhere: fast out of the gate, gentle into the stop.
 * Nothing overshoots — a bounce is a personality Arete does not have.
 */
:root {
  --a-ease: cubic-bezier(0.22, 0.61, 0.36, 1);
  --a-fast: 140ms;
  --a-base: 200ms;
}

/* ── Reveal ───────────────────────────────────────────────────────────────
 * Content settles in rather than snapping. Used on report sections and
 * dashboard cards so a page reads as "assembling" instead of "already over".
 * The stagger is applied inline as --a-i by the page; without it every item
 * simply reveals at once, which is a perfectly good outcome.
 */
@keyframes a-rise {
  from { opacity: 0; transform: translate3d(0, 6px, 0); }
  to   { opacity: 1; transform: none; }
}
.a-reveal {
  animation: a-rise var(--a-base) var(--a-ease) both;
  animation-delay: calc(var(--a-i, 0) * 45ms);
}

/* ── Press ────────────────────────────────────────────────────────────────
 * Buttons and chips give under the finger. This is the single highest-value
 * microinteraction on a touch device: it confirms the tap landed before the
 * network has done anything at all.
 */
.a-press { transition: transform var(--a-fast) var(--a-ease); }
.a-press:active { transform: scale(0.97); }

/* ── Lift ─────────────────────────────────────────────────────────────────
 * A card acknowledges the pointer. Deliberately tiny: 1px and a shadow.
 */
.a-lift { transition: transform var(--a-base) var(--a-ease), box-shadow var(--a-base) var(--a-ease); }
.a-lift:hover { transform: translate3d(0, -1px, 0); box-shadow: 0 6px 20px rgba(26,26,26,0.07); }

/* ── Mark ─────────────────────────────────────────────────────────────────
 * The moment a checkbox is satisfied. One quick settle, no celebration —
 * checking off a repair on your house is a small relief, not a victory.
 */
@keyframes a-mark {
  0%   { transform: scale(1); }
  40%  { transform: scale(1.12); }
  100% { transform: scale(1); }
}
.a-mark { animation: a-mark 220ms var(--a-ease); }

/* ── Count ────────────────────────────────────────────────────────────────
 * A number that changed draws the eye for exactly one beat, via colour rather
 * than movement so it works mid-scroll.
 */
@keyframes a-tick {
  0%   { color: var(--bronze-deep, #A56F30); }
  100% { color: inherit; }
}
.a-tick { animation: a-tick 600ms var(--a-ease); }

/* ── Progress ─────────────────────────────────────────────────────────────
 * A fill that eases rather than jumps, so completing a step feels like
 * progress being made rather than a variable being reassigned.
 */
.a-progress { transition: width 320ms var(--a-ease); }

/* ── Focus ────────────────────────────────────────────────────────────────
 * A visible, consistent focus ring on every interactive element. This is an
 * accessibility requirement first and a polish detail second, which is why it
 * lives in the motion system rather than being left to each page.
 */
.a-focus:focus-visible {
  outline: 2px solid var(--bronze, #CC8A3D);
  outline-offset: 2px;
  border-radius: 6px;
}


/* ── Advance ──────────────────────────────────────────────────────────────
 * A multi-step form that swaps screens instantly reads as a stack of pages.
 * The same form, where each step ARRIVES from the direction you are travelling,
 * reads as progress. This is the single highest-value motion in the intake and
 * it costs one transform.
 *
 * Still inside the rules: one axis, 10px, 220ms, transform and opacity only.
 */
@keyframes a-advance {
  from { opacity: 0; transform: translate3d(10px, 0, 0); }
  to   { opacity: 1; transform: none; }
}
.a-advance { animation: a-advance 220ms var(--a-ease) both; }

/* Going back is the same motion mirrored, so the direction of travel is legible
 * without reading anything. */
@keyframes a-retreat {
  from { opacity: 0; transform: translate3d(-10px, 0, 0); }
  to   { opacity: 1; transform: none; }
}
.a-retreat { animation: a-retreat 220ms var(--a-ease) both; }

/* ── Stagger ──────────────────────────────────────────────────────────────
 * Sections within a newly arrived step settle in sequence rather than landing
 * as one slab. Capped deliberately: past the fifth item the delay stops
 * growing, because a long form would otherwise make someone wait to read the
 * bottom of their own page.
 * Scoped to the ACTIVE step on purpose. `a-rise` starts at opacity 0 with a
 * `both` fill, so applying it to a hidden step would leave that step's contents
 * holding the start frame — invisible and unclickable — until something
 * happened to restart the animation. Requiring `.active` means the rule only
 * begins to match at the moment the step is shown, which is also exactly when
 * the animation should run.
 */
.a-seq.active > * { animation: a-rise var(--a-base) var(--a-ease) both; }
.a-seq.active > *:nth-child(1) { animation-delay: 0ms; }
.a-seq.active > *:nth-child(2) { animation-delay: 40ms; }
.a-seq.active > *:nth-child(3) { animation-delay: 80ms; }
.a-seq.active > *:nth-child(4) { animation-delay: 120ms; }
.a-seq.active > *:nth-child(n+5) { animation-delay: 150ms; }

/* ── The preference wins ──────────────────────────────────────────────────
 * Everything above is decoration on a state change that is already legible
 * without it. Someone who has asked their operating system for less motion
 * gets the full product, minus the movement.
 */
@media (prefers-reduced-motion: reduce) {
  .a-reveal,
  .a-mark,
  .a-tick,
  .a-advance,
  .a-retreat,
  .a-seq.active > * {
    animation: none !important;
  }
  .a-press,
  .a-lift,
  .a-progress {
    transition: none !important;
  }
  .a-lift:hover { transform: none; }
  .a-press:active { transform: none; }
}
