Skill: Telly interaktivní report

Návod pro AI (Claude, Cursor, ChatGPT…), jak vyrobit interaktivní HTML report nebo prezentaci v Telly brandu. Jeden samostatný soubor: boční menu, grafy, přepínače zobrazení, tisk do PDF. Zkopíruj celý dokument do své AI spolu s daty a popiš, co má report ukázat.

Jak skill použít (pro tebe, ne pro AI)

  1. Připrav data (export z dotazníku, tabulka výsledků, čísla kampaně)
  2. Vlož do AI tento celý dokument + data + zadání, např.: „Vyrob interaktivní Telly report podle přiloženého skillu. Data v příloze. Segmenty porovnej po krajích.”
  3. Výstup je jeden HTML soubor. Otevři v prohlížeči, pošli přílohou, nebo dej Honzovi na marketing hub.

Instrukce pro AI

Report negeneruj ručně jako jeden dlouhý HTML string v hlavě. Postav Python generátor (data → HTML), aby šel report přegenerovat při změně dat. Čísla ber vždy z agregovaných dat (JSON/CSV), nikdy je nepiš do šablony ručně — ruční přepis je nejčastější zdroj chyb v číslech.

Workflow:

  1. Data: agregace do JSON (počty, procenta, po segmentech). Zvlášť drž metadata (n, období sběru).
  2. Generátor: Python skript skládá HTML z komponent (níže). Ulož ho vedle dat, je součást deliverable.
  3. Ověření: otevři výsledek v prohlížeči a proklikej interaktivitu (menu, přepínače, koláče, tisk). Neodevzdávej bez ověření.
  4. Předání: soubor funguje jako příloha (vše inline). Google Drive HTML nerenderuje — upozorni na to.

Brand (zdroj: brand manuál Telly, viz Marketingová knihovna)

TokenHodnotaPoužití
Telly Blue#1e1ec8primární — sidebar, nadpisy, hlavní data
Azure Blue#0096fasekundární datová řada (např. SAT vs OTT)
Telly Black#111111text, řada „Celkem”
Pink Red#ff005azvýraznění, čísla doporučení, rizika
Yellow#ffd60bCTA tlačítka, aktivní stav, citace
Turquoise#00c8a0sport, pozitivní zjištění
  • Font: "Neue Haas Grotesk Display Pro","Helvetica Neue",Helvetica,Arial,sans-serif (brand fallback řetězec — Neue Haas je jen v Adobe Fonts, web ho mít nebude)
  • Tvary: zaoblený levý horní a pravý dolní roh (border-radius:18px 5px 18px 5px) — poznávací prvek Telly, použij na karty, tlačítka, chipy
  • Logo: inline SVG z oficiálního SVG loga (academy.telly.cz/academy-telly-logo.svg, nebo si ho vyžádej). Pravidlo z manuálu: tmavý podklad = bílé logo.
  • Žádné dlouhé pomlčky v textech (em dash je LLM tell). Citace zákazníků doslovně.

Struktura reportu

┌──────────┬──────────────────────────────┐
│ sidebar  │  hero (Telly Blue, titulek,  │
│ (fixed,  │   meta-chipy s n)            │
│  264px,  ├──────────────────────────────┤
│  Telly   │  Klíčová zjištění (karty)    │
│  Blue)   │  Sekce s grafy per otázka    │
│          │  Souvislosti (cross-analýzy) │
│ logo     │  Citace / otevřené odpovědi  │
│ nav      │  Doporučení (číslované)      │
│ přepínač │  Metodika                    │
│ PDF btn  │  footer (logo + datum)       │
└──────────┴──────────────────────────────┘

Pořadí vyprávění: zjištění → důkazy → souvislosti → doporučení. Manažer čte jen karty zjištění; analytik si rozklikne detaily. Doporučení vždy akční (co udělat), ne popisná.

Komponenty

