/* ==========================================================================
   Takahashi Properties — motion

   Petals drift behind the app. Screens slide in and out as you move between
   them (motion.js does the choreography, the keyframes are here), and what
   you point at answers: buttons lift, the pink ones catch a sheen, doors
   glow where the pointer is, clickable rows show a pink edge.

   One easing everywhere (--ease), a fifth to half a second, and nothing
   loops, bounces or pulses. Reduced motion, or <html data-motion="off">
   (the test harness), turns it all off.
   ========================================================================== */

/* No `to`: each piece ends at its own look. A door that's shut (.soon, 45%)
   used to rise to full strength and then drop to grey. */
@keyframes enter {
  from { opacity: 0; transform: translateY(8px); }
}

@keyframes toast-in {
  from { opacity: 0; transform: translateY(10px) scale(0.98); }
  to   { opacity: 1; transform: none; }
}

.enter { animation: enter 0.4s var(--ease) backwards; }

/* --------------------------------------------------------------------------
   Falling blossom

   Fall carries the vertical travel and the tumble; sway is animated on
   margin-left so the two never fight over `transform`. Every petal gets a
   different column, size, speed, delay and opacity — anything repeating on
   a grid reads as a screensaver rather than weather.

   Those per-petal values live on the spans in index.html rather than in
   nth-child rules here, so the number of petals is just how many spans
   there are. Each delay is negative, which starts the animation part-way
   through: the sky is already full on load instead of filling from the top.
   -------------------------------------------------------------------------- */
/* The blossom in the logo does not fall straight down, and it does not all
   fall at one angle. Tracking petals across the GIF gives drifts anywhere
   from 10 to 50 degrees off vertical, always to the right — so each petal
   carries its own --dx and the sky has a spread of angles rather than a
   single slope.

   The sideways travel is in vh, the same unit as the fall, which is what
   makes it an angle: the ratio holds at any viewport, where a percentage
   would flatten on a wide screen and steepen on a narrow one.

   Sway is folded into this one keyframe as waypoints either side of the
   line, rather than run as a second animation. Two animations cannot share
   `transform`, and the old workaround — swaying on margin-left — animates
   layout, which is affordable at 14 petals and not at 200. */
@keyframes petal-fall {
  0%   { translate: 0 0; opacity: 0; }
  7%   { opacity: var(--o); }
  25%  { translate: calc(var(--dx) * 0.25 + var(--sway)) 32.5vh; }
  50%  { translate: calc(var(--dx) * 0.5  - var(--sway)) 65vh; }
  75%  { translate: calc(var(--dx) * 0.75 + var(--sway)) 97.5vh; }
  93%  { opacity: var(--o); }
  100% { translate: var(--dx) 130vh; opacity: 0; }
}

/* `rotate` is its own property, so the tumble composes with the fall
   instead of overwriting it */
@keyframes petal-spin {
  from { rotate: 0deg; }
  to   { rotate: var(--spin); }
}

.petals span {
  animation:
    petal-fall var(--fall) linear var(--delay) infinite,
    petal-spin var(--fall) linear var(--delay) infinite;
}


/* --------------------------------------------------------------------------
   Screens arriving
   -------------------------------------------------------------------------- */
.choices.enter { animation: none; }
.choices.enter .choice { animation: enter 0.5s var(--ease) backwards; }
.choices.enter .choice:nth-child(1) { animation-delay: 0.04s; }
.choices.enter .choice:nth-child(2) { animation-delay: 0.10s; }
.choices.enter .choice:nth-child(3) { animation-delay: 0.16s; }
.choices.enter .choice:nth-child(4) { animation-delay: 0.22s; }

.money.enter { animation: none; }
.money.enter .money-item { animation: enter 0.45s var(--ease) backwards; }
.money.enter .money-item:nth-child(1) { animation-delay: 0.02s; }
.money.enter .money-item:nth-child(2) { animation-delay: 0.07s; }
.money.enter .money-item:nth-child(3) { animation-delay: 0.12s; }
.money.enter .money-item:nth-child(4) { animation-delay: 0.17s; }

.steps.enter { animation: none; }
.steps.enter .step { animation: enter 0.45s var(--ease) backwards; }
.steps.enter .step:nth-child(1) { animation-delay: 0.04s; }
.steps.enter .step:nth-child(2) { animation-delay: 0.11s; }
.steps.enter .step:nth-child(3) { animation-delay: 0.18s; }

