/* TradeLoft motion layer.
 * Everything here is gated on html.tl-motion, which a tiny inline script in <head>
 * adds only when the visitor has NOT asked for reduced motion. Without JS (or with
 * reduced motion) every element renders in its final, static state.
 * Only transform/opacity are animated. Compliance content (signup consent, legal
 * pages, footer) is never targeted.
 */
:root {
  --tl-ease-out: cubic-bezier(0.2, 0.7, 0.2, 1);
  --tl-ease-spring: cubic-bezier(0.34, 1.4, 0.5, 1);
}

/* ---------- Hero entrance (index) ----------
 * Pure CSS, keyed only on html.tl-motion (set in <head> before first paint), so the
 * first painted frame is already the animation's start state: nothing renders, hides,
 * then re-appears. html.tl-seen (sessionStorage) skips the entrance on return visits
 * in the same session, so going back to the home page doesn't replay it. */
@keyframes tlRise { from { opacity: 0; transform: translateY(18px); } to { opacity: 1; transform: none; } }
.tl-motion:not(.tl-seen) .tl-hero-grid > div:first-child > * { animation: tlRise 0.8s var(--tl-ease-out) both; }
.tl-motion:not(.tl-seen) .tl-hero-grid > div:first-child > :nth-child(1) { animation-delay: 0.05s; }
.tl-motion:not(.tl-seen) .tl-hero-grid > div:first-child > :nth-child(2) { animation-delay: 0.12s; }
.tl-motion:not(.tl-seen) .tl-hero-grid > div:first-child > :nth-child(3) { animation-delay: 0.22s; }
.tl-motion:not(.tl-seen) .tl-hero-grid > div:first-child > :nth-child(4) { animation-delay: 0.32s; }
.tl-motion:not(.tl-seen) .tl-hero-grid > div:first-child > :nth-child(5) { animation-delay: 0.42s; }

/* ---------- Trade ticket: the swap ---------- */
@keyframes tlTicketInL { from { opacity: 0; transform: translateX(-28px) rotate(-1.5deg); } to { opacity: 1; transform: none; } }
@keyframes tlTicketInR { from { opacity: 0; transform: translateX(28px) rotate(1.5deg); } to { opacity: 1; transform: none; } }
@keyframes tlNudgeDown { 0%, 100% { transform: none; } 45% { transform: translateY(7px); } }
@keyframes tlNudgeUp { 0%, 100% { transform: none; } 45% { transform: translateY(-7px); } }
@keyframes tlSwapIn { from { opacity: 0; transform: scale(0.55) rotate(-180deg); } to { opacity: 1; transform: none; } }
@keyframes tlSwapTurn { from { transform: rotate(0deg); } to { transform: rotate(180deg); } }
@keyframes tlRing { from { opacity: 0.55; transform: scale(1); } to { opacity: 0; transform: scale(3.2); } }
@keyframes tlFadeIn { from { opacity: 0; } to { opacity: 1; } }

.tl-motion:not(.tl-seen) .tl-ticket-stack > .tl-ticket:first-child { animation: tlTicketInL 0.7s var(--tl-ease-out) 0.25s both, tlNudgeDown 0.55s ease-in-out 1.25s; }
.tl-motion:not(.tl-seen) .tl-ticket-stack > .tl-ticket:nth-child(3) { animation: tlTicketInR 0.7s var(--tl-ease-out) 0.4s both, tlNudgeUp 0.55s ease-in-out 1.25s; }
.tl-motion:not(.tl-seen) .tl-ticket-stack .tl-ticket-swap { animation: tlSwapIn 0.6s var(--tl-ease-spring) 0.8s both; }
.tl-motion:not(.tl-seen) .tl-ticket-stack .tl-ticket-swap .tl-icon { animation: tlSwapTurn 0.6s var(--tl-ease-out) 1.25s both; }
.tl-motion:not(.tl-seen) .tl-ticket-stack .tl-ticket-status { animation: tlFadeIn 0.5s ease 0.6s both; }
.tl-ticket-swap .tl-icon { transition: transform 0.5s var(--tl-ease-out); }
@media (hover: hover) and (pointer: fine) {
  .tl-motion .tl-ticket-stack:hover .tl-ticket-swap .tl-icon { animation: none; transform: rotate(360deg); }
}