Hotové ověřené CSS/JS bloky jsou v v sekci „Komponenty: hotový kód” níže. Obsahuje:

  1. Sidebar + scrollspy — fixní menu, aktivní sekce přes IntersectionObserver/scroll handler, mobil = hamburger (pozor: logo posunout doprava, ať ho hamburger nepřekrývá)
  2. Přepínač zobrazení dat — globální body[data-view] + CSS skrývání řad; standardně režimy Porovnání segmentů / Jen celkem / Vše
  3. Pruhové grafy — řádek per segment, animace šířky přes IntersectionObserver (data-w → width), beforeprint vše naplno
  4. Koláče (donuty) — inline SVG, kruhy se stroke-dasharray; jen pro jednovýběrové otázky (podíly se sčítají do 100 %). U vícevýběrových koláč lže — nech jen pruhy. Přepínač pruhy/koláč per karta.
  5. Rozklikávací detaily<details class="expand"> pro dlouhé tabulky (všichni poskytovatelé…) a otevřené odpovědi
  6. Citace<blockquote> se žlutým okrajem, doslovné, s označením segmentu
  7. Tisk do PDF — tlačítko window.print(), @media print skryje sidebar, break-inside:avoid-page, print-color-adjust:exact

Datová poctivost

  • U každého grafu uveď bázi (n=…), zvlášť když se liší od celku (filtrovaná podotázka)
  • Samovýběrový vzorek = napiš metodickou poznámku, ať čísla nikdo nečte jako reprezentativní
  • Procenta + absolutní čísla vedle sebe: 58 % (334)
  • Vícevýběrové otázky: podíl z respondentů, ne z odpovědí — a řekni to v popisku

Časté chyby (z praxe)

  • scroll-behavior:smooth nefunguje v headless preview — ověřuj scroll s behavior:'instant', smooth nech pro uživatele
  • Screenshot v Claude Preview po scrollu bývá prázdný (render bug) — posouvej obsah přes transform:translateY() na .main, screenshot pak funguje; transform před měřením pozic resetuj
  • Koláč u vícevýběrové otázky (součet > 100 %) — nikdy
  • Čísla psaná ručně do šablony místo z dat — vždy generuj

Komponenty Telly interaktivního reportu

Ověřené bloky z reportu „Vylaďte 2026” (plný funkční příklad: interaktivní report výzkumu na marketing.telly.cz/vyzkumy). Bloky jsou k převzetí, přizpůsob názvy segmentů a sekcí konkrétnímu reportu.

Obsah

  1. Kostra stránky + CSS proměnné
  2. Sidebar + scrollspy + mobil
  3. Přepínač zobrazení dat
  4. Pruhové grafy s animací
  5. Koláče (SVG donuty)
  6. Karta s přepínačem pruhy/koláč
  7. Rozklikávací detail + tabulka
  8. Karty zjištění, citace, doporučení
  9. Tisk do PDF

1. Kostra

