/*
  Live mocks of what each product actually hands back — the showcase (screen in a
  browser frame, camera in a bubble, graded background) and the explainer (script,
  voiceover, storyboard). Pure CSS/DOM: no video file, no JS, a couple of KB.

  THESE ARE SHARED BETWEEN THE LANDING PAGES AND THE APP, which is why every value
  below is declared locally on `.mock` instead of read from a token.

  Propshaft's `stylesheet_link_tag :app` globs every .css under app/assets, so the
  app layout gets application.css (which defines --brand-primary etc.) AND this
  file. The landing layout links only landing.css + this one, and landing.css
  scopes all its tokens under `body.landing`. So a component that reaches for
  --brand-primary renders correctly in the app and colourlessly on the landing
  page. Hence: self-contained.

  Two rules follow from that same glob, and both matter:
    1. Nothing here may be a global selector. No `body`, no `h1`, no reset — this
       file lands on every page in the app.
    2. Everything is prefixed `.mock`.

  Motion: transform and background-position only. These loop forever on a landing
  page, so nothing here may trigger layout or paint.
*/

.mock {
  --mock-navy: #1a2f60;
  --mock-blue: #286496;
  --mock-teal: #2db7cb;
  --mock-ink: #0d0d14;
  --mock-haze: rgba(255, 255, 255, 0.08);
  --mock-line: rgba(255, 255, 255, 0.14);

  position: relative;
  aspect-ratio: 16 / 10;
  border-radius: 14px;
  overflow: hidden;
  border: 1px solid var(--mock-line);
  background-color: var(--mock-ink);
}

/* The slot: when a real rendered MP4 exists, it drops in here instead. */
.mock--video {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* ---------------------------------------------------------------- showcase */

/*
  The drifting graded background. Two radial gradients on an oversized canvas,
  slid around by background-position — the compositor's job, not the layout's.
  This is the CSS reading of what DynamicBackground does in SaasShowcase.tsx.
*/
.mock--showcase {
  background-image:
    radial-gradient(60% 60% at 30% 25%, #3a3a63 0%, rgba(58, 58, 99, 0) 70%),
    radial-gradient(50% 50% at 75% 80%, var(--mock-blue) 0%, rgba(40, 100, 150, 0) 70%);
  background-size: 160% 160%, 150% 150%;
  background-position: 0% 0%, 100% 100%;
  animation: mock-drift 18s ease-in-out infinite alternate;
}

@keyframes mock-drift {
  to { background-position: 30% 25%, 65% 60%; }
}

/* The browser window. Floats on a slow sine, like the Remotion one. */
.mock-window {
  position: absolute;
  top: 13%;
  left: 8%;
  right: 8%;
  bottom: 17%;
  border-radius: 8px;
  overflow: hidden;
  border: 1px solid rgba(255, 255, 255, 0.22);
  background: rgba(255, 255, 255, 0.06);
  box-shadow: 0 24px 48px rgba(0, 0, 0, 0.45);
  animation: mock-float 6s ease-in-out infinite;
}

@keyframes mock-float {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-6px); }
}

.mock-chrome {
  height: 16%;
  min-height: 14px;
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 0 8px;
  background: var(--mock-haze);
  border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}

.mock-dot {
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.4);
  flex: none;
}

/* The address bar — the single detail that says "browser" fastest. */
.mock-omnibox {
  margin-left: 6px;
  height: 6px;
  flex: 1;
  max-width: 55%;
  border-radius: 3px;
  background: rgba(255, 255, 255, 0.14);
}

/* A skeleton of "some SaaS app": rail, rows, a little bar chart. */
.mock-app {
  position: absolute;
  inset: 16% 0 0 0;
  display: flex;
  gap: 5%;
  padding: 6%;
}

.mock-rail {
  width: 18%;
  display: flex;
  flex-direction: column;
  gap: 7px;
}

.mock-rail span {
  height: 5px;
  border-radius: 3px;
  background: rgba(255, 255, 255, 0.16);
}

.mock-rail span:first-child {
  background: var(--mock-teal);
  opacity: 0.75;
}

