/* ============================================================
   Vaxa Idea Flow, flow motion test (revision 4)
   Behaviour: R-1.0-5 to R-1.0-10, R-1.0-17 to R-1.0-19, R-PRI-3,
   R-CARD-10 in functionality-v3.md.
   Layout: Figma FlowScreen, node 8:69, file DOpr9xrC1IHjShxiuDxVKr.

   CAM'S REVISION, ROUND 3 (session 2 step 2, not yet in the docs):
   - .flow-bottom-bar is now position:fixed (was absolute inside the
     stage): "its own layer above everything" per item 6, unaffected by
     page scroll, the bounce, or its own expansion.
   - New: .flow-focus-layer, the blur+dim shown while the capture bar
     is expanded (item 6). Both its blur and its dim are marked as
     Cam's revision, prototype values below, tunable from
     flow-test.html.
   - Removed: the transition-based calm entrance and its --entrance-dur
     property. Every entrance (initial load and, as of this round,
     State 2 arrivals too) uses the .is-popping keyframe instead.

   ROUND 4 (session 2 step 3, not yet in the docs), item 4, reverses
   part of round 3's arrangement on Cam's decision: the capture bar
   moves with the page. #bounce-wrapper now holds the stage AND
   .flow-bottom-bar (back to position:absolute, no longer fixed), so
   both get the custom overscroll bounce transform (js in
   flow-test.html) together; only .flow-focus-layer, a full-viewport
   dim/blur with no reason to scroll, stays a fixed sibling outside it.
   ============================================================ */

body {
  margin: 0;
  background: var(--bg-linen);
  color: var(--text-primary);
  font-family: var(--font-geist);
}

/* Round 3: the only element the custom overscroll bounce (item 5)
   ever transforms. Kept separate from the capture bar / focus layer
   on purpose, see file header. */
#bounce-wrapper {
  position: relative;
}

.flow-stage {
  position: relative;
  width: 100%;
  height: 100vh;
  min-height: 700px; /* prototype default, not from the brief: room to move at small viewports */
  overflow: hidden;
}

/* Cam's revision, prototype: reduced from 240px (round 2) to 120px
   (round 3), enough scrollHeight for the custom bounce to have
   somewhere to rebound from. */
.flow-bottom-space {
  height: 120px;
}

/* Figma FlowScreen node 8:69: header band 84px at top. */
.flow-header-band {
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  height: 84px;
  background: rgba(230, 244, 236, 0.05);
  border-bottom: 1px dashed rgba(230, 244, 236, 0.2);
  pointer-events: none;
  z-index: 1;
}

/* Figma FlowScreen node 8:69: capture bar centred near the bottom,
   idea count line below it. Round 4, item 4 (reverses round 3's
   position:fixed): absolute inside #bounce-wrapper now, "the capture
   bar moves with the page", so both native scroll and the custom
   overscroll bounce transform on #bounce-wrapper move it exactly like
   the stage. Sits flush above .flow-bottom-space (bottom: 120px,
   matching that element's own height exactly): the decision was "120px
   of space below it" at the bottom of the page, not that plus the old
   fixed-position 32px offset, which no longer applies now that this
   isn't anchored to the viewport. Expanding it still never resizes
   anything else: it was never in the document flow (R-CAP-6 grows
   .capture-expand-wrap in place, inside this absolutely-positioned
   box). */
.flow-bottom-bar {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 120px; /* matches .flow-bottom-space's own height, so exactly that much space shows below once scrolled to the bottom */
  z-index: 20; /* above .flow-focus-layer, so it stays interactive while expanded */
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
}

.flow-capture-bar-root {
  display: flex;
  justify-content: center;
}

.flow-idea-count {
  margin: 0;
  font-family: var(--font-geist-mono);
  font-size: 11px;
  color: var(--text-muted);
  text-transform: uppercase;
}