/* The success screen's mark settles in after the card */
@keyframes bloom {
  from { opacity: 0; transform: scale(0.82) rotate(-14deg); }
  to   { opacity: 1; transform: none; }
}
.done-mark { animation: bloom 0.55s var(--ease) backwards; animation-delay: 0.08s; }

/* --------------------------------------------------------------------------
   Moving between screens (motion.js)

   The screen being left is lifted into a ghost over the page and slides
   away; the new one slides in behind it. Deeper screens come from the
   right, the way back from the left; Realtor ⇄ Manager crossfades; a door
   opening into its page rises in under the growing card.
   -------------------------------------------------------------------------- */
@keyframes page-out-forward { to { opacity: 0; transform: translateX(-30px); } }
@keyframes page-out-back    { to { opacity: 0; transform: translateX(30px); } }
@keyframes page-out-fade    { to { opacity: 0; transform: scale(0.985); } }
@keyframes page-in-forward  { from { opacity: 0; transform: translateX(36px); } }
@keyframes page-in-back     { from { opacity: 0; transform: translateX(-36px); } }
@keyframes page-in-fade     { from { opacity: 0; transform: scale(1.012); } }
@keyframes page-in-morph    { from { opacity: 0; transform: translateY(12px); } }

.page-ghost {
  position: fixed;
  z-index: 5;
  pointer-events: none;
  animation: page-out-forward 0.2s var(--ease) both;
}
.page-ghost.out-back { animation-name: page-out-back; }
.page-ghost.out-fade { animation-name: page-out-fade; animation-duration: 0.2s; }
/* What was already on screen doesn't arrive a second time on its way out */
.page-ghost * { animation: none !important; transition: none !important; }

.page-in-forward { animation: page-in-forward 0.44s var(--ease) 0.07s backwards; }
.page-in-back    { animation: page-in-back 0.44s var(--ease) 0.07s backwards; }
.page-in-fade    { animation: page-in-fade 0.4s var(--ease) 0.06s backwards; }
.page-in-morph   { animation: page-in-morph 0.44s var(--ease) 0.18s backwards; }

/* A door opening: the card grows to the page, its name flies to the heading */
.morph-card {
  position: fixed;
  z-index: 55;                 /* under the top line (60) */
  pointer-events: none;
  background: var(--surface);
  border: 1px solid var(--accent-line);
  box-shadow: var(--lift), var(--bevel);
}
.morph-title {
  position: fixed;
  z-index: 56;
  pointer-events: none;
  transform-origin: top left;
  white-space: nowrap;
  line-height: 1.2;
}

/* Signing in (motion.js leaveSignIn → enterHome). The sign-in screen is
   pinned over the page while it goes: the card sinks back and dissolves,
   the blossom behind it lifts away like a curtain, and the logo (a flying
   copy, .morph-logo) rises into the top line's brand mark. The top line
   drops in and home rises up from beneath. */
.signin-leaving {
  z-index: 58;                 /* over the page, under the flying logo */
  pointer-events: none;
}
/* Only transform and opacity move anywhere in the sign-in: a blur is redrawn
   every frame, and made the words stutter. */
.signin-leaving .auth-card { animation: signin-card-out 0.65s var(--ease) both; will-change: transform, opacity; }
.signin-leaving .auth-logo { visibility: hidden; }
.signin-leaving .auth-foot { animation: signin-card-out 0.4s var(--ease) both; }
.signin-leaving .petals-dense { animation: signin-petals-out 0.9s ease-out both; }
@keyframes signin-card-out {
  to { opacity: 0; transform: translateY(14px) scale(0.93); }
}
@keyframes signin-petals-out {
  to { opacity: 0; transform: translateY(-4vh); }
}

.morph-logo {
  position: fixed;
  z-index: 61;                 /* over the top line, which it lands in */
  pointer-events: none;
  transform-origin: center;
  filter: drop-shadow(0 18px 30px var(--accent-line));
  will-change: transform, opacity;
}

/* Home and the top line wait, unseen, while the logo fills the screen, and
   come in as it retreats to the corner (the rest of home rises in piece by
   piece, motion.riseAround). Home's own greeting ("Good morning, Karina")
   is the one thing shown meanwhile: it flies large under the big logo and
   settles into its place (motion.flyGreeting), over the fading card. */
.signin-hold { visibility: hidden; pointer-events: none; }
.signin-hold .signin-greet { visibility: visible; }
.signin-greet { position: relative; z-index: 59; }

