/* ============================================================
   Vaxa Idea Flow, app shell (session 2 step 7)
   index.html only: the real app, wired to Supabase.

   Per CLAUDE.md's approved sources: the 1.0 view's own layout
   (#bounce-wrapper, .flow-stage, .flow-focus-layer, .flow-bottom-bar
   at bottom:120px, .flow-bottom-space) is taken from flow-test.html
   and css/flow.css exactly, unchanged, reusing that existing CSS as-is.
   This file only adds the plain body reset flow-test.html/list-test.html
   already both use, the real header's position as a sibling above
   whichever view is showing (flow-test.html has no real header to
   match, since its own .flow-header-band is a decorative test-only
   placeholder, dropped here in favour of the real one), the two states
   with no existing page to copy (hiding the inactive view, and Error),
   and, session 2 step 7 fixes round 2: one deliberate override of
   .flow-stage's own height (item C, see below, needed only because
   this page has a real header sibling flow-test.html doesn't) and the
   flow/list cross-fade transition (item D, also below).
   ============================================================ */

body {
  margin: 0;
  /* Cam's decision, step 7 fixes: a very subtle radial glow behind
     both views, built only from existing tokens (--app-background,
     tokens.css). Fixed so it never moves with page scroll or the
     flow's own custom overscroll bounce (that transform only ever
     touches #bounce-wrapper, never body); doesn't reach the flow
     stage's own layers, card blur or the popups, which keep
     --modal-surface/--modal-backdrop as they are. */
  background: var(--app-background);
  background-attachment: fixed;
  color: var(--text-primary);
  font-family: var(--font-geist);
}

/* Defensive: css/list.css's .list-page sets its own display:flex,
   which would otherwise win the cascade over the native `hidden`
   attribute (equal specificity, declared later). #bounce-wrapper has
   no competing `display` of its own, so this is only load-bearing for
   the list view, but applying it generally costs nothing. */
[hidden] {
  display: none !important;
}

/* ---------- Capture bar never below the fold, flow scheduler rebuild
   ----------
   flow-test.html has no real header sibling above #bounce-wrapper, so
   its approved .flow-stage height:100vh (css/flow.css) is correct
   there. Here #header-root adds its own height on top, which would
   push the approved bottom:120px capture bar (css/flow.css, unchanged)
   down by the header's own height. --app-header-height is set from
   js/app.js, measured live from the real header element (no
   line-height is set on .app-header-title/.app-header-nav-item, so
   this isn't derivable from the stylesheet alone). dvh, not vh, per
   Cam's instruction, so mobile browser chrome resizing doesn't throw
   the gap off. The extra 72px is the required clearance below the
   collapsed bar: .flow-bottom-bar sits flush against .flow-bottom-space
   (bottom:120px matches that element's own height exactly, css/flow.css,
   unchanged), so trimming the stage by header height alone would put
   the bar's own bottom edge exactly on the fold, zero clearance.
   Trimming by header + 72px instead pushes the whole wrapper up that
   much further, landing the bar's bottom edge exactly 72px above the
   fold, by construction, at any viewport size. 84px fallback matches
   MOTION_CONFIG's own fallback in js/app.js. */
#view-stack {
  position: relative;
}

.flow-stage {
  height: calc(100dvh - var(--app-header-height, 84px) - 72px);
  /* css/flow.css's approved min-height:700px ("room to move" on the
     test page, which has no capture-bar-clearance requirement to
     satisfy) would win over a shorter calc() result below ~872px
     total viewport height and push the bar back past the fold at a
     short viewport. Overridden to 0 here only; flow-test.html doesn't
     load this file, so its own 700px is untouched. */
  min-height: 0;
}

/* ---------- D, session 2 step 7 fixes round 2: flow/list transition
   ----------
   Cam's decision: cross-fade, 160ms ease-out, 4px rise on the incoming
   view, matching .details-shell's own entry animation exactly
   (details-fade-rise, css/idea-details.css: same duration, easing and
   4px). No sliding: the outgoing view only ever fades (opacity), never
   moves. #bounce-wrapper already owns its own inline `transform` (the
   custom overscroll bounce, js/app.js's paint()), so animating
   `transform` on it too would fight that; it fades in/out on opacity
   alone, no rise, while #list-view gets the full fade-rise like the
   popup. The header is never touched by either class, so it never
   animates. js/app.js applies these classes only on a real route
   switch after the first paint, and swaps them for an instant toggle
   under prefers-reduced-motion, so the guard below is only a second,
   defensive layer (e.g. a browser setting changed mid-session). */
@keyframes app-view-fade-out {
  from { opacity: 1; }
  to { opacity: 0; }
}

@keyframes app-view-fade-in {
  from { opacity: 0; }
  to { opacity: 1; }
}

@keyframes app-view-fade-rise-in {
  from { opacity: 0; transform: translateY(4px); }
  to { opacity: 1; transform: translateY(0); }
}

#bounce-wrapper.app-view-leaving,
#list-view.app-view-leaving {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  animation: app-view-fade-out 160ms ease-out;
  pointer-events: none;
}

#bounce-wrapper.app-view-entering {
  animation: app-view-fade-in 160ms ease-out;
}

#list-view.app-view-entering {
  animation: app-view-fade-rise-in 160ms ease-out;
}

@media (prefers-reduced-motion: reduce) {
  #bounce-wrapper.app-view-leaving,
  #list-view.app-view-leaving,
  #bounce-wrapper.app-view-entering,
  #list-view.app-view-entering {
    animation: none;
  }
}

/* ---------- Error, R-1.0-16 ----------
   No literal copy exists in either doc for this beyond "states
   plainly that ideas could not be loaded" and "must be visually
   distinct from Empty"; the message text reuses data-layer.js's own
   thrown Error messages verbatim rather than inventing new copy.
   Loading has no separate visual at all: the shell (header, capture
   bar / Add idea trigger) renders immediately and the view is
   indistinguishable from Empty until data arrives, which is already
   the correct Empty treatment per 1.0/2.0's own "capture bar is the
   only action" rule, so nothing extra is drawn for "loading" on
   purpose. */
.app-error-message {
  box-sizing: border-box;
  margin: var(--space-2xl) auto 0;
  padding: 0 var(--space-lg);
  text-align: center;
  font-family: var(--font-geist);
  font-size: var(--type-body-size); /* tokens.css */
  color: var(--color-text-error-on-dark);
}
