/* Framesite public-site motion system.
   Marketing pages use Jakub-led production polish with selective character;
   legal pages stay deliberately quiet. All motion is progressive enhancement. */
:root {
  --fs-motion-fast: 180ms;
  --fs-motion-medium: 420ms;
  --fs-motion-slow: 560ms;
  --fs-motion-enter: cubic-bezier(.16, 1, .3, 1);
  --fs-motion-state: cubic-bezier(.22, 1, .36, 1);
}

/* Nothing off screen should keep asking the browser—or the visitor—for attention. */
.fs-motion-v2 main > section:not([data-fs-visible]) *,
.fs-motion-v2 main > section:not([data-fs-visible]) *::before,
.fs-motion-v2 main > section:not([data-fs-visible]) *::after {
  animation-play-state: paused !important;
}

html.fs-motion-ready [data-fs-enter]:not(.is-entered) {
  opacity: 0;
  transform: translate3d(0, 10px, 0);
  filter: blur(3px);
}

html.fs-motion-ready [data-fs-enter].is-entered {
  opacity: 1;
  transform: translate3d(0, 0, 0);
  filter: blur(0);
  transition:
    opacity var(--fs-motion-medium) var(--fs-motion-enter) var(--fs-motion-delay, 0ms),
    transform var(--fs-motion-medium) var(--fs-motion-enter) var(--fs-motion-delay, 0ms),
    filter var(--fs-motion-medium) var(--fs-motion-enter) var(--fs-motion-delay, 0ms),
    clip-path var(--fs-motion-slow) var(--fs-motion-enter) var(--fs-motion-delay, 0ms);
}

/* Every public route gets a deliberate hierarchy pass. Copy arrives first;
   the visual follows from the same section instead of every block receiving
   the same generic fade. */
html.fs-motion-ready [data-fs-stage-visual]:not(.is-entered) {
  clip-path: inset(0 0 11% 0 round 14px);
  transform: translate3d(0, 16px, 0) scale(.988);
}

html.fs-motion-ready [data-fs-stage-visual].is-entered {
  clip-path: inset(0 0 0 0 round 0);
}

html.fs-motion-ready [data-fs-stage-head] {
  --fs-motion-delay: 0ms !important;
}

html.fs-motion-ready [data-fs-stage-visual] {
  --fs-motion-delay: 75ms !important;
}

/* Agency and studio stories read as a handoff: the explanatory surface enters
   a few pixels from the direction of the outcome, then settles. */
html.fs-motion-ready body[data-fs-route="agency"] main > section:nth-of-type(even) [data-fs-stage-visual]:not(.is-entered),
html.fs-motion-ready body[data-fs-route="studio"] main > section:nth-of-type(even) [data-fs-stage-visual]:not(.is-entered) {
  transform: translate3d(14px, 8px, 0) scale(.99);
}

html.fs-motion-ready body[data-fs-route="agency"] main > section:nth-of-type(odd) [data-fs-stage-visual]:not(.is-entered),
html.fs-motion-ready body[data-fs-route="studio"] main > section:nth-of-type(odd) [data-fs-stage-visual]:not(.is-entered) {
  transform: translate3d(-14px, 8px, 0) scale(.99);
}

/* Existing route reveals keep their content model, but use one calmer curve. */
.fs-motion-v2.motion-ready .reveal,
.fs-motion-v2.motion-ready .rx,
.fs-motion-v2 .reveal {
  transition-timing-function: var(--fs-motion-enter) !important;
}

/* Tactile feedback for occasional pointer interactions. Keyboard activation is instant. */
@media (hover: hover) and (pointer: fine) {
  .fs-motion-v2 a[class*="button"],
  .fs-motion-v2 a[class*="action"],
  .fs-motion-v2 button:not([role="tab"]),
  .fs-motion-v2 summary {
    transition-property: color, background-color, border-color, box-shadow, transform, opacity, filter;
    transition-duration: var(--fs-motion-fast);
    transition-timing-function: var(--fs-motion-state);
  }

  .fs-motion-v2 a[class*="button"]:active,
  .fs-motion-v2 a[class*="action"]:active,
  .fs-motion-v2 button:not([role="tab"]):active {
    transform: scale(.98);
  }

  .fs-motion-v2 :is(.aud-proof-card,.aud-path-card,.aud-step-card,.aud-route-card,.research-claim,.model-node,.strategy-row,.person-card,.quote-card,.product-bridge) {
    transition:
      transform var(--fs-motion-fast) var(--fs-motion-state),
      border-color var(--fs-motion-fast) var(--fs-motion-state),
      box-shadow var(--fs-motion-fast) var(--fs-motion-state),
      background-color var(--fs-motion-fast) var(--fs-motion-state);
  }

  .fs-motion-v2 :is(.aud-proof-card,.aud-path-card,.aud-step-card,.aud-route-card,.research-claim,.model-node,.strategy-row,.person-card,.quote-card,.product-bridge):hover {
    transform: translate3d(0, -2px, 0);
  }
}

