/* ── Splitit demo layer ───────────────────────────────────────────────────
   Safe to ship on every screen. Every rule below is either a .dm-* class or
   scoped under html.dm-on, and demo.js only adds .dm-on when the URL carries
   a ?demo flag. With the flag absent the prototype renders byte-identically.

   Phase 1 scope: the arrival moment. A purchase lands, the hero number moves,
   the transaction appears. Nothing here touches the split flow. */

/* Stage sits inside .app so the banner is clipped to the phone frame rather
   than the desktop viewport. */
html.dm-on .app { position: relative; }

/* Floors, not fallbacks. The `, 44px` in var() only applies when the variable
   is UNDEFINED — it does nothing when the variable is defined as 0px, which is
   exactly what the home screen does: standalone sets --statusbar-h and
   --homebar-h to 0 so .app's padding can fall back to the real safe-area
   insets. That collapsed this to 7px and put the notification hard against the
   top edge of the web view instead of 66px down. max() gives it a real floor.
*/
.dm-stage {
  position: absolute;
  top: 0; left: 0; right: 0;
  z-index: 90;
  display: grid;
  justify-items: center;
  gap: 8px;
  padding: calc(max(var(--sat, 0px), var(--statusbar-h, 44px), 44px) + 7px) 10px 0;
  pointer-events: none;
}

/* ── Push notification ─────────────────────────────────────────────────── */
.dm-note {
  width: 100%;
  max-width: 372px;
  display: grid;
  grid-template-columns: 36px 1fr auto;
  gap: 11px;
  align-items: start;
  padding: 11px 13px 12px;
  border-radius: 19px;
  background: color-mix(in srgb, var(--surface) 97%, transparent);
  -webkit-backdrop-filter: blur(20px) saturate(1.5);
  backdrop-filter: blur(20px) saturate(1.5);
  border: 1px solid color-mix(in srgb, var(--line) 75%, transparent);
  box-shadow: 0 16px 40px rgba(0, 0, 0, .38), 0 3px 10px rgba(0, 0, 0, .22);
  pointer-events: auto;
  /* Start off-stage. .in drives it down. */
  transform: translate3d(0, -150%, 0);
  opacity: 0;
  will-change: transform, opacity;
}

/* Spring with a small settle — linear easing here reads as a page load. */
.dm-note.in {
  transform: translate3d(0, 0, 0);
  opacity: 1;
  transition: transform 620ms cubic-bezier(.19, 1.25, .38, 1), opacity 220ms ease-out;
}

.dm-note.out {
  transform: translate3d(0, -150%, 0);
  opacity: 0;
  transition: transform 380ms cubic-bezier(.4, 0, .7, .2), opacity 300ms ease-in 60ms;
}