@keyframes topline-in { from { opacity: 0; transform: translateY(-100%); } }
.topline-in { animation: topline-in 0.7s var(--ease) 0.08s backwards; }

/* A fresh screen's rows and cards come in one after another */
@keyframes rise-in { from { opacity: 0; transform: translateY(8px); } }
.page-fresh .tbl tbody tr:nth-child(-n+14),
.page-fresh .payee,
.page-fresh .sale-card,
.page-fresh .rate-preview > div {
  animation: rise-in 0.4s var(--ease) backwards;
}
.page-fresh .tbl tbody tr:nth-child(1), .page-fresh .payee:nth-child(1), .page-fresh .sale-card:nth-child(1), .page-fresh .rate-preview > div:nth-child(1) { animation-delay: 0.08s; }
.page-fresh .tbl tbody tr:nth-child(2), .page-fresh .payee:nth-child(2), .page-fresh .sale-card:nth-child(2), .page-fresh .rate-preview > div:nth-child(2) { animation-delay: 0.11s; }
.page-fresh .tbl tbody tr:nth-child(3), .page-fresh .payee:nth-child(3), .page-fresh .sale-card:nth-child(3), .page-fresh .rate-preview > div:nth-child(3) { animation-delay: 0.14s; }
.page-fresh .tbl tbody tr:nth-child(4), .page-fresh .payee:nth-child(4) { animation-delay: 0.17s; }
.page-fresh .tbl tbody tr:nth-child(5), .page-fresh .payee:nth-child(5) { animation-delay: 0.2s; }
.page-fresh .tbl tbody tr:nth-child(6), .page-fresh .payee:nth-child(6) { animation-delay: 0.23s; }
.page-fresh .tbl tbody tr:nth-child(7), .page-fresh .payee:nth-child(7) { animation-delay: 0.26s; }
.page-fresh .tbl tbody tr:nth-child(8), .page-fresh .payee:nth-child(8) { animation-delay: 0.29s; }
.page-fresh .tbl tbody tr:nth-child(9)  { animation-delay: 0.32s; }
.page-fresh .tbl tbody tr:nth-child(10) { animation-delay: 0.35s; }
.page-fresh .tbl tbody tr:nth-child(11) { animation-delay: 0.38s; }
.page-fresh .tbl tbody tr:nth-child(12) { animation-delay: 0.41s; }
.page-fresh .tbl tbody tr:nth-child(13) { animation-delay: 0.44s; }
.page-fresh .tbl tbody tr:nth-child(14) { animation-delay: 0.47s; }

/* --------------------------------------------------------------------------
   What you point at
   -------------------------------------------------------------------------- */
/* Buttons lift a touch, and press in when clicked */
.btn:hover { transform: translateY(-1px); }
.btn:active { transform: translateY(0) scale(0.97); transition-duration: 0.08s; }
.btn:disabled, .btn:disabled:hover, .btn:disabled:active { transform: none; }

/* The pink buttons catch a sheen as the pointer arrives */
.btn-primary { position: relative; overflow: hidden; }
.btn-primary::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: linear-gradient(105deg, transparent 32%, rgba(255, 255, 255, 0.34) 47%,
                              rgba(255, 255, 255, 0.08) 56%, transparent 68%);
  transform: translateX(-115%);
  transition: transform 0.75s var(--ease);
  pointer-events: none;
}
.btn-primary:hover::after { transform: translateX(115%); }
.btn-primary:disabled::after { display: none; }

/* Arrows nudge the way they point */
.choice-go svg, .backlink svg { transition: transform 0.3s var(--ease); }
.choice:hover .choice-go svg { transform: translateX(4px); }
.backlink:hover svg { transform: translateX(-3px); }

.hub-link { transition: color 0.2s var(--ease), background 0.2s var(--ease), transform 0.24s var(--ease), box-shadow 0.24s var(--ease); }
.hub-link:hover { transform: translateY(-2px); box-shadow: var(--lift-sm); }

/* The home pages' doors grow under the pointer and press in when clicked, so
   they read as buttons and stand apart from the money cards below, which
   don't move at all. */
.choice { transition: transform 0.32s var(--ease), box-shadow 0.32s var(--ease); }
.choice:hover {
  z-index: 1;
  transform: translateY(-6px) scale(1.045);
  box-shadow: 0 24px 48px -22px rgba(0, 0, 0, 0.75), 0 0 0 1px var(--accent-wash), var(--bevel);
}
.choice:active { transform: translateY(-2px) scale(1.02); transition-duration: 0.1s; }

