> ## Documentation Index
> Fetch the complete documentation index at: https://hyperframes-fix-nested-composition-media-inpoint.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Beat Freeze Cut

> A beat-driven speed ramp, freeze-frame hit, and hard-cut sequence for music-led promos and montages.

export const InstallCommand = ({command, item}) => {
  const [copied, setCopied] = React.useState(false);
  const [tuned, setTuned] = React.useState("");
  React.useEffect(() => {
    if (!item) return;
    const read = () => {
      try {
        const raw = new URLSearchParams(window.location.search).get(`vars-${item}`);
        if (!raw) return setTuned("");
        const parsed = JSON.parse(raw);
        if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return setTuned("");
        if (Object.keys(parsed).length === 0) return setTuned("");
        setTuned(` --vars '${JSON.stringify(parsed)}'`);
      } catch {
        setTuned("");
      }
    };
    read();
    window.addEventListener("hf-vars-changed", read);
    window.addEventListener("popstate", read);
    return () => {
      window.removeEventListener("hf-vars-changed", read);
      window.removeEventListener("popstate", read);
    };
  }, [item]);
  const fullCommand = `${command}${tuned}`;
  const copy = async () => {
    try {
      if (navigator.clipboard && window.isSecureContext) {
        await navigator.clipboard.writeText(fullCommand);
      } else {
        const previous = document.activeElement;
        const scratch = document.createElement("textarea");
        scratch.value = fullCommand;
        scratch.setAttribute("readonly", "");
        scratch.style.position = "fixed";
        scratch.style.opacity = "0";
        document.body.appendChild(scratch);
        scratch.select();
        document.execCommand("copy");
        document.body.removeChild(scratch);
        previous?.focus?.();
      }
      setCopied(true);
      setTimeout(() => setCopied(false), 2000);
    } catch {}
  };
  return <div className="hf-install-command not-prose my-4 flex items-stretch overflow-hidden rounded-xl border border-zinc-200 bg-zinc-50 dark:border-zinc-800 dark:bg-zinc-900">
      <code className="flex-1 overflow-x-auto whitespace-nowrap border-r border-zinc-200 px-4 py-3 font-mono text-sm text-zinc-800 dark:border-zinc-800 dark:text-zinc-100">
        {fullCommand}
      </code>
      <button type="button" onClick={copy} data-copied={copied ? "true" : "false"} aria-label={`Copy ${command} to the clipboard`} className="hf-install-copy">
        <svg className="hf-install-copy-clipboard" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 18 18" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
          <path d="M14.25 5.25H7.25C6.14543 5.25 5.25 6.14543 5.25 7.25V14.25C5.25 15.3546 6.14543 16.25 7.25 16.25H14.25C15.3546 16.25 16.25 15.3546 16.25 14.25V7.25C16.25 6.14543 15.3546 5.25 14.25 5.25Z" />
          <path d="M2.80103 11.998L1.77203 5.07397C1.61003 3.98097 2.36403 2.96397 3.45603 2.80197L10.38 1.77297C11.313 1.63397 12.19 2.16297 12.528 3.00097" />
        </svg>
        <svg className="hf-install-copy-check" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 18 18" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
          <path d="M2.75 9.5L6.5 13.25L15.25 4.5" />
        </svg>
      </button>
      <span className="hf-install-copy-status" role="status" aria-live="polite">
        {copied ? "Copied" : ""}
      </span>
    </div>;
};

<iframe className="w-full aspect-video rounded-xl border-0 bg-zinc-100 dark:bg-zinc-800" title="beat-freeze-cut preview" loading="lazy" srcDoc={`<!doctype html><html><head><meta charset="utf-8"><style>html,body{margin:0;height:100%;overflow:hidden;background:transparent}hyperframes-player{display:block;width:100%;height:100%}</style><script src="https://cdn.jsdelivr.net/npm/@hyperframes/player@0.7/dist/hyperframes-player.global.js"><\/script></head><body><script>fetch("/public/catalog/blocks/beat-freeze-cut.json").then(function(r){return r.json()}).then(function(d){var p=document.createElement("hyperframes-player");p.setAttribute("srcdoc",d.html);p.setAttribute("controls","");p.setAttribute("autoplay","");p.setAttribute("loop","");p.setAttribute("muted","");p.setAttribute("poster","https://static.heygen.ai/hyperframes-oss/docs/images/catalog/blocks/beat-freeze-cut.png");document.body.appendChild(p)});<\/script></body></html>`} />