/* Persistent CTA halos and play-button pulses compete with the page story.
   Keep the coral treatment; let focus and hover provide the feedback. */
.fs-motion-v2 :is(.fs-prompt,.fs-repeat-prompt,.fs-demo-confirm)::before,
.fs-motion-v2 :is(.fs-vf-play,.dpg-playmark),
.fs-motion-v2 .aud-pulse {
  animation: none !important;
}

/* Audience diagrams may demonstrate a process, but only while their section is visible. */
.fs-motion-v2 :is(.aud-after-flow,.aud-delivery-bridge,.aud-packet,.path-line,.document-model) {
  contain: paint;
}

/* Details are state changes, not spectacles. The content arrives quickly and from its trigger. */
.fs-motion-v2 details > :not(summary) {
  transform-origin: top center;
}

.fs-motion-v2 details[open] > :not(summary) {
  animation: fs-details-enter 240ms var(--fs-motion-enter) both;
}

@keyframes fs-details-enter {
  from { opacity: 0; transform: translate3d(0, -4px, 0); filter: blur(2px); }
  to { opacity: 1; transform: translate3d(0, 0, 0); filter: blur(0); }
}

/* Explanation graphics use finite, visibility-triggered sequences. The timing
   carries the eye from source to outcome, then stops and leaves the evidence readable. */
html.fs-motion-ready [data-fs-explain]:not([data-fs-explain-active]) [data-fs-explain-item] {
  opacity: 0;
  transform: translate3d(0, 9px, 0);
  filter: blur(3px);
}

html.fs-motion-ready [data-fs-explain-active] [data-fs-explain-item] {
  animation: fs-explain-arrive 520ms var(--fs-motion-enter) both;
  animation-delay: calc(var(--fs-explain-index, 0) * 90ms);
}

@keyframes fs-explain-arrive {
  from { opacity: 0; transform: translate3d(0, 9px, 0); filter: blur(3px); }
  to { opacity: 1; transform: translate3d(0, 0, 0); filter: blur(0); }
}

/* Frame speaks where the conversation lives. The caret is functional feedback,
   while the character's three-dot voice cue remains a secondary action. */
.fs-motion-v2 #frame :is(.fr2-dock-prompt,.fr2-bubble,.fr2-answer).is-typing::after {
  content: "";
  display: inline-block;
  width: 2px;
  height: 1em;
  margin-left: 3px;
  vertical-align: -.12em;
  background: #f4566b;
  animation: fs-type-caret 620ms steps(1,end) infinite;
}

@keyframes fs-type-caret {
  50% { opacity: 0; }
}

/* The homepage source story reveals the footage first, then its structured
   companion. This is the brand idea—not decorative camera/editing iconography. */
.fs-motion-v2 [data-fs-explain="source-step"] .hiw-visual {
  transform-origin: center bottom;
}

.fs-motion-v2 [data-fs-explain="source-step"][data-fs-explain-active] .hiw-visual {
  animation-duration: 620ms;
}

.fs-motion-v2 [data-fs-explain="enrich"][data-fs-explain-active] .fs-enrich-scene {
  animation-delay: 260ms;
}

/* Research motion behaves like evidence being assembled: measured values and
   document nodes resolve in sequence, never loop for attention. */
.fs-motion-v2[data-fs-route="research"] [data-fs-explain-item] {
  transform-origin: left center;
}

/* The research model behaves like a five-state document pipeline instead of
   an ambient marquee. It plays once as the explanation enters view. */
.fs-motion-v2 .model-travel,
.fs-motion-v2 .model-node::after {
  animation: none !important;
}

.fs-motion-v2 [data-fs-explain="document-model"][data-fs-explain-active] .model-travel {
  animation: fs-model-travel 2.8s cubic-bezier(.22, 1, .36, 1) 180ms both !important;
}

.fs-motion-v2 [data-fs-explain="document-model"][data-fs-explain-active] .model-node::after {
  animation: fs-model-node 420ms var(--fs-motion-state) both !important;
  animation-delay: calc(260ms + var(--fs-explain-index, 0) * 410ms) !important;
}

@keyframes fs-model-travel {
  from { transform: translate3d(-100%, 0, 0); opacity: 0; }
  12%, 82% { opacity: 1; }
  to { transform: translate3d(500%, 0, 0); opacity: 0; }
}

