open-design/skills/swiss-user-research-video-template/example.html
Tuola-waj dd439c29bf
add swiss-user-research-video-template template skill (#1054)
Introduce a Swiss editorial user-research live-artifact template with self-contained HTML seed/example and checklist, and register i18n fallback ids for DE/FR/RU so localized coverage stays green.

Co-authored-by: Tuola Ge <gexingli@refly.ai>
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-09 17:00:00 +08:00

265 lines
9.8 KiB
HTML

<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>User Research Synthesis Example</title>
<style>
:root {
--paper: #f7f6ea;
--ink: #161616;
--muted: #5d5a51;
--line: rgba(22, 22, 22, 0.2);
--seg1: #171717;
--seg2: #595959;
--seg3: #8b8b84;
--seg4: #c8c8bf;
}
* { box-sizing: border-box; }
body {
margin: 0;
font-family: Inter, "Helvetica Neue", Arial, sans-serif;
background: var(--paper);
color: var(--ink);
-webkit-font-smoothing: antialiased;
min-height: 100vh;
}
.deck {
max-width: 1360px;
min-height: 860px;
margin: 26px auto;
border: 1px solid rgba(22, 22, 22, 0.08);
background: var(--paper);
box-shadow: 0 18px 60px rgba(0, 0, 0, 0.08);
display: flex;
flex-direction: column;
position: relative;
overflow: hidden;
}
.toolbar {
display: flex;
justify-content: space-between;
align-items: center;
padding: 14px 20px;
border-bottom: 1px solid var(--line);
font-size: 12px;
letter-spacing: 0.18em;
text-transform: uppercase;
color: var(--muted);
}
.toolbar .btns { display: flex; gap: 8px; }
.toolbar button {
border: 1px solid var(--line);
background: transparent;
color: var(--ink);
border-radius: 999px;
height: 30px;
padding: 0 12px;
font-size: 11px;
letter-spacing: 0.08em;
cursor: pointer;
}
.slides { position: relative; flex: 1; }
.slide {
position: absolute;
inset: 0;
padding: 52px 64px;
opacity: 0;
transform: translateX(28px);
transition: opacity .45s ease, transform .45s ease;
pointer-events: none;
}
.slide.active {
opacity: 1;
transform: translateX(0);
pointer-events: auto;
}
.rule-top, .rule-bottom {
height: 1px;
background: var(--line);
transform-origin: 0 50%;
transform: scaleX(0);
transition: transform .6s ease;
}
.slide.active .rule-top, .slide.active .rule-bottom { transform: scaleX(1); }
.meta { font-size: 11px; letter-spacing: .24em; text-transform: uppercase; color: var(--muted); }
h1, h2 { font-weight: 300; letter-spacing: -0.02em; margin: 0; }
h1 { font-size: 88px; line-height: 1.02; margin-top: 24px; }
h2 { font-size: 58px; line-height: 1.05; margin-top: 18px; }
p { color: var(--muted); line-height: 1.55; }
.s1-main { margin-top: 84px; max-width: 980px; }
.s1-main p { font-size: 24px; max-width: 760px; margin-top: 26px; }
.foot {
position: absolute;
left: 64px;
right: 64px;
bottom: 44px;
display: flex;
justify-content: space-between;
font-size: 11px;
letter-spacing: .2em;
text-transform: uppercase;
color: var(--muted);
}
.s2-grid {
margin-top: 52px;
display: grid;
grid-template-columns: 420px 1fr;
gap: 80px;
align-items: center;
}
.donut-wrap { width: 420px; height: 420px; margin: 0 auto; }
.legend { display: grid; gap: 18px; }
.legend-row {
display: grid;
grid-template-columns: 16px 1fr auto;
gap: 14px;
align-items: center;
font-size: 21px;
transition: transform .2s ease;
}
.legend-row:hover { transform: translateX(6px); }
.swatch { width: 16px; height: 16px; border-radius: 2px; }
.pct { font-variant-numeric: tabular-nums; color: var(--muted); font-size: 20px; }
.s3-grid {
margin-top: 44px;
display: grid;
grid-template-columns: 1fr 520px;
gap: 52px;
}
.s3-grid p { font-size: 29px; max-width: 760px; margin-top: 16px; }
.bullets { margin-top: 30px; display: grid; gap: 14px; font-size: 20px; }
.bullets div { padding-left: 24px; position: relative; }
.bullets div::before { content: "—"; position: absolute; left: 0; color: var(--muted); }
.evidence {
border: 1px solid var(--line);
min-height: 360px;
display: grid;
place-items: center;
color: var(--muted);
position: relative;
background: linear-gradient(140deg, rgba(0, 0, 0, 0.02), rgba(0, 0, 0, 0.06));
transition: box-shadow .3s ease, transform .3s ease;
}
.evidence:hover {
box-shadow: 0 24px 48px rgba(0, 0, 0, 0.12);
transform: translateY(-2px);
}
.cap { font-size: 12px; letter-spacing: .1em; margin-top: 14px; color: var(--muted); }
.dots {
position: absolute;
left: 50%;
bottom: 14px;
transform: translateX(-50%);
display: flex;
gap: 12px;
z-index: 20;
}
.dots button {
width: 9px; height: 9px; border-radius: 50%;
border: 1px solid var(--ink);
background: transparent; cursor: pointer;
}
.dots button.active { background: var(--ink); transform: scale(1.3); }
</style>
</head>
<body>
<main class="deck">
<header class="toolbar">
<span>Swiss research synthesis</span>
<div class="btns">
<button type="button" id="prevBtn">Prev</button>
<button type="button" id="nextBtn">Next</button>
</div>
</header>
<section class="slides">
<article class="slide active" data-slide="0">
<div class="rule-top"></div>
<div class="s1-main">
<div class="meta">User research synthesis · May, 2026</div>
<h1>User Research Synthesis</h1>
<p>What we learned from 24 interviews and what it means for the product roadmap.</p>
</div>
<div class="rule-bottom" style="margin-top: 84px;"></div>
<div class="foot"><span>Research team · May, 2026</span><span>Round 1 · Internal</span></div>
</article>
<article class="slide" data-slide="1">
<div class="rule-top"></div>
<div class="meta" style="margin-top: 10px;">Participant breakdown</div>
<h2>Who we spoke with</h2>
<div class="s2-grid">
<div class="donut-wrap">
<svg viewBox="0 0 400 400" width="420" height="420" aria-label="Participant donut">
<g transform="translate(200 200) rotate(-90)" fill="none" stroke-width="38">
<circle r="118" cx="0" cy="0" stroke="var(--seg1)" stroke-dasharray="283.39 741.78"></circle>
<circle r="118" cx="0" cy="0" stroke="var(--seg2)" stroke-dasharray="186.44 741.78" stroke-dashoffset="-283.39"></circle>
<circle r="118" cx="0" cy="0" stroke="var(--seg3)" stroke-dasharray="163.19 741.78" stroke-dashoffset="-469.83"></circle>
<circle r="118" cx="0" cy="0" stroke="var(--seg4)" stroke-dasharray="108.76 741.78" stroke-dashoffset="-633.02"></circle>
</g>
</svg>
</div>
<div class="legend">
<div class="legend-row"><span class="swatch" style="background:var(--seg1)"></span><span>Power users</span><span class="pct">38%</span></div>
<div class="legend-row"><span class="swatch" style="background:var(--seg2)"></span><span>Casual users</span><span class="pct">25%</span></div>
<div class="legend-row"><span class="swatch" style="background:var(--seg3)"></span><span>Churn-risk users</span><span class="pct">22%</span></div>
<div class="legend-row"><span class="swatch" style="background:var(--seg4)"></span><span>Prospects</span><span class="pct">15%</span></div>
</div>
</div>
<div class="rule-bottom" style="margin-top: 18px;"></div>
<div class="foot"><span>Source: Recruitment screener</span><span>Total participants: 24</span></div>
</article>
<article class="slide" data-slide="2">
<div class="rule-top"></div>
<div class="s3-grid">
<div>
<div class="meta">The pattern</div>
<h2>The first 48 hours determine everything</h2>
<p>Users who complete three core actions in their first two days have a 4x higher 90-day retention rate.</p>
<div class="bullets">
<div>Onboarding drop-off peaks at step 3</div>
<div>"What do I do next?" is the most common exit trigger</div>
<div>Users who invite a teammate retain at 2x the rate</div>
</div>
</div>
<div>
<div class="evidence">Session image placeholder</div>
<div class="cap">Session recording review · April, 2026</div>
</div>
</div>
<div class="rule-bottom" style="margin-top: 24px;"></div>
<div class="foot"><span>User research synthesis</span><span>Research team</span></div>
</article>
</section>
<nav class="dots" aria-label="Slide navigation">
<button type="button" class="active" data-dot="0" aria-label="Slide 1"></button>
<button type="button" data-dot="1" aria-label="Slide 2"></button>
<button type="button" data-dot="2" aria-label="Slide 3"></button>
</nav>
</main>
<script>
(function () {
const slides = Array.from(document.querySelectorAll(".slide"));
const dots = Array.from(document.querySelectorAll(".dots button"));
let idx = 0;
const max = slides.length - 1;
function show(next) {
idx = Math.max(0, Math.min(max, next));
slides.forEach((el, i) => el.classList.toggle("active", i === idx));
dots.forEach((el, i) => el.classList.toggle("active", i === idx));
}
document.getElementById("prevBtn").addEventListener("click", () => show(idx - 1));
document.getElementById("nextBtn").addEventListener("click", () => show(idx + 1));
dots.forEach((dot, i) => dot.addEventListener("click", () => show(i)));
document.addEventListener("keydown", (event) => {
if (event.key === "ArrowLeft") show(idx - 1);
if (event.key === "ArrowRight") show(idx + 1);
});
})();
</script>
</body>
</html>