:root { --blue:#1e1ec8; --azure:#0096fa; --pink:#ff005a; --turq:#00c8a0; --yellow:#ffd60b; --black:#111111; }
* { margin:0; padding:0; box-sizing:border-box; }
html { scroll-behavior:smooth; }
body { font-family:"Neue Haas Grotesk Display Pro","Helvetica Neue",Helvetica,Arial,sans-serif;
       color:#111; background:#f4f4fa; line-height:1.5; }
.main { margin-left:264px; }
.wrap { max-width:1000px; margin:0 auto; padding:0 32px 64px; }
.card { background:#fff; border-radius:18px 5px 18px 5px; padding:28px 30px;
        box-shadow:0 2px 10px rgba(30,30,200,.06); margin-bottom:20px; }

Hero hlavička: Telly Blue pozadí, H1 bílý 2.1rem/800, pod ním meta-chipy (border-radius:14px 4px 14px 4px, rgba(255,255,255,.12); zvýrazněný chip --yellow + černý text).

2. Sidebar

.sidebar { position:fixed; top:0; left:0; bottom:0; width:264px; background:var(--blue);
           color:#fff; display:flex; flex-direction:column; padding:28px 0 20px; z-index:50; overflow-y:auto; }
.sidebar .logo { width:96px; margin:0 28px 8px; }   /* inline SVG bílé logo */
.sidebar nav a { color:#fff; text-decoration:none; font-size:.92rem; padding:9px 28px;
                 border-left:4px solid transparent; opacity:.78; transition:all .15s; display:block; }
.sidebar nav a.active { opacity:1; background:rgba(255,255,255,.12);
                        border-left-color:var(--yellow); font-weight:700; }
.burger { display:none; position:fixed; top:14px; left:14px; z-index:60; width:44px; height:44px;
          border:none; background:var(--blue); color:#fff; border-radius:12px 4px 12px 4px;
          font-size:1.3rem; cursor:pointer; }
@media (max-width:900px) {
  .sidebar { transform:translateX(-100%); transition:transform .25s; width:280px; }
  .sidebar.open { transform:translateX(0); box-shadow:4px 0 24px rgba(0,0,0,.25); }
  .burger { display:block; }
  .sidebar .logo { margin-left:84px; }  /* ať hamburger nepřekrývá logo */
  .main { margin-left:0; }
}
// scrollspy — bez knihoven
var links = [].slice.call(document.querySelectorAll('#nav a'));
var secs = links.map(function (l) { return document.getElementById(l.dataset.sec); });
function spy() {
  var pos = window.scrollY + 120, act = secs[0];
  secs.forEach(function (s) { if (s && s.offsetTop <= pos) act = s; });
  links.forEach(function (l) { l.classList.toggle('active', l.dataset.sec === act.id); });
}
window.addEventListener('scroll', spy, { passive: true }); spy();

// mobil menu
burger.addEventListener('click', function () { sidebar.classList.toggle('open'); });
sidebar.addEventListener('click', function (e) { if (e.target.closest('a')) sidebar.classList.remove('open'); });

Sekce potřebují scroll-margin-top:24px, odkazy <a href="#id" data-sec="id">.

3. Přepínač zobrazení dat

Globální režim na <body data-view="...">, řady grafů mají třídy row-cel/row-ott/row-sat (analogicky koláče pie-cel/...). CSS jen skrývá:

body[data-view="porovnani"] .row-cel { display:none; }
body[data-view="celkem"] .row-ott, body[data-view="celkem"] .row-sat { display:none; }
/* data-view="vse" nechává všechno */
sw.addEventListener('click', function (e) {
  var btn = e.target.closest('button'); if (!btn) return;
  document.body.dataset.view = btn.dataset.view;
  sw.querySelectorAll('button').forEach(function (b) { b.classList.toggle('active', b === btn); });
  animateVisible();   // doanimovat pruhy, které se právě odkryly
});

Tlačítka v sidebaru: border-radius:12px 4px 12px 4px, aktivní = bílé pozadí + modrý text.

4. Pruhy

<div class="bp"><div class="bp-label">Netflix</div><div class="bp-bars">
  <div class="bp-row row-ott"><span class="bp-seg">OTT</span>
    <div class="bp-track"><div class="bp-fill ott" data-w="41.2"></div></div>
    <span class="bp-val">41 % <small>(237)</small></span></div>
  ...
</div></div>
.bp-track { flex:1; background:#ececf6; border-radius:6px 2px 6px 2px; height:16px; overflow:hidden; }
.bp-fill { height:100%; width:0; border-radius:6px 2px 6px 2px;
           transition:width .8s cubic-bezier(.25,.8,.35,1); }
.bp-fill.cel { background:var(--black); } .bp-fill.ott { background:var(--blue); }
.bp-fill.sat { background:var(--azure); }
// animace při vstupu do viewportu
var fills = [].slice.call(document.querySelectorAll('.bp-fill'));
var io = new IntersectionObserver(function (entries) {
  entries.forEach(function (en) { if (en.isIntersecting) {
    en.target.style.width = en.target.dataset.w + '%'; io.unobserve(en.target); } });
}, { threshold: 0.1 });
fills.forEach(function (f) { io.observe(f); });
// helper pro přepínače (odkryté řady mimo IO):
function animateVisible() { fills.forEach(function (f) {
  var r = f.getBoundingClientRect();
  if (r.top < window.innerHeight && r.bottom > 0 && f.offsetParent !== null)
    f.style.width = f.dataset.w + '%'; }); }

5. Koláče

Jen jednovýběrové otázky (součet = 100 %). Generuj v Pythonu:

PALETTE = ['#1e1ec8', '#0096fa', '#00c8a0', '#ffd60b', '#ff005a', '#111111', '#9a9ab0']
CIRC = 2 * math.pi * 40

def donut(seg_label, items, n):           # items: (label, count, color)
    parts, legend, offset = [], [], 0.0
    for label, cnt, color in items:
        frac = cnt / n if n else 0
        dash = frac * CIRC
        parts.append(f'<circle cx="60" cy="60" r="40" fill="none" stroke="{color}" stroke-width="22" '
                     f'stroke-dasharray="{dash:.2f} {CIRC - dash:.2f}" stroke-dashoffset="{-offset:.2f}" />')
        legend.append(f'<li><i style="background:{color}"></i>{label} <b>{100*frac:.0f}&nbsp;%</b> <small>({cnt})</small></li>')
        offset += dash
    svg = (f'<svg viewBox="0 0 120 120" class="donut"><g transform="rotate(-90 60 60)">{"".join(parts)}</g>'
           f'<text x="60" y="56" text-anchor="middle" class="d-seg">{seg_label}</text>'
           f'<text x="60" y="72" text-anchor="middle" class="d-n">n={n}</text></svg>')
    return f'<div class="pie-row"><div class="pie-chart">{svg}</div><ul class="pie-legend">{"".join(legend)}</ul></div>'

Kategorií navíc nad paletu → slož zbytek do „Ostatní” (poslední barva palety). Tři donuty per otázka (celkem/segment A/segment B) ve wrapperech pie-cel/pie-ott/pie-sat, viditelnost řídí stejný body[data-view] mechanismus jako u pruhů.

6. Karta s přepínačem pruhy/koláč

def chart_card(title, bars_html, pies_html, extra=''):
    return f'''<div class="card chart-card">
<div class="chart-head"><h3>{title}</h3>
<div class="chart-toggle"><button class="t-bar active">▮▮ pruhy</button><button class="t-pie">◔ koláč</button></div></div>
<div class="chart-bars">{bars_html}</div>
<div class="chart-pies">{pies_html}</div>
{extra}</div>'''
.chart-card.mode-pie .chart-bars { display:none; }
.chart-card:not(.mode-pie) .chart-pies { display:none; }

JS: klik na toggle → card.classList.toggle('mode-pie', btn.classList.contains('t-pie')) + animateVisible().

7. Rozklikávací detail

.expand { margin-top:16px; border-top:1px solid #ececf6; padding-top:12px; }
.expand summary { cursor:pointer; font-weight:600; color:var(--blue); list-style:none; }
.expand summary::before { content:"▸ "; }  .expand[open] summary::before { content:"▾ "; }
.dtable th { text-align:left; background:var(--blue); color:#fff; padding:7px 12px; }
.dtable td { padding:5px 12px; border-bottom:1px solid #ececf6; }
.dtable tbody tr:nth-child(even) { background:#f7f7fc; }

Použij na: kompletní seznamy (všichni poskytovatelé), otevřené odpovědi, metodické detaily. V summary vždy řekni, co a kolik toho uvnitř je („Zobrazit všechny poskytovatele (68)“).

8. Obsahové komponenty

/* karty zjištění — barevný horní proužek podle typu (modrá neutrální, pink riziko, turq příležitost) */
.finding { background:#fff; border-radius:18px 5px 18px 5px; padding:22px 24px;
           border-top:4px solid var(--blue); }
.finding .big { font-size:1.9rem; font-weight:800; display:block; }  /* hlavní číslo */

/* citace — doslovné, se segmentem */
blockquote { border-left:4px solid var(--yellow); background:#fffdf0; padding:12px 16px;
             border-radius:0 12px 0 12px; font-style:italic; }

/* doporučení — číslovaná pink kostka přes CSS counter */
.reco { counter-reset:reco; }
.reco .card::before { counter-increment:reco; content:counter(reco); background:var(--pink);
  color:#fff; font-weight:800; min-width:44px; height:44px; display:flex; align-items:center;
  justify-content:center; border-radius:14px 4px 14px 4px; }

9. Tisk

@media print {
  .sidebar, .burger { display:none; }
  .main { margin-left:0; }
  section { break-inside:avoid-page; }
  .bp-fill { transition:none; }
  * { -webkit-print-color-adjust:exact; print-color-adjust:exact; }
}
window.addEventListener('beforeprint', function () {
  fills.forEach(function (f) { f.style.width = f.dataset.w + '%'; });
});

Tlačítko v sidebaru: žluté (--yellow, černý text), onclick="window.print()", text „Vytisknout / uložit PDF”.