.mock-body {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.mock-row {
  height: 5px;
  border-radius: 3px;
  background: rgba(255, 255, 255, 0.13);
}

.mock-row:nth-child(2) { width: 70%; }
.mock-row:nth-child(3) { width: 45%; }

.mock-bars {
  margin-top: auto;
  display: flex;
  align-items: flex-end;
  gap: 6px;
  height: 45%;
}

.mock-bars i {
  flex: 1;
  /* Full height, then scaled down — `flex: 1` only grows the WIDTH, and with
     align-items: flex-end an <i> with no height collapses to nothing. */
  height: 100%;
  border-radius: 2px 2px 0 0;
  background: linear-gradient(180deg, var(--mock-teal), var(--mock-blue));
  transform-origin: bottom;
  transform: scaleY(var(--h, 0.5));
}

/*
  The facecam. Springs in with an overshoot, then settles into a float.
  cubic-bezier(0.34, 1.56, 0.64, 1) is the CSS reading of Remotion's spring() —
  the mock and the render should speak the same motion language.
*/
.mock-bubble {
  position: absolute;
  right: 6%;
  bottom: 8%;
  width: 21%;
  aspect-ratio: 1;
  border-radius: 50%;
  border: 3px solid rgba(255, 255, 255, 0.9);
  background: linear-gradient(135deg, var(--mock-teal), var(--mock-navy));
  box-shadow: 0 10px 24px rgba(0, 0, 0, 0.4);
  animation:
    mock-bubble-in 900ms cubic-bezier(0.34, 1.56, 0.64, 1) both,
    mock-bubble-float 5s ease-in-out 900ms infinite;
}

@keyframes mock-bubble-in {
  from { transform: scale(0); }
  to { transform: scale(1); }
}

@keyframes mock-bubble-float {
  0%, 100% { transform: translateY(0) scale(1); }
  50% { transform: translateY(-5px) scale(1); }
}

/* --------------------------------------------------------------- explainer */

/*
  Script → voice → picture, on one 9s loop. Three beats sharing one duration with
  different keyframe windows, so they stagger with no JS and never drift apart.
*/
.mock--explainer {
  background-image: radial-gradient(70% 70% at 50% 30%, #23304f 0%, var(--mock-ink) 75%);
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 7%;
  padding: 8%;
}

.mock-script {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.mock-script span {
  height: 6px;
  border-radius: 3px;
  background: rgba(255, 255, 255, 0.35);
  transform: scaleX(0);
  transform-origin: left;
  animation: mock-type 9s linear infinite;
}

.mock-script span:nth-child(1) { width: 90%; animation-delay: 0s; }
.mock-script span:nth-child(2) { width: 75%; animation-delay: 0.35s; }
.mock-script span:nth-child(3) { width: 55%; animation-delay: 0.7s; }

/* Type on, hold, then clear before the loop restarts. */
@keyframes mock-type {
  0% { transform: scaleX(0); }
  12% { transform: scaleX(1); }
  92% { transform: scaleX(1); }
  100% { transform: scaleX(0); }
}

.mock-wave {
  display: flex;
  align-items: center;
  gap: 3px;
  height: 18%;
}

.mock-wave i {
  flex: 1;
  height: 100%;
  border-radius: 2px;
  background: var(--mock-teal);
  opacity: 0.85;
  transform: scaleY(0.12);
  animation: mock-pulse 9s ease-in-out infinite;
  /* Set per-bar in the partial, so the wave travels rather than throbbing. */
  animation-delay: calc(var(--i) * 40ms);
}

@keyframes mock-pulse {
  0%, 30% { transform: scaleY(0.12); }
  40% { transform: scaleY(0.9); }
  50% { transform: scaleY(0.35); }
  60% { transform: scaleY(0.75); }
  70%, 100% { transform: scaleY(0.12); }
}

.mock-frames {
  display: flex;
  gap: 6px;
  height: 30%;
}

.mock-frames span {
  flex: 1;
  border-radius: 5px;
  border: 1px solid var(--mock-line);
  background: linear-gradient(135deg, rgba(45, 183, 203, 0.3), rgba(26, 47, 96, 0.5));
  opacity: 0;
  transform: translateX(14px);
  animation: mock-slide 9s ease-out infinite;
}

/* Stagger ONLY. The lateness is in the keyframe window below (they stay hidden
   until 55% of the loop), so an additional multi-second delay would push them
   past the end of the cycle and they'd never be seen in phase with the script
   and the voiceover — which is the whole point of the sequence. */
.mock-frames span:nth-child(1) { animation-delay: 0s; }
.mock-frames span:nth-child(2) { animation-delay: 0.15s; }
.mock-frames span:nth-child(3) { animation-delay: 0.3s; }

@keyframes mock-slide {
  0%, 55% { opacity: 0; transform: translateX(14px); }
  62%, 96% { opacity: 1; transform: translateX(0); }
  100% { opacity: 0; transform: translateX(14px); }
}

/* ----------------------------------------------------------------- a11y */

/*
  Mandatory, not a nicety: these loop forever. With motion off the mock must still
  read as a finished still of the product — so everything lands in its END state
  rather than disappearing.
*/
@media (prefers-reduced-motion: reduce) {
  .mock,
  .mock * {
    animation: none !important;
  }

  .mock-script span { transform: scaleX(1); }
  .mock-wave i { transform: scaleY(0.55); }
  .mock-frames span { opacity: 1; transform: none; }
  .mock-bubble { transform: scale(1); }
}