/* Status line: "sent" resolves to "accepted" in the same grid cell (no layout shift).
 * The markup is static in index.html; the hand-off is timed in CSS to land as the swap
 * icon finishes its turn (1.25s + 0.6s), so no script swaps text after first paint.
 * Default (no motion / reduced motion / return visit): only the final text shows. */
.tl-ticket-status .tl-status-text { display: grid; }
.tl-ticket-status .tl-status-text > span { grid-area: 1 / 1; }
.tl-status-pending { opacity: 0; color: #c3c6ce; }
@keyframes tlStatusOut { from { opacity: 1; } to { opacity: 0; } }
@keyframes tlStatusIn { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
@keyframes tlDotPending { from { background: var(--tl-champagne); box-shadow: 0 0 0 4px rgba(216,194,154,0.2); } }
.tl-motion:not(.tl-seen) .tl-ticket-status .tl-status-pending { animation: tlStatusOut 0.45s ease 1.85s both; }
.tl-motion:not(.tl-seen) .tl-ticket-status .tl-status-final { animation: tlStatusIn 0.45s var(--tl-ease-out) 1.85s both; }
.tl-motion:not(.tl-seen) .tl-ticket-status .dot { animation: tlDotPending 0.4s ease 1.85s backwards; }
.tl-ticket-status .dot { position: relative; }
.tl-ticket-status .dot::after { content: ''; position: absolute; inset: 0; border-radius: 50%; background: #6fcf97; opacity: 0; pointer-events: none; }
.tl-motion:not(.tl-seen) .tl-ticket-status .dot::after { animation: tlRing 0.9s ease-out 2.2s 2; }

/* Watch on the hero ticket keeps real time; the seconds hand sweeps.
 * The live hands fade in once script has set them, so the static 10:10 hands never
 * visibly jump to the real time. */
.tl-hands line, .tl-hands .tl-sec { transform-box: view-box; transform-origin: 50px 50px; }
@keyframes tlSweep { to { transform: rotate(360deg); } }
.tl-motion .tl-hero .tl-hands { opacity: 0; }
.tl-motion .tl-hero .tl-hands.is-live { opacity: 1; animation: tlFadeIn 0.35s ease both; }
.tl-motion .tl-hands .tl-sec-wrap { transform-box: view-box; transform-origin: 50px 50px; animation: tlSweep 60s linear infinite; animation-delay: var(--sec-delay, 0s); }
.tl-hands.is-paused .tl-sec-wrap { animation-play-state: paused; }

/* ---------- Brass sheen (one pass on primary CTAs) ---------- */
.tl-sheen { position: relative; overflow: hidden; isolation: isolate; }
.tl-sheen::after {
  content: ''; position: absolute; top: -10%; bottom: -10%; left: 0; width: 45%; pointer-events: none; z-index: 1;
  background: linear-gradient(100deg, transparent 0%, rgba(255, 244, 222, 0.5) 50%, transparent 100%);
  transform: translateX(-160%) skewX(-18deg); opacity: 0;
}
@keyframes tlSheen { 0% { transform: translateX(-160%) skewX(-18deg); opacity: 1; } 100% { transform: translateX(330%) skewX(-18deg); opacity: 1; } }
.tl-motion .tl-sheen.tl-sheen-go::after { animation: tlSheen 1.1s var(--tl-ease-out) 1; }
.tl-motion:not(.tl-seen) .tl-hero .tl-btn-primary.tl-sheen::after { animation: tlSheen 1.1s var(--tl-ease-out) 2.1s 1; }
@media (hover: hover) and (pointer: fine) {
  .tl-motion .tl-sheen:hover::after { animation: tlSheen 0.9s var(--tl-ease-out) 1; }
}

/* ---------- Logo: the two arrows trade places on hover ---------- */
.tl-logo-mark path { transform-box: fill-box; transition: transform 0.45s var(--tl-ease-out); }
@media (hover: hover) and (pointer: fine) {
  .tl-motion .tl-logo:hover .tl-logo-mark path:nth-of-type(2) { transform: translateX(-2.5px); }
  .tl-motion .tl-logo:hover .tl-logo-mark path:nth-of-type(3) { transform: translateX(2.5px); }
}

/* ---------- Header gains depth once the page scrolls ---------- */
.tl-header::after {
  content: ''; position: absolute; left: 0; right: 0; bottom: -18px; height: 18px; pointer-events: none;
  background: linear-gradient(180deg, rgba(10, 11, 14, 0.28), transparent); opacity: 0; transition: opacity 0.35s ease;
}
.tl-header.is-scrolled::after { opacity: 1; }

/* ---------- Scroll reveal (editorial stagger) ---------- */
.tl-motion .tl-reveal { opacity: 0; transform: translateY(22px); transition: opacity 0.75s var(--tl-ease-out), transform 0.85s var(--tl-ease-out); transition-delay: calc(var(--i, 0) * 75ms); }
.tl-motion .tl-reveal.is-in { opacity: 1; transform: none; }
/* Once revealed, hand transforms back to the component's own hover rules */
.tl-motion .tl-reveal.is-done { transition: transform var(--transition-base), box-shadow var(--transition-base), border-color var(--transition-base), opacity 0s; transition-delay: 0s; }

/* ---------- Listing cards: pointer tilt, art parallax, soft glare ---------- */
.tl-listing .tl-art svg:not(.tl-icon) { transition: transform 0.6s var(--tl-ease-out); }
.tl-listing .tl-art::after, .tl-cat-tile .tl-art::after {
  content: ''; position: absolute; width: 140%; aspect-ratio: 1; left: -20%; top: -20%; pointer-events: none; z-index: 0;
  background: radial-gradient(closest-side, rgba(255, 255, 255, 0.55), transparent 70%);
  opacity: 0; transform: translate(var(--gx, 0px), var(--gy, 0px)); transition: opacity 0.35s ease;
}
.tl-listing .tl-badges { z-index: 2; }
@media (hover: hover) and (pointer: fine) {
  .tl-motion .tl-listing:hover, .tl-motion .tl-cat-tile:hover {
    transform: perspective(900px) rotateX(var(--rx, 0deg)) rotateY(var(--ry, 0deg)) translateY(-4px);
  }
  .tl-motion .tl-listing.is-tilting, .tl-motion .tl-cat-tile.is-tilting { transition: transform 0.12s linear, box-shadow var(--transition-base), border-color var(--transition-base); }
  .tl-motion .tl-listing:hover .tl-art svg:not(.tl-icon) { transform: translate(var(--px, 0px), var(--py, 0px)) scale(1.05); }
  .tl-motion .tl-listing:hover .tl-art::after, .tl-motion .tl-cat-tile:hover .tl-art::after { opacity: 0.55; }
}

/* ---------- Category tiles: art lifts, brass rule draws under the label ---------- */
.tl-cat-tile .tl-art svg:not(.tl-icon) { transition: transform 0.6s var(--tl-ease-out); }
.tl-cat-tile-body strong { position: relative; display: inline-block; }
.tl-cat-tile-body strong::after {
  content: ''; position: absolute; left: 0; right: 0; bottom: -3px; height: 2px; background: var(--tl-brass);
  transform: scaleX(0); transform-origin: left; transition: transform 0.45s var(--tl-ease-out);
}
.tl-cat-tile-body span { display: block; }
@media (hover: hover) and (pointer: fine) {
  .tl-motion .tl-cat-tile:hover .tl-art svg:not(.tl-icon) { transform: translateY(-4px) rotate(-4deg) scale(1.07); }
  .tl-motion .tl-cat-tile:hover .tl-cat-tile-body strong::after, .tl-motion .tl-cat-tile:focus-visible .tl-cat-tile-body strong::after { transform: scaleX(1); }
}

/* ---------- Listing modal: sheet rises on mobile, scale-fades on desktop ---------- */
/* Only the scrim fades; the sheet itself stays opaque while it rises */
.tl-motion .tl-modal-backdrop { opacity: 1; background: transparent; transition: visibility 0.3s ease; }
.tl-motion .tl-modal-backdrop::before { content: ''; position: fixed; inset: 0; background: var(--bg-overlay); opacity: 0; transition: opacity 0.3s ease; pointer-events: none; }
.tl-motion .tl-modal-backdrop.open::before { opacity: 1; }
.tl-motion .tl-modal { position: relative; z-index: 1; transform: translateY(100%); transition: transform 0.28s cubic-bezier(0.4, 0, 1, 1); }
.tl-motion .tl-modal-backdrop.open .tl-modal { transform: none; transition: transform 0.46s var(--tl-ease-out); }
@media (min-width: 640px) {
  .tl-motion .tl-modal { transform: translateY(12px) scale(0.965); opacity: 0; transition: transform 0.22s ease-in, opacity 0.22s ease-in; }
  .tl-motion .tl-modal-backdrop.open .tl-modal { transform: none; opacity: 1; transition: transform 0.42s var(--tl-ease-out), opacity 0.3s ease; }
}
@keyframes tlArtSettle { from { transform: scale(1.12); } to { transform: none; } }
.tl-motion .tl-modal-backdrop.open .tl-modal > #modal-content > .tl-art svg:not(.tl-icon) { animation: tlArtSettle 1s var(--tl-ease-out) both; }
.tl-motion .tl-modal-backdrop.open .tl-modal-body > * { animation: tlRise 0.55s var(--tl-ease-out) both; }
.tl-motion .tl-modal-backdrop.open .tl-modal-body > :nth-child(2) { animation-delay: 0.05s; }
.tl-motion .tl-modal-backdrop.open .tl-modal-body > :nth-child(3) { animation-delay: 0.1s; }
.tl-motion .tl-modal-backdrop.open .tl-modal-body > :nth-child(4) { animation-delay: 0.15s; }
.tl-motion .tl-modal-backdrop.open .tl-modal-body > :nth-child(n+5) { animation-delay: 0.2s; }

/* ---------- Sell flow: direction-aware steps, filling stepper, "ready" reveal ---------- */
@keyframes tlStepFwd { from { opacity: 0; transform: translateX(22px); } to { opacity: 1; transform: none; } }
@keyframes tlStepBack { from { opacity: 0; transform: translateX(-22px); } to { opacity: 1; transform: none; } }
.tl-motion #sell-form[data-dir="fwd"] .tl-sell-step.active { animation: tlStepFwd 0.42s var(--tl-ease-out) both; }
.tl-motion #sell-form[data-dir="back"] .tl-sell-step.active { animation: tlStepBack 0.42s var(--tl-ease-out) both; }
.tl-motion .tl-stepper span { position: relative; overflow: hidden; background: var(--border-color); }
.tl-motion .tl-stepper span::after { content: ''; position: absolute; inset: 0; background: var(--tl-brass); transform: scaleX(0); transform-origin: left; transition: transform 0.5s var(--tl-ease-out); }
.tl-motion .tl-stepper li.done span, .tl-motion .tl-stepper li.current span { background: var(--border-color); }
.tl-motion .tl-stepper li.done span::after, .tl-motion .tl-stepper li.current span::after { transform: none; }

.tl-ready-stamp {
  position: absolute; top: 10px; right: 10px; z-index: 2; padding: 5px 10px 4px; border-radius: 4px;
  border: 1.5px solid var(--tl-brass-dark); background: rgba(255, 252, 245, 0.94); color: var(--tl-brass-dark);
  font-size: 0.66rem; font-weight: 800; letter-spacing: 0.12em; text-transform: uppercase; transform: rotate(-6deg);
}
@keyframes tlCardUp { from { opacity: 0; transform: translateY(16px) scale(0.98); } to { opacity: 1; transform: none; } }
@keyframes tlPop { from { opacity: 0; transform: scale(0.86); } to { opacity: 1; transform: none; } }
@keyframes tlStamp { 0% { opacity: 0; transform: scale(1.9) rotate(-14deg); } 70% { opacity: 1; transform: scale(0.94) rotate(-5deg); } 100% { opacity: 1; transform: rotate(-6deg); } }
.tl-preview-card { position: relative; }
.tl-motion .tl-sell-step.active .tl-preview-card.is-ready { animation: tlCardUp 0.55s var(--tl-ease-out) both; }
.tl-motion .tl-preview-card.is-ready .tl-art svg:not(.tl-icon) { animation: tlPop 0.6s var(--tl-ease-spring) 0.15s both; }
.tl-motion .tl-preview-card.is-ready .tl-ready-stamp { animation: tlStamp 0.5s cubic-bezier(0.3, 0.6, 0.3, 1) 0.6s both; }

/* ---------- How it works: tab panels ease in ---------- */
.tl-motion .tl-tab-panel.active.is-entering { animation: tlRise 0.45s var(--tl-ease-out) both; }

/* Safety net: honour a reduced-motion change made after load */
@media (prefers-reduced-motion: reduce) {
  .tl-motion *, .tl-motion *::before, .tl-motion *::after { animation: none !important; transition: none !important; }
  .tl-motion .tl-reveal { opacity: 1 !important; transform: none !important; }
  .tl-motion .tl-modal { opacity: 1 !important; }
  .tl-motion .tl-hero .tl-hands { opacity: 1 !important; }
}