@keyframes fs-model-node {
  from { background: #534f4a; box-shadow: none; transform: scale(.82); }
  to { background: #f4566b; box-shadow: 0 0 0 5px rgba(244,86,107,.12); transform: scale(1); }
}

/* Numerical graphics reveal their actual measure from the label outward. */
.fs-motion-v2 [data-fs-explain="distribution"] .bar-track i {
  transform-origin: left center;
  transform: scaleX(0);
}

.fs-motion-v2 [data-fs-explain="distribution"][data-fs-explain-active] .bar-track i {
  animation: fs-measure-grow 620ms var(--fs-motion-enter) both;
  animation-delay: calc(180ms + var(--fs-explain-index, 0) * 95ms);
}

@keyframes fs-measure-grow {
  to { transform: scaleX(1); }
}

/* The studio delivery line resolves once: approved film plus readable source. */
.fs-motion-v2 .aud-delivery-bridge i::after {
  left: 0 !important;
  right: 0;
  width: auto;
  transform: scaleX(0);
  transform-origin: left center;
  animation: none !important;
}

.fs-motion-v2 [data-fs-explain="delivery-merge"][data-fs-explain-active] .aud-delivery-bridge i::after {
  animation: fs-delivery-line 760ms var(--fs-motion-enter) 540ms both !important;
}

@keyframes fs-delivery-line {
  to { transform: scaleX(1); }
}

/* Existing interactive workflow states remain interruptible; this adds a
   small continuity cue without changing their click or keyboard behavior. */
.fs-motion-v2 .aud-platform-flow-steps li > span {
  transition:
    transform var(--fs-motion-fast) var(--fs-motion-state),
    color var(--fs-motion-fast) var(--fs-motion-state),
    border-color var(--fs-motion-fast) var(--fs-motion-state),
    background-color var(--fs-motion-fast) var(--fs-motion-state);
}

.fs-motion-v2 .aud-platform-flow-steps li.is-active > span {
  transform: scale(1.08);
}

/* Keep the product demonstrations readable as demonstrations, not debug panels.
   Status and outcome copy stays; redundant eyebrow and telemetry labels go. */
.fs-motion-v2 #frame :is(
  .fr2-context,
  .fr2-chat-label,
  .fr2-queue-label,
  .fr2-cite,
  .fr2-tab small
),
.fs-motion-v2 .aud-delivery-merge .aud-delivery-head b,
.fs-motion-v2 .aud-delivery-merge .aud-delivery-foot span,
.fs-motion-v2 .aud-white-label-bar > span:not(.aud-faux-brand),
.fs-motion-v2 .aud-white-label-bar > b,
.fs-motion-v2 .aud-client-delivery-bar > span,
.fs-motion-v2 .aud-client-delivery-meta > span {
  display: none;
}

/* Legal and security routes: one quiet page arrival, then no scroll choreography. */
.fs-motion-v2[data-fs-route="legal"] [data-fs-enter].is-entered {
  transition-duration: 360ms;
}

.fs-motion-v2[data-fs-route="legal"] :is(h2,p,li,.note,footer) {
  animation: none !important;
  transition: none !important;
}

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

  html.fs-motion-ready [data-fs-enter],
  html.fs-motion-ready [data-fs-enter].is-entered {
    opacity: 1 !important;
    transform: none !important;
    filter: none !important;
    clip-path: none !important;
  }

  .fs-motion-v2 #frame :is(.fr2-dock-prompt,.fr2-bubble,.fr2-answer).is-typing::after {
    animation: none !important;
    opacity: 1;
  }

  html.fs-motion-ready [data-fs-explain] [data-fs-explain-item],
  .fs-motion-v2 [data-fs-explain] .model-travel,
  .fs-motion-v2 [data-fs-explain] .model-node::after,
  .fs-motion-v2 [data-fs-explain] .bar-track i,
  .fs-motion-v2 [data-fs-explain] .aud-delivery-bridge i::after {
    opacity: 1 !important;
    transform: none !important;
    filter: none !important;
    animation: none !important;
  }
}

@media (max-width: 720px) {
  .fs-motion-v2 .aud-delivery-bridge i::after {
    inset: 0 0 0 -1px !important;
    width: 3px;
    height: auto;
    transform: scaleY(0);
    transform-origin: center top;
  }

  .fs-motion-v2 [data-fs-explain="delivery-merge"][data-fs-explain-active] .aud-delivery-bridge i::after {
    animation-name: fs-delivery-line-vertical !important;
  }
}

@keyframes fs-delivery-line-vertical {
  to { transform: scaleY(1); }
}

@media (prefers-reduced-motion: reduce) {
  .fs-motion-v2 [data-fs-explain="delivery-merge"][data-fs-explain-active] .aud-delivery-bridge i::after {
    animation-name: none !important;
  }
}