/* Round 3, item 6: shown only while the capture bar is expanded
   (detected from outside, js/flow-test.html). Covers the cards and
   header, not the capture bar, purely by z-index: .flow-bottom-bar
   sits above this regardless of this layer's own footprint. Blur and
   dim are both Cam's revision, prototype: no source beyond this task,
   tunable via CSS custom properties set from flow-test.html's sliders. */
.flow-focus-layer {
  /* Round 5: absolute inside #bounce-wrapper (was fixed, outside it),
     so it shares the capture bar's stacking layer and sits below it. */
  position: absolute;
  inset: 0;
  z-index: 10;
  opacity: 0;
  pointer-events: none;
  backdrop-filter: blur(var(--focus-blur-px, 8px)); /* Cam's revision, prototype */
  background: color-mix(in srgb, var(--scrim) var(--focus-dim-pct, 40%), transparent); /* Cam's revision, prototype */
  transition: opacity 200ms ease-out;
}

.flow-focus-layer.is-active {
  opacity: 1;
  pointer-events: auto;
}

/* Outer layer: position only. Written every frame by the physics loop
   in js/flow.js as a plain translate3d, never a CSS animation. */
.flow-pos {
  position: absolute;
  left: 0;
  top: 0;
  width: 240px; /* 3B desktop card width, keeps the physics math simple */
  will-change: transform;
  z-index: 0;
}

/* Middle layer: exit/highlight transitions, and the pop-settle
   keyframe (below) for every entrance. */
.flow-fx {
  width: 240px;
  will-change: opacity, transform;
  opacity: 0;
  transform: scale(0.96);
  transition-property: opacity, transform, filter;
  transition-timing-function: ease-in-out;
  transition-duration: 400ms;
}

.flow-fx.is-visible {
  opacity: 1;
  transform: scale(1);
}

.flow-fx.is-exiting {
  opacity: 0;
  transform: scale(0.97);
  transition-duration: var(--exit-dur, 350ms);
  transition-timing-function: ease-in;
}

/* Scale + glow. The fill/star-reveal half of the look reuses the
   card's own .force-hover hook (css/floating-card.css, added for
   card-test.html's forced-hover rows) rather than duplicating that
   CSS here, so "fill as in the hover state" is literally the same
   rule, not a copy of it. Left in place, unused, while
   js/flow.js's HIGHLIGHT_ENABLED is false. */
.flow-fx.is-highlighted {
  transform: scale(var(--highlight-scale, 1.03));
  filter: drop-shadow(0 0 16px color-mix(in srgb, var(--color-brand-accnet-B) 45%, transparent));
  transition-duration: var(--highlight-dur, 600ms);
  transition-timing-function: ease-in-out;
}

/* Every entrance, initial load and (round 3) State 2 arrivals alike: a
   real @keyframes animation, not a transition, since it overshoots on
   both scale and rotation with an intermediate stop, which a
   transition can't express. --pop-sign is 1 or -1, chosen randomly per
   card in js/flow.js; --pop-tilt is a positive magnitude, so the 0%
   and 60% rotations always land on opposite sides of zero, whichever
   sign this card got. */
@keyframes flow-pop-settle {
  0% {
    opacity: 0;
    transform: scale(var(--pop-start-scale, 0.85)) translateY(var(--pop-rise, 12px))
      rotate(calc(var(--pop-sign, 1) * var(--pop-tilt, 2deg)));
  }
  60% {
    opacity: 1;
    transform: scale(var(--pop-overshoot-scale, 1.04)) translateY(-2px)
      rotate(calc(var(--pop-sign, 1) * -0.25 * var(--pop-tilt, 2deg)));
  }
  100% {
    opacity: 1;
    transform: scale(1) translateY(0) rotate(0deg);
  }
}

.flow-fx.is-popping {
  animation: flow-pop-settle var(--pop-dur, 550ms) cubic-bezier(0.34, 1.56, 0.64, 1) forwards;
}
