/** * C196/C197 — the visual templates of the reel, ported class-by-class from the * design artifacts: the family design `docs/plans/reels-tutoriais-ui-design.html` * and the revision `docs/plans/reels-tutoriais-foto-de-perfil-ui-design.html` * (official campaign kit: palette, marks, illustrations, Brexter display face, * command rail, capture brand cap, profile handoff, cover). Every template is a * pure string builder rendered at 360×640 with deviceScaleFactor 3, so the * physical asset is 1080×1920. * * The reel's message is data: hook/cover/CTA/profile copy comes from the shot * list (`graphics.*`); the templates carry structure only. * * Pure module: the caller passes the font CSS and the kit asset data URIs. */ const BRAND = { red: '#e4102f', blue: '#184e92', yellow: '#ffeb00', green: '#009647', cream: '#fff8f2', ink: '#111111', muted: '#6c615e', line: 'rgb(0 0 0 / 12%)', } const BASE_CSS = ` *,*::before,*::after{box-sizing:border-box;margin:0;padding:0} html,body{width:360px;height:640px;overflow:hidden;background:transparent} body{font-family:ReelInter,Inter,ui-sans-serif,system-ui,sans-serif;color:${BRAND.ink};-webkit-font-smoothing:antialiased} .frame{position:relative;width:360px;height:640px;overflow:hidden} .brexter{font-family:ReelBrexter,Impact,Haettenschweiler,'Arial Narrow Bold',sans-serif;font-weight:700;text-transform:uppercase} .kit-asset{display:block;height:auto;object-fit:contain} .pattern-wash{position:absolute;inset:0 0 auto;width:360px;height:540px;object-fit:cover;object-position:top center;opacity:.16;pointer-events:none} .official-mark{position:absolute;display:block;height:auto} /* Capture chrome — a quiet top cap and one command rail, never a central card. */ .capture-brand-cap{position:absolute;z-index:20;inset:0 0 auto;height:38px;background:linear-gradient(90deg,${BRAND.red} 0 78%,${BRAND.blue} 100%);border-bottom:2px solid ${BRAND.yellow};box-shadow:0 4px 12px rgb(0 0 0 / 14%)} .capture-brand-cap img{position:absolute;right:16px;top:7px;width:86px;height:auto} .command-rail{position:absolute;z-index:24;left:16px;top:88px;width:328px;min-height:50px;display:grid;grid-template-columns:auto minmax(0,1fr);align-items:center;gap:10px;padding:8px 12px 8px 8px;border:1px solid rgb(0 0 0 / 10%);border-left:4px solid ${BRAND.red};border-radius:12px;background:rgb(255 255 255 / 96%);box-shadow:0 8px 24px rgb(0 0 0 / 18%);color:${BRAND.ink}} .step-badge{display:grid;width:34px;height:34px;place-items:center;border-radius:50%;background:${BRAND.yellow};color:#000;font-size:11px;font-weight:900;line-height:1;box-shadow:inset 0 0 0 1px rgb(0 0 0 / 8%)} .step-badge--label{width:auto;min-width:70px;border-radius:999px;padding:0 10px} .command-copy{margin:0;max-width:258px;font-size:12.5px;font-weight:800;line-height:1.2;letter-spacing:-.01em} .command-copy strong{color:#a21c1c;font-weight:900} /* Graphic scene: hook. */ .hook-scene{background:linear-gradient(156deg,${BRAND.red} 0 68%,${BRAND.blue} 145%)} .hook-illustration{position:absolute;right:-30px;top:58px;width:154px;opacity:.98} .hook-copy{position:absolute;left:22px;right:20px;top:94px;color:#fff} .hook-eyebrow{display:inline-flex;border-radius:999px;padding:6px 12px;background:${BRAND.yellow};color:#000;font-size:10.5px;font-weight:900;letter-spacing:.06em} .hook-title{width:310px;margin:24px 0 0;font-size:40px;line-height:.88;letter-spacing:-.035em} .hook-sub{width:205px;margin:20px 0 0;font-size:14px;line-height:1.3;font-weight:650} /* Graphic scene: profile handoff. Class names are the port contract. */ .profile-scene{background:linear-gradient(180deg,#fff8f2 0%,#fff 72%,#f3f6fb 100%)} .profile-scene::before{content:'';position:absolute;inset:0 0 auto;height:64px;background:${BRAND.red};border-bottom:4px solid ${BRAND.yellow}} .profile-brand{position:absolute;z-index:3;right:18px;top:16px;width:95px} .profile-heading{position:absolute;z-index:3;left:22px;right:22px;top:88px;text-align:center} .profile-eyebrow{color:${BRAND.red};font-size:10px;font-weight:900;letter-spacing:.12em;text-transform:uppercase} .profile-title{margin-top:5px;color:${BRAND.blue};font-size:27px;line-height:.92;letter-spacing:-.02em} .profile-phones{position:absolute;left:18px;right:18px;top:176px;display:grid;grid-template-columns:1fr 1fr;gap:16px} .profile-phone{position:relative;height:226px;overflow:hidden;border:1px solid rgb(0 0 0 / 12%);border-radius:22px;background:#fff;box-shadow:0 12px 30px rgb(24 78 146 / 13%)} .profile-phone__top{height:38px;display:flex;align-items:center;justify-content:center;border-bottom:1px solid ${BRAND.line};font-size:11px;font-weight:800} .profile-phone--ig .profile-phone__top{color:#9d174d} .profile-phone--wa .profile-phone__top{color:#087a3f} .profile-avatar-shell{position:absolute;left:50%;top:58px;width:82px;height:82px;transform:translateX(-50%);border-radius:50%;padding:4px;background:linear-gradient(135deg,${BRAND.red},${BRAND.yellow},${BRAND.green})} .profile-phone--wa .profile-avatar-shell{background:#d9f6e5} .profile-avatar{position:relative;width:100%;height:100%;overflow:hidden;border:3px solid #fff;border-radius:50%;background:#e7eaee} .profile-avatar img{width:100%;height:100%;object-fit:cover;filter:saturate(0.72);opacity:.58} .profile-handle{position:absolute;left:12px;right:12px;top:151px;text-align:center;font-size:10px;font-weight:800} .profile-lines{position:absolute;left:34px;right:34px;top:172px;display:grid;gap:6px} .profile-lines span{height:5px;border-radius:999px;background:#e7e7e7} .profile-lines span:last-child{margin-inline:11px} .profile-card{position:absolute;z-index:10;left:145px;top:330px;width:70px;height:70px;overflow:hidden;border:3px solid #fff;border-radius:12px;background:#dfe9f0;box-shadow:0 10px 24px rgb(0 0 0 / 24%);opacity:0} .profile-card__photo{width:100%;height:100%;object-fit:cover} .profile-card__frame{position:absolute;inset:0;width:100%;height:100%} .profile-check{position:absolute;z-index:12;top:344px;display:grid;width:28px;height:28px;place-items:center;border:3px solid #fff;border-radius:50%;background:${BRAND.green};color:#fff;font-size:15px;font-weight:900;opacity:0;transform:scale(.65)} .profile-check--ig{left:118px} .profile-check--wa{right:34px} .profile-footnote{position:absolute;left:22px;right:22px;top:370px;text-align:center;color:${BRAND.blue};font-size:11px;font-weight:800} @keyframes profile-heading-in{0%{opacity:0;transform:translateY(12px)}100%{opacity:1;transform:translateY(0)}} @keyframes profile-phones-in{0%{opacity:0;transform:translateY(20px)}100%{opacity:1;transform:translateY(0)}} @keyframes profile-to-instagram{0%,12%{opacity:0;transform:translate(0,12px) scale(.88);border-radius:12px}24%{opacity:1;transform:translate(0,0) scale(1);border-radius:12px}62%,100%{opacity:1;transform:translate(-87px,-100px) scale(1.06);border-radius:50%}} @keyframes profile-to-whatsapp{0%,46%{opacity:0;transform:translate(0,12px) scale(.88);border-radius:12px}58%{opacity:1;transform:translate(0,0) scale(1);border-radius:12px}88%,100%{opacity:1;transform:translate(87px,-100px) scale(1.06);border-radius:50%}} @keyframes profile-check-in{0%,78%{opacity:0;transform:scale(.65)}88%{opacity:1;transform:scale(1.15)}100%{opacity:1;transform:scale(1)}} @keyframes profile-done-pulse{0%,85%,100%{box-shadow:0 12px 30px rgb(24 78 146 / 13%)}92%{box-shadow:0 0 0 4px rgb(255 235 0 / 65%),0 12px 30px rgb(24 78 146 / 13%)}} .play .profile-heading{animation:profile-heading-in .42s cubic-bezier(.2,.7,.2,1) both} .play .profile-phones{animation:profile-phones-in .5s cubic-bezier(.2,.7,.2,1) .3s both} .play .profile-card--ig{animation:profile-to-instagram 2.15s cubic-bezier(.2,.7,.2,1) .55s both} .play .profile-card--wa{animation:profile-to-whatsapp 2.9s cubic-bezier(.2,.7,.2,1) .55s both} .play .profile-check{animation:profile-check-in 3.35s cubic-bezier(.2,.8,.2,1) .35s both} .play .profile-phone{animation:profile-done-pulse 4s ease-out both} /* Graphic scene: CTA. */ .cta-scene{background:${BRAND.cream}} .cta-red{position:absolute;inset:0 0 auto;height:306px;overflow:hidden;background:${BRAND.red}} .cta-punho{position:absolute;left:-38px;top:42px;width:180px;opacity:.98} .cta-copy{position:absolute;left:132px;right:20px;top:90px;color:#fff;text-align:left} .cta-copy p{margin:0;color:${BRAND.yellow};font-size:10px;font-weight:900;letter-spacing:.1em;text-transform:uppercase} .cta-copy h3{margin:10px 0 0;font-size:36px;line-height:.88;letter-spacing:-.025em} .cta-card{position:absolute;left:22px;right:22px;top:328px;padding:20px 18px;border:1px solid ${BRAND.line};border-radius:18px;background:#fff;text-align:center;box-shadow:0 14px 36px rgb(71 19 14 / 14%)} .cta-card__eyebrow{color:${BRAND.red};font-size:10px;font-weight:900;letter-spacing:.1em;text-transform:uppercase} .cta-card__action{margin-top:5px;color:${BRAND.blue};font-size:29px;line-height:.95} .cta-card__sub{margin-top:8px;color:${BRAND.muted};font-size:11px;line-height:1.35} .cta-url{position:absolute;left:22px;bottom:30px;color:${BRAND.blue};font-size:10px;font-weight:800} /* Cover. */ .cover-scene{background:linear-gradient(156deg,${BRAND.red} 0 72%,${BRAND.blue} 155%)} .cover-copy{position:absolute;left:24px;right:20px;top:132px;color:#fff} .cover-copy h3{margin:24px 0 0;font-size:44px;line-height:.86;letter-spacing:-.035em} .cover-copy p{width:232px;margin:20px 0 0;font-size:13px;line-height:1.3;font-weight:650} .cover-tag{position:absolute;left:24px;top:500px;border-radius:7px;background:rgb(0 0 0 / 35%);padding:6px 11px;color:#fff;font-size:10px;font-weight:800} /* Family motion vocabulary (hook/CTA). */ @keyframes reel-beat{0%{opacity:0;transform:translateY(14px)}100%{opacity:1;transform:translateY(0)}} @keyframes reel-fade{0%{opacity:0}100%{opacity:1}} @keyframes reel-derive{0%{opacity:0;transform:translateX(8px)}100%{opacity:1;transform:translateX(0)}} @keyframes reel-rise{0%{opacity:0;transform:translateY(18px)}100%{opacity:1;transform:translateY(0)}} @keyframes reel-punch{0%{opacity:0;transform:translateX(-16px)}100%{opacity:1;transform:translateX(0)}} .play .fade-1{animation:reel-fade .45s ease-out .15s both} .play .beat-1{animation:reel-beat .55s cubic-bezier(.2,.7,.2,1) both} .play .beat-2{animation:reel-beat .55s cubic-bezier(.2,.7,.2,1) .28s both} .play .rise-1{animation:reel-rise .5s cubic-bezier(.2,.7,.2,1) .35s both} .play .derive-1{animation:reel-derive .65s ease-out .1s both} .play .punch-1{animation:reel-punch .6s ease-out both} ` const htmlDocument = ({ title, fontCss, body }) => `
${parts}
${copy.sub}
${variant === 'ig' ? '@seuperfil' : 'Seu perfil'}
${copy.eyebrow}
${copy.instruction}
${copy.eyebrow}
FAÇA A SUA
${copy.actionLines.join('
')}
${copy.sub}
${copy.url}
${copy.sub}