/* A glow that follows the pointer across a door or a money card (--mx/--my
   from motion.js). The money cards shine but don't move: only the doors grow. */
.choice, .money-item { isolation: isolate; }
.choice::before, .money-item::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  background: radial-gradient(280px circle at var(--mx, 50%) var(--my, 0%), rgba(240, 179, 189, 0.13), transparent 65%);
  opacity: 0;
  transition: opacity 0.35s var(--ease);
  pointer-events: none;
}
.choice:hover::before, .money-item:hover::before { opacity: 1; }
.choice.soon::before { display: none; }

/* A row that opens something shows a pink edge */
.tbl tbody tr > td:first-child { transition: box-shadow 0.22s var(--ease); }
.tbl tbody tr.row-link:hover > td:first-child { box-shadow: inset 3px 0 0 var(--accent); }

/* A field you click into glows */
.field:focus { box-shadow: 0 0 0 3px var(--accent-wash), 0 0 26px -8px var(--accent-line); }

/* The Realtor / Manager switch: one highlight that slides between them */
.modes.has-pill { position: relative; }
.modes-pill {
  position: absolute;
  top: 3px;
  bottom: 3px;
  left: 0;
  width: 0;
  border-radius: 10px;
  background: var(--surface);
  box-shadow: 0 3px 12px -5px rgba(0, 0, 0, 0.6);
  transition: left 0.4s var(--ease), width 0.4s var(--ease);
}
.modes.has-pill .mode { position: relative; z-index: 1; }
.modes.has-pill .mode[aria-pressed="true"] { background: transparent; }
/* On the Manager side the highlight is pink. The pink is a layer that fades
   in over the plain one, since a gradient can't be transitioned. */
.modes-pill::before {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: var(--accent-grad);
  opacity: 0;
  transition: opacity 0.4s var(--ease);
}
.modes[data-side="manager"] .modes-pill { box-shadow: 0 6px 18px -8px var(--accent-line); }
.modes[data-side="manager"] .modes-pill::before { opacity: 1; }
.modes[data-side="manager"] .mode[aria-pressed="true"] { color: var(--accent-ink); }
@media (max-width: 620px) { .modes-pill { top: 2px; bottom: 2px; } }

/* Lists open out of the field that owns them */
div.dd-pop { transform-origin: top center; }
div.dd-pop[data-side="up"] { transform-origin: bottom center; }
@keyframes dd-in    { from { opacity: 0; transform: translateY(-6px) scale(0.97); } }
@keyframes dd-in-up { from { opacity: 0; transform: translateY(6px) scale(0.97); } }

/* Dialogs rise into place as the page behind them blurs */
.modal-content {
  opacity: 0;
  transform: translateY(18px) scale(0.965);
  transition: transform 0.36s var(--ease), opacity 0.24s var(--ease);
}
.modal-overlay.active .modal-content { opacity: 1; transform: none; }

/* Copied: the copy icon turns to a tick for a moment */
@keyframes tick-in { from { opacity: 0; transform: scale(0.6); } }
@keyframes tick-draw { from { stroke-dashoffset: 24; } }
.copy-chip .copy-ok { display: none; color: var(--pos); }
.copy-chip.is-copied { border-color: rgba(134, 201, 164, 0.55); background: rgba(134, 201, 164, 0.08); }
.copy-chip.is-copied .copy-icon { display: none; }
.copy-chip.is-copied .copy-ok { display: block; animation: tick-in 0.3s var(--ease) backwards; }
.copy-chip.is-copied .copy-ok polyline,
.btn.is-copied svg polyline { stroke-dasharray: 24; animation: tick-draw 0.4s var(--ease) backwards; }
.btn.is-copied { color: var(--pos); }

/* Messages slide away, then the gap closes */
@keyframes toast-out { to { opacity: 0; transform: translateX(28px); } }
.toast.leaving { animation: toast-out 0.2s var(--ease) forwards; }
.toast.closing {
  overflow: hidden;
  height: 0 !important;
  padding-top: 0;
  padding-bottom: 0;
  margin-top: -10px;
  border-width: 0;
  transition: height 0.24s var(--ease), padding 0.24s var(--ease), margin 0.24s var(--ease);
}

/* The test harness reads each screen as it lands */
html[data-motion="off"] *, html[data-motion="off"] *::before, html[data-motion="off"] *::after {
  animation: none !important;
  transition: none !important;
}

@media (prefers-reduced-motion: reduce) {
  .petals { display: none; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-delay: 0ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}