.dm-note-ic {
  width: 36px; height: 36px;
  display: grid; place-items: center;
  border-radius: 9px;
  background: var(--teal);
  color: var(--accent-ink, #05201f);
}
.dm-note-ic svg { width: 22px; height: 22px; }

.dm-note-tx { min-width: 0; }
.dm-note-tx b {
  display: block;
  font-size: 13.5px; font-weight: 800;
  letter-spacing: -.01em;
  color: var(--ink);
}
.dm-note-tx span {
  display: block;
  margin-top: 2px;
  font-size: 13px; line-height: 1.35;
  color: var(--muted);
}
.dm-note-when {
  font-size: 11.5px; font-weight: 700;
  color: var(--muted);
  white-space: nowrap;
  padding-top: 1px;
}

/* ── Hero number ───────────────────────────────────────────────────────── */
/* Tabular figures stop the digits jittering sideways while they roll. */
html.dm-on .amount { font-variant-numeric: tabular-nums; }

/* Overshoot on the usage bar. The bar arriving slightly past its mark and
   settling back is what makes the change feel physical. */
html.dm-on .meter > span {
  transition: width 900ms cubic-bezier(.34, 1.42, .64, 1);
}

/* A brief lift on the hero while the number is moving, so the eye is pulled
   there before the row lands underneath. */
.dm-lift { animation: dm-lift 760ms cubic-bezier(.25, .9, .3, 1); }
@keyframes dm-lift {
  0%   { transform: translate3d(0, 0, 0); }
  38%  { transform: translate3d(0, -3px, 0); }
  100% { transform: translate3d(0, 0, 0); }
}

/* ── The incoming transaction row ──────────────────────────────────────── */
/* Collapsed to nothing, then driven open. Height is set inline by demo.js
   because auto is not animatable. */
.dm-row {
  overflow: hidden;
  height: 0;
  opacity: 0;
  transform: translate3d(0, -7px, 0);
}
.dm-row.in {
  opacity: 1;
  transform: translate3d(0, 0, 0);
  transition: height 480ms cubic-bezier(.22, 1, .36, 1),
              opacity 340ms ease-out 90ms,
              transform 480ms cubic-bezier(.22, 1, .36, 1);
}

/* Pending shimmer. This is deliberate theatre: an instantly-final state reads
   as fake, a chip that settles reads as a network round trip. */
.dm-shim {
  position: relative;
  overflow: hidden;
}
.dm-shim::after {
  content: '';
  position: absolute; inset: 0;
  background: linear-gradient(100deg,
    transparent 20%,
    color-mix(in srgb, var(--ink) 22%, transparent) 50%,
    transparent 80%);
  transform: translateX(-100%);
  animation: dm-shim 1050ms ease-in-out 2;
}
@keyframes dm-shim { to { transform: translateX(100%); } }
.dm-shim.settled::after { display: none; }

/* ── Presenter affordances ─────────────────────────────────────────────── */
.dm-hint {
  position: absolute;
  bottom: calc(max(var(--sab, 0px), var(--homebar-h, 24px), 24px) + 10px);
  left: 50%;
  transform: translateX(-50%);
  z-index: 91;
  padding: 6px 12px;
  border-radius: 999px;
  background: color-mix(in srgb, var(--ink) 78%, transparent);
  color: var(--surface);
  font: 700 11.5px/1 var(--font, system-ui);
  letter-spacing: .01em;
  white-space: nowrap;
  opacity: .82;
  pointer-events: none;
  transition: opacity 300ms ease;
}
.dm-hint.gone { opacity: 0; }

/* Live-link status pip, only meaningful in ?demo=ws */
.dm-pip {
  position: absolute;
  top: calc(max(var(--sat, 0px), var(--statusbar-h, 44px), 44px) + 12px);
  right: 12px;
  z-index: 92;
  width: 7px; height: 7px;
  border-radius: 50%;
  background: var(--warn, #e0a33c);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--warn, #e0a33c) 22%, transparent);
  transition: background 240ms ease, box-shadow 240ms ease;
}
.dm-pip.live {
  background: var(--teal);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--teal) 22%, transparent);
}

/* ── Reduced motion ───────────────────────────────────────────────────────
   Everything still happens, it just stops moving. The demo remains legible
   for anyone who has the OS preference set. */
@media (prefers-reduced-motion: reduce) {
  .dm-note, .dm-note.in, .dm-note.out { transition: opacity 160ms linear; transform: none; }
  .dm-row.in { transition: opacity 200ms linear; transform: none; }
  html.dm-on .meter > span { transition: width 260ms linear; }
  .dm-lift { animation: none; }
  .dm-shim::after { animation: none; display: none; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   Lifecycle — pending → posted

   A pending purchase that qualifies shows its split up front, but ghosted. The
   shape is real, the state is not yet. When the merchant settles, the same
   elements go solid rather than being redrawn, so the room watches the promise
   turn into the thing itself.
   ═══════════════════════════════════════════════════════════════════════ */

/* Tag crossfade, so a row changing state is legible from the back of a room.
   Applied to the tag itself — `.tx .tag` is display:block on purpose, sitting
   on its own line under the amount, and any wrapper here breaks that. */
.tx .dm-row .tag { transition: opacity 200ms ease; }
.tx .dm-row .tag.dm-fade { opacity: 0; }

/* A settled row gets one quiet pulse. Enough to catch the eye mid-sentence,
   not enough to look like an error state. */
.dm-posted { animation: dm-posted 1400ms cubic-bezier(.25, .9, .3, 1); }
@keyframes dm-posted {
  0%   { background: color-mix(in srgb, var(--teal) 17%, transparent); }
  100% { background: transparent; }
}

/* ── Planned, not yet real ─────────────────────────────────────────────── */
/* The body swaps between the prototype's own components as a transaction
   moves from pending to posted. One crossfade, so the change is not a jump
   cut, and no new visual language. */
.dm-swap { animation: dm-swap 420ms cubic-bezier(.22, 1, .36, 1); }
@keyframes dm-swap {
  0%   { opacity: 0; transform: translate3d(0, 8px, 0); }
  100% { opacity: 1; transform: none; }
}

@media (prefers-reduced-motion: reduce) {
  .dm-posted { animation: none; }
  .dm-swap { animation: none; }
  .tx .dm-row .tag { transition: none; }
}
