Files
roboco/motion/compositions/release-0.26.0/vertical.html
cd73ad6a74 [68e1e4db] Video: release 0.26.0 (#604)
* [68e1e4db] feat(video): author release-0.26.0 marketing clip in the panel-demo kit register

* [68e1e4db] fix(video): extend pk-frame clip window to full length to kill black-gap render bug

* [68e1e4db] docs(video): document release-0.26.0 composition structure in motion/README

Added a comprehensive "Release-specific example: release-0.26.0" section documenting the v0.26.0 marketing video composition: a 40-second panel-demo kit clip showcasing four key features (orchestrator security hardening, three-forge support, Telegram Mini App V4, active guard mode) with choreographed panel elements, stats overlay, and dual-format captions. Includes preview/test instructions, props.js shape, captions schema with verified character counts, and smoke-test invariants matching the pattern established by release-0.25.0.

---------

Co-authored-by: UX/UI Developer 1 <ux-dev-1@roboco.tech>
Co-authored-by: UX/UI Documenter <ux-doc@roboco.tech>
2026-07-20 11:00:27 +02:00

378 lines
15 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!doctype html>
<html lang="en" data-composition-id="release-0.26.0" data-composition-duration="40" data-fps="30">
<head>
<meta charset="utf-8" />
<title>RoboCo v0.26.0 Release - vertical (1080×1920)</title>
<link rel="stylesheet" href="../../kit/kit.css" />
<script src="props.js"></script>
<script src="../../kit/kit.js"></script>
<style>
/* v0.26.0 release clip - panel-demo register, same shape as
release-0.25.0: identity cold open, panel assembles, four feature
cards flip to completed one per scene, cursor click, receipt
stats, toast, lockup. Total 40s. */
/* ---- Identity cold open -------------------------------------------- */
.r26-hero {
position: absolute;
inset: 0;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 38px;
background: var(--pk-bg);
z-index: 30;
animation: r26-hero-out 0.6s var(--pk-ease) 2.6s forwards;
}
@keyframes r26-hero-out { to { opacity: 0; visibility: hidden; } }
.r26-hero__markwrap { position: relative; width: 520px; height: 520px; }
.r26-hero__mark {
width: 520px;
height: 520px;
transform: scale(0.82);
opacity: 0;
filter: drop-shadow(0 12px 60px rgba(255, 90, 31, 0.18));
animation: r26-mark-in 1s var(--pk-ease) 0.2s forwards;
}
@keyframes r26-mark-in { to { transform: scale(1); opacity: 1; } }
.r26-hero__ring {
position: absolute;
inset: 6px;
border-radius: 50%;
padding: 3px;
background: conic-gradient(from 0deg, transparent 0 78%, var(--pk-accent) 92%, transparent 100%);
-webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
-webkit-mask-composite: xor;
mask-composite: exclude;
opacity: 0;
animation: r26-ring-in 0.3s linear 0.9s forwards, r26-ring-spin 1.4s cubic-bezier(0.5, 0, 0.3, 1) 0.9s forwards;
}
@keyframes r26-ring-in { to { opacity: 1; } }
@keyframes r26-ring-spin { to { transform: rotate(360deg); opacity: 0; } }
.r26-hero__version {
font-family: var(--pk-font-display);
font-size: 120px;
color: var(--pk-text);
opacity: 0;
transform: translateY(18px);
animation: pk-enter-rise 0.7s var(--pk-ease) 1.2s forwards;
}
.r26-hero__tag {
font-size: 30px;
color: var(--pk-text-muted);
opacity: 0;
transform: translateY(14px);
animation: pk-enter-rise 0.7s var(--pk-ease) 1.5s forwards;
}
/* ---- Panel chrome --------------------------------------------------- */
.pk-frame { animation-delay: 2.6s; }
.pk-frame__sidebar {
width: 250px;
align-items: stretch;
gap: 6px;
padding: 28px 18px 0 18px;
transform: translateX(-40px);
opacity: 0;
animation: r26-side-in 0.7s var(--pk-ease) 2.8s forwards;
}
@keyframes r26-side-in { to { transform: translateX(0); opacity: 1; } }
.r26-side__logo {
width: 44px;
height: 44px;
border-radius: 12px;
background: #f4f6f8;
display: flex;
align-items: center;
justify-content: center;
margin: 0 0 22px 4px;
}
.r26-side__logo img { width: 34px; height: 34px; }
.r26-nav {
display: flex;
align-items: center;
height: 52px;
padding: 0 16px;
border-radius: 10px;
font-size: 21px;
color: var(--pk-text-muted);
}
.r26-nav--active { background: var(--pk-active-bg); color: var(--pk-active-fg); font-weight: 600; }
.pk-frame__topbar { left: 250px; }
.pk-frame__content { left: 250px; }
.r26-user {
display: flex;
align-items: center;
gap: 12px;
color: var(--pk-text-muted);
font-size: 20px;
}
.r26-user__chip {
background: var(--pk-surface-raised);
border: 1px solid var(--pk-border);
border-radius: 999px;
padding: 8px 18px;
color: var(--pk-text);
}
/* ---- Content placement --------------------------------------------- */
.pk-intake { --pk-intake-top: 32px; }
.pk-column { --pk-column-top: 220px; width: 720px; }
.pk-column .pk-card {
position: static;
margin-bottom: 20px;
/* Springy entrance with a hint of overshoot; a flat fade on every
card is the metronome that makes the cut feel like a slideshow. */
animation-duration: 0.55s;
animation-timing-function: cubic-bezier(0.34, 1.4, 0.64, 1);
}
.r26-sub {
margin-top: 10px;
font-size: 22px;
line-height: 1.35;
color: var(--pk-text-muted);
}
/* Receipt stats overlay. */
.r26-stats {
position: absolute;
right: 64px;
bottom: 320px;
text-align: right;
font-family: var(--pk-font-display);
}
.r26-stats__line {
font-size: 64px;
line-height: 1.22;
color: var(--pk-text);
opacity: 0;
transform: translateY(24px) scale(0.96);
animation: pk-enter-rise-scale 0.55s var(--pk-ease) forwards;
}
.r26-stats__line--accent { color: var(--pk-accent); }
.r26-stats { animation: r26-stats-out 0.5s var(--pk-ease) 32.0s forwards; }
@keyframes r26-stats-out { to { opacity: 0; } }
.pk-toast { --pk-toast-bottom: 140px; }
/* Closing lockup. */
.pk-outro {
--pk-outro-bottom: 56px;
display: flex;
align-items: center;
gap: 20px;
}
.r26-outro__logo {
width: 52px;
height: 52px;
border-radius: 14px;
background: #f4f6f8;
display: flex;
align-items: center;
justify-content: center;
}
.r26-outro__logo img { width: 40px; height: 40px; }
#typeIntro { display: inline-block; overflow: hidden; white-space: pre; vertical-align: bottom; width: 0; }
@keyframes type-reveal { to { width: var(--type-ch, 20ch); } }
</style>
</head>
<body>
<div id="stage" data-composition-id="release-0.26.0" data-width="1080" data-height="1920" data-start="0" data-duration="40" data-fps="30">
<!-- Beat 1: identity cold open. -->
<div class="r26-hero clip" data-start="0" data-duration="3.2" data-track-index="16">
<div class="r26-hero__markwrap">
<img class="r26-hero__mark" src="../../public/roboco-logo-darkmode.png" alt="RoboCo" />
<div class="r26-hero__ring"></div>
</div>
<div class="r26-hero__version">v0.26.0</div>
<div class="r26-hero__tag">the control plane gets a lock</div>
</div>
<!-- Beat 2: the panel assembles, and the camera lives on it: start a
touch tight, push toward each card as it completes, pull wide for
the receipt, ease onto the toast, settle for the lockup. -->
<div class="pk-camera"
data-shots="2.6 0 14 1.025; 4.8 0 8 1.03;
6.4 34 96 1.055; 9.2 30 88 1.05;
10.4 30 30 1.06; 13.6 26 24 1.055;
15.4 32 -52 1.065; 18.6 28 -58 1.06;
20.4 30 -150 1.065; 22.6 26 -156 1.06;
25.0 0 0 1.0; 29.2 0 0 1.0;
30.8 -26 -120 1.035; 33.4 -22 -116 1.03;
37.0 0 0 1.0; 39.6 0 6 1.005">
<div class="pk-frame clip" data-start="0" data-duration="40" data-track-index="1">
<aside class="pk-frame__sidebar">
<div class="r26-side__logo"><img src="../../public/roboco-logo.png" alt="" /></div>
<div class="r26-nav">Overview</div>
<div class="r26-nav">Business</div>
<div class="r26-nav">Social</div>
<div class="r26-nav r26-nav--active">Tasks</div>
<div class="r26-nav">Kanban</div>
<div class="r26-nav">Git</div>
<div class="r26-nav">Agents</div>
<div class="r26-nav">Metrics</div>
</aside>
<header class="pk-frame__topbar">
<div class="pk-frame__search">Search tasks, agents...</div>
<div class="r26-user">
<div class="pk-frame__status clip" data-start="0" data-duration="40" data-track-index="0">
<span class="pk-frame__statusdot"></span>
<span>Live</span>
</div>
<span class="r26-user__chip">CEO · Renzo</span>
</div>
</header>
<div class="pk-frame__content">
<!-- Beat 3: the hook types into intake. -->
<div class="pk-intake" style="animation-delay: 3.6s;">
<div class="pk-intake__label">New task</div>
<div class="pk-intake__field"><span id="typeIntro">The control plane gets a lock</span><span class="pk-caret"></span></div>
</div>
<!-- Beat 4: four feature cards, one per ~5s scene, each fully visible before the next enters. -->
<div class="pk-column">
<div class="pk-column__header">Shipped in v0.26.0</div>
<div class="pk-card" style="animation-delay: 5.0s;">
<div class="pk-card__title">Off the public net</div>
<div class="r26-sub">127.0.0.1 only, nginx does the rest.</div>
<div class="pk-card__meta">
<span class="pk-chip pk-chip--gray">orchestrator :8000</span>
</div>
<div class="pk-card__status">
<span class="pk-pill pk-pill--progress pk-pill--swap-out" style="--pk-pill-enter-delay: 5.0s; --pk-pill-exit-delay: 6.4s;">in progress</span>
<span class="pk-pill pk-pill--completed pk-pill--swap-in" style="--pk-pill-enter-delay: 6.6s;">completed</span>
</div>
</div>
<div class="pk-card" style="animation-delay: 10.0s;">
<div class="pk-card__title">3 forges, 1 API</div>
<div class="r26-sub">GitHub, Gitea, GitLab. Pick your forge.</div>
<div class="pk-card__meta">
<span class="pk-chip pk-chip--gray">git settings</span>
</div>
<div class="pk-card__status">
<span class="pk-pill pk-pill--progress pk-pill--swap-out" style="--pk-pill-enter-delay: 10.0s; --pk-pill-exit-delay: 11.4s;">in progress</span>
<span class="pk-pill pk-pill--completed pk-pill--swap-in" style="--pk-pill-enter-delay: 11.6s;">completed</span>
</div>
</div>
<div class="pk-card" style="animation-delay: 15.0s;">
<div class="pk-card__title">Telegram cockpit</div>
<div class="r26-sub">Today brief, approvals, chat. One socket.</div>
<div class="pk-card__meta">
<span class="pk-chip pk-chip--gray">telegram</span>
</div>
<div class="pk-card__status">
<span class="pk-pill pk-pill--progress pk-pill--swap-out" style="--pk-pill-enter-delay: 15.0s; --pk-pill-exit-delay: 16.4s;">in progress</span>
<span class="pk-pill pk-pill--completed pk-pill--swap-in" style="--pk-pill-enter-delay: 16.6s;">completed</span>
</div>
</div>
<div class="pk-card" style="animation-delay: 20.0s;">
<div class="pk-card__title">Guard mode: active</div>
<div class="r26-sub">fastapi-guard stops watching, starts blocking.</div>
<div class="pk-card__meta">
<span class="pk-chip pk-chip--gray">fastapi-guard</span>
</div>
<div class="pk-card__status">
<span class="pk-pill pk-pill--progress pk-pill--swap-out" style="--pk-pill-enter-delay: 20.0s; --pk-pill-exit-delay: 21.4s;">in progress</span>
<span class="pk-pill pk-pill--completed pk-pill--swap-in" style="--pk-pill-enter-delay: 21.6s;">completed</span>
</div>
</div>
</div>
<!-- The cursor is the CEO's hand: settle on the intake while it
types, ONE submit click just before the org takes over, then
travel to witness each card completing (the agents do the
clicking-free work), drift to the receipt, acknowledge the
toast, and leave the frame; never freeze, never blink out. -->
<div class="pk-cursor"
data-waypoints="4.0 640 210; 4.5 552 152; 4.8 545 148 click;
5.6 300 330; 6.4 160 405; 7.6 178 420;
9.6 260 520; 10.4 190 628; 12.0 172 642;
14.6 250 760; 15.4 162 848; 17.0 180 862;
19.6 255 985; 20.4 190 1068; 22.0 174 1082;
23.6 420 1180; 24.8 560 1250; 28.6 585 1268;
29.6 615 1420; 30.8 612 1462 click;
33.2 700 1520; 35.0 940 1660">
<div class="pk-cursor__glyph"></div>
</div>
<!-- Beat 5: receipt stats. -->
<div class="r26-stats">
<div class="r26-stats__line" style="animation-delay: 24.0s;">1 release</div>
<div class="r26-stats__line r26-stats__line--accent" style="animation-delay: 24.3s;">3 forges</div>
<div class="r26-stats__line" style="animation-delay: 24.6s;">0 leaks</div>
</div>
<!-- Beat 6: confirmation toast, then lockup. -->
<div class="pk-toast" style="animation-delay: 30.0s;">
<div class="pk-toast__icon"></div>
<div class="pk-toast__body">
<div class="pk-toast__title" id="toastTitle">v0.26.0 shipped</div>
<div class="pk-toast__text" id="toastBody">I approved once. 25 agents shipped it.</div>
</div>
</div>
<div class="pk-outro" style="animation-delay: 36.0s;">
<span class="r26-outro__logo"><img src="../../public/roboco-logo.png" alt="" /></span>
<span>roboco.tech</span>
</div>
</div>
</div>
</div>
</div>
<script>
window.__timelines = window.__timelines || {};
window.__timelines["release-0.26.0"] = {
id: "release-0.26.0",
duration: 40,
fps: 30,
animations: []
};
(function () {
var props = (window.__PROPS__ && typeof window.__PROPS__ === "object") ? window.__PROPS__ : {};
function setText(id, value) {
if (typeof value !== "string" || !value) return;
var el = document.getElementById(id);
if (el) el.textContent = value;
}
setText("toastTitle", props.toastTitle);
setText("toastBody", props.toastBody);
function typeReveal(el) {
var n = (el.textContent || "").length || 1;
el.style.setProperty("--type-ch", (n + 1) + "ch");
el.style.animation = "type-reveal " + (n * 0.07).toFixed(2) + "s steps(" + n + ", end) 4.0s forwards";
}
var typeEl = document.getElementById("typeIntro");
if (typeEl) {
if (typeof props.introText === "string" && props.introText) {
typeEl.textContent = props.introText;
}
typeReveal(typeEl);
}
window.PanelKit.choreographAllCursors();
window.PanelKit.choreographAllCameras();
})();
</script>
</body>
</html>