## Install

<InstallCommand command="npx hyperframes add beat-freeze-cut" item="beat-freeze-cut" />

That writes one file: `compositions/beat-freeze-cut.html`.

## Add it to your video

It runs for 6 seconds at 1920×1080. Paste this into your composition:

```html index.html theme={null}
<div
  data-composition-id="beat-freeze-cut"
  data-composition-src="compositions/beat-freeze-cut.html"
  data-start="0"
  data-duration="6"
  data-track-index="1"
  data-width="1920"
  data-height="1080"
></div>
```

Move it in time with `data-start`. Put it on a different timeline row with
`data-track-index`. See [data attributes](/concepts/data-attributes) for the rest.

## Change the colors

Set these CSS variables on the block:

* `--bg-color` — Background. Defaults to `#0B0D10`.
* `--accent-color` — Accent. Defaults to `#00E5C7`.

## Source

<Accordion title={`beat-freeze-cut.html`}>
  ```html theme={null}
  <!doctype html>
  <html lang="en">
    <head>
      <meta charset="UTF-8" />
      <meta name="viewport" content="width=1920, height=1080" />
      <title>Beat Freeze Cut</title>
      <link rel="preconnect" href="https://fonts.googleapis.com" />
      <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
      <link
        href="https://fonts.googleapis.com/css2?family=Inter:wght@500;600;700;800;900&display=block"
        rel="stylesheet"
      />
      <script src="https://cdn.jsdelivr.net/npm/gsap@3.14.2/dist/gsap.min.js"></script>
      <style>
        *,
        *::before,
        *::after {
          margin: 0;
          padding: 0;
          box-sizing: border-box;
        }

        html,
        body {
          width: 1920px;
          height: 1080px;
          margin: 0;
          overflow: hidden;
          background: #0b0d10;
        }

        /*
          EDIT / STUDIO PARAMS
          ────────────────────
          Studio color params (CSS custom properties on the root):
            --bg-color       default #0B0D10
            --accent-color   default #00E5C7

          Numeric / string params (beat times, labels, intensity) are NOT in the
          formal registry params schema today (only color keys are used by
          existing blocks). Edit the CONFIG object in the script below instead.
        */

        #bfc-root {
          position: relative;
          width: 1920px;
          height: 1080px;
          overflow: hidden;
          --bg-color: #0b0d10;
          --accent-color: #00e5c7;
          --bfc-ink: #f4f6f8;
          --bfc-muted: #a0a8b0;
          --bfc-panel: #14181f;
          --bfc-panel-2: #1a2029;
          --bfc-line: rgba(255, 255, 255, 0.08);
          font-family:
            "Inter",
            system-ui,
            -apple-system,
            sans-serif;
          color: var(--bfc-ink);
        }

        #bfc-bg {
          position: absolute;
          inset: 0;
          background:
            radial-gradient(ellipse 80% 60% at 50% 40%, rgba(0, 229, 199, 0.07) 0%, transparent 55%),
            radial-gradient(
              ellipse 50% 40% at 80% 80%,
              rgba(255, 255, 255, 0.03) 0%,
              transparent 50%
            ),
            var(--bg-color);
        }

        #bfc-grid {
          position: absolute;
          inset: 0;
          opacity: 0.22;
          background-image:
            linear-gradient(rgba(255, 255, 255, 0.04) 1px, transparent 1px),
            linear-gradient(90deg, rgba(255, 255, 255, 0.04) 1px, transparent 1px);
          background-size: 80px 80px;
          mask-image: radial-gradient(ellipse 70% 60% at 50% 45%, #000 20%, transparent 75%);
          pointer-events: none;
        }

        #bfc-stage {
          position: absolute;
          inset: 0;
          transform-origin: 50% 48%;
          will-change: transform, filter;
        }

        #bfc-shot-a,
        #bfc-shot-b {
          position: absolute;
          inset: 0;
          overflow: hidden;
        }

        #bfc-shot-b {
          visibility: hidden;
          opacity: 0;
        }

        /* ── Shot A: single product card hero ── */
        #bfc-a-crop {
          position: absolute;
          inset: 0;
          display: flex;
          align-items: center;
          justify-content: center;
          transform-origin: 50% 50%;
        }

        #bfc-a-card {
          position: relative;
          width: 680px;
          height: 720px;
          border-radius: 36px;
          background:
            linear-gradient(160deg, rgba(255, 255, 255, 0.06) 0%, transparent 40%),
            linear-gradient(180deg, var(--bfc-panel-2) 0%, var(--bfc-panel) 100%);
          border: 1px solid var(--bfc-line);
          box-shadow:
            0 40px 120px rgba(0, 0, 0, 0.55),
            0 0 0 1px rgba(0, 229, 199, 0.08),
            inset 0 1px 0 rgba(255, 255, 255, 0.06);
          overflow: hidden;
          transform-origin: 50% 50%;
        }

        #bfc-a-card-glow {
          position: absolute;
          left: 50%;
          top: 28%;
          width: 420px;
          height: 420px;
          margin-left: -210px;
          margin-top: -210px;
          border-radius: 50%;
          background: radial-gradient(circle, rgba(0, 229, 199, 0.28) 0%, transparent 68%);
          opacity: 0.85;
          pointer-events: none;
        }

        #bfc-a-wave {
          position: absolute;
          left: 64px;
          right: 64px;
          top: 120px;
          height: 220px;
        }

        #bfc-a-wave svg {
          width: 100%;
          height: 100%;
          display: block;
        }

        #bfc-a-wave-path {
          fill: none;
          stroke: var(--accent-color);
          stroke-width: 4;
          stroke-linecap: round;
          stroke-linejoin: round;
          opacity: 0.95;
        }

        #bfc-a-wave-fill {
          fill: var(--accent-color);
          opacity: 0.12;
        }

        #bfc-a-bars {
          position: absolute;
          left: 80px;
          right: 80px;
          bottom: 160px;
          height: 96px;
          display: flex;
          align-items: flex-end;
          gap: 10px;
        }

        .bfc-bar {
          flex: 1;
          border-radius: 6px 6px 2px 2px;
          background: linear-gradient(180deg, var(--accent-color) 0%, rgba(0, 229, 199, 0.25) 100%);
          transform-origin: 50% 100%;
          height: 40%;
        }

        #bfc-a-meta {
          position: absolute;
          left: 64px;
          right: 64px;
          bottom: 56px;
          display: flex;
          align-items: center;
          justify-content: space-between;
        }

        #bfc-a-kicker {
          font-size: 18px;
          font-weight: 600;
          letter-spacing: 0.18em;
          text-transform: uppercase;
          color: var(--bfc-muted);
        }

        #bfc-a-pill {
          font-size: 15px;
          font-weight: 700;
          letter-spacing: 0.08em;
          text-transform: uppercase;
          color: #04120f;
          background: var(--accent-color);
          padding: 8px 16px;
          border-radius: 999px;
        }

        /* ── Shot B: split layout, higher info density ── */
        #bfc-b-layout {
          position: absolute;
          inset: 0;
          display: grid;
          grid-template-columns: 1.05fr 0.95fr;
          gap: 48px;
          padding: 100px 110px;
          align-items: center;
        }

        #bfc-b-left {
          display: flex;
          flex-direction: column;
          gap: 28px;
          transform-origin: 0% 50%;
        }

        #bfc-b-eyebrow {
          font-size: 20px;
          font-weight: 700;
          letter-spacing: 0.22em;
          text-transform: uppercase;
          color: var(--accent-color);
        }

        #bfc-b-title {
          font-size: 128px;
          font-weight: 900;
          line-height: 0.92;
          letter-spacing: -0.04em;
          text-transform: uppercase;
          color: var(--bfc-ink);
        }

        #bfc-b-sub {
          font-size: 28px;
          font-weight: 500;
          color: var(--bfc-muted);
          max-width: 520px;
          line-height: 1.35;
        }

        #bfc-b-right {
          display: flex;
          flex-direction: column;
          gap: 18px;
        }

        .bfc-b-card {
          display: flex;
          align-items: center;
          justify-content: space-between;
          gap: 24px;
          padding: 28px 32px;
          border-radius: 20px;
          background: linear-gradient(135deg, var(--bfc-panel-2), var(--bfc-panel));
          border: 1px solid var(--bfc-line);
          box-shadow: 0 18px 48px rgba(0, 0, 0, 0.35);
        }

        .bfc-b-card-label {
          font-size: 18px;
          font-weight: 600;
          letter-spacing: 0.12em;
          text-transform: uppercase;
          color: var(--bfc-muted);
        }

        .bfc-b-card-value {
          font-size: 42px;
          font-weight: 800;
          letter-spacing: -0.03em;
          color: var(--bfc-ink);
        }

        .bfc-b-card-value.accent {
          color: var(--accent-color);
        }

        #bfc-b-accent-bar {
          width: 120px;
          height: 6px;
          border-radius: 999px;
          background: var(--accent-color);
          opacity: 0.9;
        }

        /* ── Intro / transient typography ── */
        #bfc-intro {
          position: absolute;
          left: 0;
          right: 0;
          top: 72px;
          display: flex;
          justify-content: center;
          pointer-events: none;
          z-index: 20;
          opacity: 0;
          visibility: hidden;
        }

        #bfc-intro-label {
          font-size: 18px;
          font-weight: 700;
          letter-spacing: 0.28em;
          text-transform: uppercase;
          color: var(--bfc-muted);
          padding: 10px 18px;
          border: 1px solid var(--bfc-line);
          border-radius: 999px;
          background: rgba(11, 13, 16, 0.55);
          backdrop-filter: blur(8px);
        }

        #bfc-hit-type {
          position: absolute;
          inset: 0;
          display: flex;
          align-items: center;
          justify-content: center;
          pointer-events: none;
          z-index: 30;
          opacity: 0;
          visibility: hidden;
        }

        #bfc-hit-type-text {
          font-size: 160px;
          font-weight: 900;
          letter-spacing: -0.04em;
          text-transform: uppercase;
          color: var(--bfc-ink);
          text-shadow:
            0 0 40px rgba(0, 229, 199, 0.35),
            0 8px 40px rgba(0, 0, 0, 0.55);
          -webkit-text-stroke: 2px rgba(0, 0, 0, 0.35);
          paint-order: stroke fill;
        }

        /* ── Freeze frame treatment ── */
        #bfc-freeze {
          position: absolute;
          inset: 0;
          pointer-events: none;
          z-index: 25;
          opacity: 0;
          visibility: hidden;
        }

        #bfc-freeze-outline {
          position: absolute;
          inset: 48px;
          border: 3px solid var(--accent-color);
          border-radius: 8px;
          box-shadow:
            0 0 0 1px rgba(0, 229, 199, 0.25),
            inset 0 0 0 1px rgba(0, 229, 199, 0.15),
            0 0 48px rgba(0, 229, 199, 0.2);
          opacity: 0;
        }

        #bfc-freeze-flash {
          position: absolute;
          inset: 0;
          background: #ffffff;
          opacity: 0;
          mix-blend-mode: screen;
        }

        #bfc-freeze-contour {
          position: absolute;
          inset: 0;
          background:
            linear-gradient(90deg, transparent 0%, rgba(0, 229, 199, 0.08) 48%, transparent 52%),
            radial-gradient(ellipse 40% 55% at 50% 48%, transparent 40%, rgba(0, 229, 199, 0.18) 100%);
          opacity: 0;
          mix-blend-mode: screen;
        }

        #bfc-freeze-badge {
          position: absolute;
          top: 80px;
          right: 96px;
          font-size: 16px;
          font-weight: 800;
          letter-spacing: 0.2em;
          text-transform: uppercase;
          color: #04120f;
          background: var(--accent-color);
          padding: 10px 18px;
          border-radius: 6px;
          opacity: 0;
        }

        /* ── Hard-cut connector (directional stretch / blur) ── */
        #bfc-cut {
          position: absolute;
          inset: -8% -20%;
          pointer-events: none;
          z-index: 40;
          opacity: 0;
          visibility: hidden;
          background: linear-gradient(
            90deg,
            transparent 0%,
            rgba(0, 229, 199, 0.12) 35%,
            rgba(255, 255, 255, 0.55) 50%,
            rgba(0, 229, 199, 0.12) 65%,
            transparent 100%
          );
          filter: blur(18px);
          transform-origin: 50% 50%;
        }

        #bfc-vignette {
          position: absolute;
          inset: 0;
          pointer-events: none;
          z-index: 15;
          background: radial-gradient(
            ellipse 75% 70% at 50% 50%,
            transparent 45%,
            rgba(0, 0, 0, 0.55) 100%
          );
          opacity: 0.85;
        }

        #bfc-driver {
          position: absolute;
          width: 1px;
          height: 1px;
          opacity: 0;
          pointer-events: none;
        }
      </style>
    </head>
    <body>
      <div
        id="bfc-root"
        data-composition-id="beat-freeze-cut"
        data-start="0"
        data-duration="6"
        data-width="1920"
        data-height="1080"
      >
        <div id="bfc-bg" aria-hidden="true"></div>
        <div id="bfc-grid" aria-hidden="true"></div>

        <div id="bfc-stage">
          <!-- Shot A -->
          <div id="bfc-shot-a">
            <div id="bfc-a-crop" data-layout-allow-overflow>
              <div id="bfc-a-card" data-layout-allow-overflow>
                <div id="bfc-a-card-glow" aria-hidden="true"></div>
                <div id="bfc-a-wave" aria-hidden="true">
                  <svg viewBox="0 0 592 220" preserveAspectRatio="none">
                    <path
                      id="bfc-a-wave-fill"
                      d="M0,160 C40,150 60,90 100,100 C140,110 160,40 200,55 C240,70 260,150 300,140 C340,130 360,30 400,45 C440,60 460,130 500,120 C540,110 560,70 592,80 L592,220 L0,220 Z"
                    />
                    <path
                      id="bfc-a-wave-path"
                      d="M0,160 C40,150 60,90 100,100 C140,110 160,40 200,55 C240,70 260,150 300,140 C340,130 360,30 400,45 C440,60 460,130 500,120 C540,110 560,70 592,80"
                    />
                  </svg>
                </div>
                <div id="bfc-a-bars" aria-hidden="true">
                  <div class="bfc-bar" id="bfc-bar-0" style="height: 34%"></div>
                  <div class="bfc-bar" id="bfc-bar-1" style="height: 58%"></div>
                  <div class="bfc-bar" id="bfc-bar-2" style="height: 42%"></div>
                  <div class="bfc-bar" id="bfc-bar-3" style="height: 78%"></div>
                  <div class="bfc-bar" id="bfc-bar-4" style="height: 52%"></div>
                  <div class="bfc-bar" id="bfc-bar-5" style="height: 88%"></div>
                  <div class="bfc-bar" id="bfc-bar-6" style="height: 46%"></div>
                  <div class="bfc-bar" id="bfc-bar-7" style="height: 64%"></div>
                  <div class="bfc-bar" id="bfc-bar-8" style="height: 36%"></div>
                  <div class="bfc-bar" id="bfc-bar-9" style="height: 72%"></div>
                  <div class="bfc-bar" id="bfc-bar-10" style="height: 48%"></div>
                  <div class="bfc-bar" id="bfc-bar-11" style="height: 92%"></div>
                </div>
                <div id="bfc-a-meta">
                  <span id="bfc-a-kicker">MUSIC PROMO</span>
                  <span id="bfc-a-pill">LIVE</span>
                </div>
              </div>
            </div>
          </div>

          <!-- Shot B -->
          <div id="bfc-shot-b">
            <div id="bfc-b-layout">
              <div id="bfc-b-left">
                <div id="bfc-b-eyebrow">Next shot</div>
                <div id="bfc-b-title">HARD<br />CUT</div>
                <div id="bfc-b-accent-bar" aria-hidden="true"></div>
                <div id="bfc-b-sub">
                  Beat-locked freeze, then cut. Built for music-led promos and montages.
                </div>
              </div>
              <div id="bfc-b-right">
                <div class="bfc-b-card" id="bfc-b-card-0">
                  <span class="bfc-b-card-label">Ramp</span>
                  <span class="bfc-b-card-value accent">1.35→2.2</span>
                </div>
                <div class="bfc-b-card" id="bfc-b-card-1">
                  <span class="bfc-b-card-label">Freeze</span>
                  <span class="bfc-b-card-value">0.8s</span>
                </div>
                <div class="bfc-b-card" id="bfc-b-card-2">
                  <span class="bfc-b-card-label">Cut</span>
                  <span class="bfc-b-card-value accent">3.00</span>
                </div>
              </div>
            </div>
          </div>
        </div>

        <div id="bfc-vignette" aria-hidden="true"></div>

        <div id="bfc-intro" aria-hidden="true">
          <span id="bfc-intro-label">ON THE BEAT</span>
        </div>

        <div id="bfc-hit-type" aria-hidden="true">
          <span id="bfc-hit-type-text">DROP</span>
        </div>

        <div id="bfc-freeze" aria-hidden="true">
          <div id="bfc-freeze-flash"></div>
          <div id="bfc-freeze-contour"></div>
          <div id="bfc-freeze-outline"></div>
          <div id="bfc-freeze-badge">FREEZE</div>
        </div>

        <div id="bfc-cut" aria-hidden="true"></div>

        <div id="bfc-driver" class="clip" data-start="0" data-duration="6" data-track-index="0"></div>
      </div>

      <script>
        (function () {
          window.__timelines = window.__timelines || {};

          // ── EDIT ME (not Studio params — see HTML comment) ──────────────
          var CONFIG = {
            primaryLabel: "DROP",
            secondaryLabel: "ON THE BEAT",
            beat1: 0.7,
            beat2: 2.2,
            freezeTime: 2.2,
            intensity: 1.0,
          };
          // ────────────────────────────────────────────────────────────────

          var DURATION = 6;
          var intensity = Math.max(0.6, Math.min(1.4, Number(CONFIG.intensity) || 1));
          var beat1 = Number(CONFIG.beat1) || 0.7;
          var beat2 = Number(CONFIG.beat2) || 2.2;
          var freezeAt = Number(CONFIG.freezeTime) || beat2;
          var cutAt = 3.0;
          var beat3 = 4.7;
          var holdAt = 5.2;

          var root = document.getElementById("bfc-root");
          var stage = document.getElementById("bfc-stage");
          var shotA = document.getElementById("bfc-shot-a");
          var shotB = document.getElementById("bfc-shot-b");
          var aCrop = document.getElementById("bfc-a-crop");
          var aCard = document.getElementById("bfc-a-card");
          var intro = document.getElementById("bfc-intro");
          var introLabel = document.getElementById("bfc-intro-label");
          var hitType = document.getElementById("bfc-hit-type");
          var hitText = document.getElementById("bfc-hit-type-text");
          var freeze = document.getElementById("bfc-freeze");
          var freezeOutline = document.getElementById("bfc-freeze-outline");
          var freezeFlash = document.getElementById("bfc-freeze-flash");
          var freezeContour = document.getElementById("bfc-freeze-contour");
          var freezeBadge = document.getElementById("bfc-freeze-badge");
          var cutFx = document.getElementById("bfc-cut");
          var bLeft = document.getElementById("bfc-b-left");
          var bCards = [
            document.getElementById("bfc-b-card-0"),
            document.getElementById("bfc-b-card-1"),
            document.getElementById("bfc-b-card-2"),
          ];
          var bars = [];
          for (var bi = 0; bi < 12; bi++) {
            bars.push(document.getElementById("bfc-bar-" + bi));
          }

          // Apply editable labels
          if (hitText) hitText.textContent = CONFIG.primaryLabel || "DROP";
          if (introLabel) introLabel.textContent = CONFIG.secondaryLabel || "ON THE BEAT";

          // Accent color from CSS var → freeze/glow that use hardcoded rgba fallbacks
          // stay coherent because stroke/fill already use var(--accent-color).

          var tl = gsap.timeline({ paused: true });

          // Initial states (no CSS transform conflicts on animated props)
          gsap.set(stage, { scale: 1, x: 0, y: 0, filter: "blur(0px) brightness(1)" });
          gsap.set(aCrop, { scale: 1, x: 0, y: 0 });
          // Card visible at t=0 so catalog snapshots are never a black frame
          gsap.set(aCard, { scale: 0.9, y: 20, opacity: 1 });
          gsap.set(shotA, { opacity: 1, visibility: "visible" });
          gsap.set(shotB, { opacity: 0, visibility: "hidden" });
          gsap.set(intro, { opacity: 0, visibility: "hidden", y: -12 });
          gsap.set(hitType, { opacity: 0, visibility: "hidden", scale: 1.15 });
          gsap.set(freeze, { opacity: 0, visibility: "hidden" });
          gsap.set([freezeOutline, freezeFlash, freezeContour, freezeBadge], { opacity: 0 });
          gsap.set(cutFx, { opacity: 0, visibility: "hidden", scaleX: 0.4, x: -200 });
          gsap.set(bLeft, { opacity: 0, x: -48 });
          gsap.set(bCards, { opacity: 0, x: 40 });
          gsap.set(bars, { scaleY: 0.55 });

          // Full duration anchor (seek-safe length)
          tl.to({}, { duration: DURATION, ease: "none" }, 0);

          // ── 0.00–0.70: intro push-in + secondary type ──
          tl.to(aCard, { scale: 1, y: 0, duration: 0.55, ease: "power3.out" }, 0);
          tl.to(stage, { scale: 1 + 0.04 * intensity, duration: 0.7, ease: "power1.out" }, 0);
          tl.to(bars, { scaleY: 1, duration: 0.5, ease: "power2.out", stagger: 0.02 }, 0.12);
          tl.set(intro, { visibility: "visible" }, 0.12);
          tl.to(intro, { opacity: 1, y: 0, duration: 0.28, ease: "power2.out" }, 0.12);
          tl.to(intro, { opacity: 0, y: -8, duration: 0.18, ease: "power2.in" }, 0.52);
          tl.set(intro, { visibility: "hidden", opacity: 0 }, 0.7);

          // ── 0.70–1.35: beat 1 — hard reframe ──
          tl.to(
            aCrop,
            {
              scale: 1 + 0.18 * intensity,
              x: -80 * intensity,
              y: 24 * intensity,
              duration: 0.22,
              ease: "power4.out",
            },
            beat1,
          );
          tl.to(
            stage,
            {
              scale: 1.08 * intensity > 1.2 ? 1.2 : 1 + 0.08 * intensity,
              duration: 0.28,
              ease: "expo.out",
            },
            beat1,
          );
          tl.to(
            bars,
            {
              scaleY: function (i) {
                // Deterministic bar pattern (no Math.random)
                var pattern = [0.55, 1.15, 0.7, 1.35, 0.9, 1.4, 0.65, 1.1, 0.5, 1.25, 0.8, 1.45];
                return pattern[i % pattern.length];
              },
              duration: 0.18,
              ease: "power3.out",
              stagger: 0.01,
            },
            beat1,
          );

          // ── 1.35–2.20: speed ramp into freeze ──
          var rampStart = 1.35;
          var rampDur = Math.max(0.2, freezeAt - rampStart);
          tl.to(
            aCrop,
            {
              scale: 1.28 * (0.9 + 0.1 * intensity),
              x: 28 * intensity,
              y: -12 * intensity,
              duration: rampDur,
              ease: "power3.in",
            },
            rampStart,
          );
          tl.to(
            stage,
            {
              scale: 1.12,
              filter: "blur(0px) brightness(1.08)",
              duration: rampDur,
              ease: "power2.in",
            },
            rampStart,
          );
          tl.to(
            bars,
            {
              scaleY: 1.55,
              duration: rampDur * 0.85,
              ease: "power2.in",
              stagger: { each: 0.012, from: "center" },
            },
            rampStart,
          );

          // ── 2.20–3.00: freeze hit (snap-on for seek/snapshot stability) ──
          tl.set(freeze, { visibility: "visible", opacity: 1 }, freezeAt);
          tl.set(freezeOutline, { opacity: 1 }, freezeAt);
          tl.set(freezeContour, { opacity: 0.85 }, freezeAt);
          tl.set(freezeBadge, { opacity: 1 }, freezeAt);
          tl.set(hitType, { visibility: "visible", opacity: 1, scale: 1 }, freezeAt);
          // Hold crop/stage where ramp ended
          tl.to(aCrop, { duration: 0.01, ease: "none" }, freezeAt);
          tl.to(
            stage,
            {
              scale: 1.12,
              filter: "blur(0px) brightness(1.15)",
              duration: 0.05,
              ease: "power4.out",
            },
            freezeAt,
          );
          // Single exposure flash (not a strobe sequence)
          tl.fromTo(
            freezeFlash,
            { opacity: 0.55 * intensity },
            { opacity: 0, duration: 0.28, ease: "power2.out" },
            freezeAt,
          );
          tl.to(
            hitType,
            { opacity: 0, scale: 0.96, duration: 0.2, ease: "power2.in" },
            freezeAt + 0.55,
          );
          tl.set(hitType, { visibility: "hidden", opacity: 0 }, freezeAt + 0.78);
          // Soft settle of freeze dressing before cut
          tl.to(
            [freezeOutline, freezeContour, freezeBadge],
            { opacity: 0.75, duration: 0.35, ease: "sine.out" },
            freezeAt + 0.35,
          );

          // ── 3.00–3.35: hard cut connector ──
          tl.set(cutFx, { visibility: "visible" }, cutAt);
          tl.fromTo(
            cutFx,
            { opacity: 0, scaleX: 0.35, x: -280 },
            {
              opacity: 0.95,
              scaleX: 1.6,
              x: 120,
              duration: 0.12,
              ease: "power4.in",
            },
            cutAt,
          );
          tl.to(
            stage,
            {
              filter: "blur(14px) brightness(1.35)",
              scaleX: 1.35,
              scaleY: 0.92,
              duration: 0.12,
              ease: "power3.in",
            },
            cutAt,
          );
          // Switch shots mid-cut — shot B content lands immediately (no black gap)
          var switchAt = cutAt + 0.14;
          tl.set(shotA, { opacity: 0, visibility: "hidden" }, switchAt);
          tl.set(shotB, { opacity: 1, visibility: "visible" }, switchAt);
          tl.set(hitType, { opacity: 0, visibility: "hidden" }, switchAt);
          tl.set(
            [freeze, freezeOutline, freezeFlash, freezeContour, freezeBadge],
            { opacity: 0, visibility: "hidden" },
            switchAt,
          );
          tl.set(freeze, { visibility: "hidden" }, switchAt);
          // Shot B content visible on switch (offset settles after)
          tl.set(bLeft, { opacity: 1, x: -24 }, switchAt);
          tl.set(bCards, { opacity: 1, x: 24 }, switchAt);
          tl.to(
            stage,
            {
              filter: "blur(0px) brightness(1)",
              scale: 1,
              scaleX: 1,
              scaleY: 1,
              x: 0,
              y: 0,
              duration: 0.18,
              ease: "power3.out",
            },
            switchAt,
          );
          tl.to(cutFx, { opacity: 0, x: 360, duration: 0.16, ease: "power2.out" }, cutAt + 0.16);
          tl.set(cutFx, { visibility: "hidden", opacity: 0 }, cutAt + 0.34);

          // ── after switch: shot B settle (no scale overlap with recover) ──
          tl.to(bLeft, { x: 0, duration: 0.4, ease: "power3.out" }, switchAt);
          tl.to(
            bCards,
            {
              x: 0,
              duration: 0.38,
              ease: "power3.out",
              stagger: 0.06,
            },
            switchAt + 0.04,
          );
          tl.to(stage, { scale: 1.02, duration: 1.17, ease: "sine.out" }, switchAt + 0.18);

          // ── 4.70–5.20: final beat punch-in ──
          tl.to(
            stage,
            {
              scale: 1.08 * (0.9 + 0.1 * intensity),
              duration: 0.14,
              ease: "power4.out",
            },
            beat3,
          );
          tl.to(
            bCards[1],
            {
              scale: 1.04,
              duration: 0.12,
              ease: "power3.out",
            },
            beat3,
          );
          tl.to(
            bCards[1],
            {
              scale: 1,
              duration: 0.22,
              ease: "power2.out",
            },
            beat3 + 0.14,
          );
          // Micro freeze feel: brief hold of scale
          tl.to(
            stage,
            { scale: 1.08 * (0.9 + 0.1 * intensity), duration: 0.2, ease: "none" },
            beat3 + 0.14,
          );

          // ── 5.20–6.00: hold readable end card (≥0.8s) ──
          tl.to(stage, { scale: 1.03, duration: 0.35, ease: "power2.out" }, holdAt);
          // Ensure transient layers stay dead through end
          tl.set(intro, { opacity: 0, visibility: "hidden" }, holdAt);
          tl.set(hitType, { opacity: 0, visibility: "hidden" }, holdAt);
          tl.set(freeze, { opacity: 0, visibility: "hidden" }, holdAt);
          tl.set(cutFx, { opacity: 0, visibility: "hidden" }, holdAt);

          window.__timelines["beat-freeze-cut"] = tl;
        })();
      </script>
    </body>
  </html>
  ```
</Accordion>

Tagged `transition` `music` `beat-driven` `freeze-frame`.

## Related topics

* [Browse the complete Catalog](/catalog)
* [Add assets and Catalog items in Studio](/studio/assets-and-blocks)
* [Build a richer composition](/go-further)
