Gate consistency video to members; embed on rhythm page; add vertical cut

- Members-only: the stay-consistent video now requires a wallet-verified session
  (server 403 + training-page lock UI), matching Module 3.
- Embedded on /weekly-rhythm above the sheet (hidden in print) with a members-only
  fallback card for signed-out visitors.
- Added a ~31s vertical (1080x1920) social cut, ungated, for Telegram/social.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
martbost
2026-09-08 06:08:46 -05:00
parent 47955c6b56
commit 946a9d75b5
4 changed files with 18 additions and 3 deletions
+1 -1
View File
@@ -30,7 +30,7 @@ if(tid&&/^\d+$/.test(tid))document.querySelectorAll('a[href^="/tools"]').forEach
'use strict'; 'use strict';
const gated=[...document.querySelectorAll('video')].filter(v=>{ const gated=[...document.querySelectorAll('video')].filter(v=>{
const s=v.getAttribute('src')||''; const s=v.getAttribute('src')||'';
return (/\/v\/rmc-method-m\d+l\d+-/.test(s)&&s.indexOf('rmc-method-m1l1-')<0)||s.indexOf('/training/egift_cards.mp4')>=0; return (/\/v\/rmc-method-m\d+l\d+-/.test(s)&&s.indexOf('rmc-method-m1l1-')<0)||s.indexOf('/v/rmc-stay-consistent-')>=0||s.indexOf('/training/egift_cards.mp4')>=0;
}); });
if(!gated.length)return; if(!gated.length)return;
let member=null; let member=null;
Binary file not shown.
+16 -1
View File
@@ -24,7 +24,7 @@
@media print{ @media print{
@page{size:letter;margin:0.55in} @page{size:letter;margin:0.55in}
body{background:#fff!important;color:#111!important} body{background:#fff!important;color:#111!important}
header,footer,nav,#fsPrintBtn,#rmcTrBtn,#rmcTrPanel,.chat-fab,.chat-panel,.fs-print-btn,.pp-stack{display:none!important} header,footer,nav,#fsPrintBtn,#rmcTrBtn,#rmcTrPanel,.chat-fab,.chat-panel,.fs-print-btn,.pp-stack,.wr-video{display:none!important}
.fs-wrap{max-width:none;padding:0} .fs-wrap{max-width:none;padding:0}
.fs-sheet{background:#fff;border:0;border-radius:0;padding:0;color:#111} .fs-sheet{background:#fff;border:0;border-radius:0;padding:0;color:#111}
.fs-sheet h1,.fs-sec h2{color:#111} .fs-sheet h1,.fs-sec h2{color:#111}
@@ -38,6 +38,10 @@
<body> <body>
<div class="scr-nav"><a href="/my">← My Dashboard</a><a href="/suite">🧰 My Tools</a><a href="/tools">🎬 Promo Tools</a></div> <div class="scr-nav"><a href="/my">← My Dashboard</a><a href="/suite">🧰 My Tools</a><a href="/tools">🎬 Promo Tools</a></div>
<div class="fs-wrap"> <div class="fs-wrap">
<div class="wr-video" style="max-width:820px;margin:0 auto 22px">
<div style="font-weight:800;font-size:18px;margin:0 0 8px">▶ Watch first — Consistency Wins the Race</div>
<video id="wrVid" class="video-frame" style="display:block;width:100%;border-radius:12px;aspect-ratio:16/9;background:#000" controls preload="none" poster="/v/rmc-stay-consistent-poster.jpg" src="/v/rmc-stay-consistent-bfbaa04500.mp4"></video>
</div>
<div class="fs-sheet"> <div class="fs-sheet">
<h1>🔁 The Weekly Rhythm</h1> <h1>🔁 The Weekly Rhythm</h1>
<p class="tag">Twenty minutes. Same time. Every week. Put it in the calendar like a dentist appointment you can't weasel out of.</p> <p class="tag">Twenty minutes. Same time. Every week. Put it in the calendar like a dentist appointment you can't weasel out of.</p>
@@ -80,6 +84,17 @@
<a href="/training#stay-consistent" class="btn btn-secondary" style="margin-left:8px">▶ Watch: Stay consistent</a><a href="/training#lesson-10" class="btn btn-secondary" style="margin-left:8px">▶ Watch Lesson 10</a> <a href="/training#stay-consistent" class="btn btn-secondary" style="margin-left:8px">▶ Watch: Stay consistent</a><a href="/training#lesson-10" class="btn btn-secondary" style="margin-left:8px">▶ Watch Lesson 10</a>
<a href="/my" class="btn btn-secondary" style="margin-left:8px">← My dashboard</a></div> <a href="/my" class="btn btn-secondary" style="margin-left:8px">← My dashboard</a></div>
</div> </div>
<script>
(async function(){
var v=document.getElementById('wrVid'); if(!v) return;
var member=null; try{ var r=await fetch('/api/public/msg-me'); if(r.ok) member=await r.json(); }catch(e){}
if(member&&member.id) return; // signed-in member: leave the player as-is
var box=document.createElement('div'); box.className='video-frame';
box.style.cssText='display:flex;align-items:center;justify-content:center;aspect-ratio:16/9;border-radius:12px;background:#08131f;text-align:center;padding:20px';
box.innerHTML='<div><div style="font-size:30px">🔒</div><div style="font-weight:800;margin:6px 0 4px">Members area</div><p class="micro" style="color:var(--muted,#aebdca);margin:0 0 12px;max-width:440px">This one is for members. Open it from the training page with the wallet that owns your position, or through the Telegram Mini App.</p><a class="btn btn-secondary" href="/training#stay-consistent">Unlock on the training page</a></div>';
v.replaceWith(box);
})();
</script>
<script src="/qrlib.js"></script> <script src="/qrlib.js"></script>
<script src="/fast-start.js"></script> <script src="/fast-start.js"></script>
<script src="/chat.js" defer></script> <script src="/chat.js" defer></script>
+1 -1
View File
@@ -1616,7 +1616,7 @@ const server=http.createServer(async(req,res)=>{
// member session (web sign-in or the Mini App auth bridge). Lesson 1, all // member session (web sign-in or the Mini App auth bridge). Lesson 1, all
// posters, and every join-funnel/transparency video stay public on purpose: // posters, and every join-funnel/transparency video stay public on purpose:
// Lesson 1 is the free preview, the rest is the trust engine. // Lesson 1 is the free preview, the rest is the trust engine.
if((/^\/v\/rmc-method-m\d+l\d+-[0-9a-f]+\.mp4$/.test(pathname)&&!/^\/v\/rmc-method-m1l1-/.test(pathname))||pathname==='/training/egift_cards.mp4'){ if((/^\/v\/rmc-method-m\d+l\d+-[0-9a-f]+\.mp4$/.test(pathname)&&!/^\/v\/rmc-method-m1l1-/.test(pathname))||/^\/v\/rmc-stay-consistent-[0-9a-f]+\.mp4$/.test(pathname)||pathname==='/training/egift_cards.mp4'){
if(!messages.authFromCookie(req))return json(res,403,{error:'Members area — sign in on the training page with the wallet that owns your position, or open it through the Telegram Mini App.'},{'Cache-Control':'no-store'}); if(!messages.authFromCookie(req))return json(res,403,{error:'Members area — sign in on the training page with the wallet that owns your position, or open it through the Telegram Mini App.'},{'Cache-Control':'no-store'});
} }
if(pathname==='/unsubscribe'){ if(pathname==='/unsubscribe'){