Viral welcome tour + line banner + wall, milestone stepper, rich solo editor, CTA-gated reads

- Welcome tour (3 levels x 10s) unlocks welcome credits; line banner in Profile; public /wall/<username>
- 'Your next move' redesigned as a milestone stepper
- Solo composer: BV-style rich editor (H2/H3, inline image+video, undo/redo, raw text)
- Solo read reward now requires clicking through to the advertiser, not just dwelling
- Sanitizer: inline media whitelist + script/style stripped whole

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
martbost
2026-09-06 07:30:49 -05:00
parent 718d7f2d0e
commit 1ee0b5626e
15 changed files with 477 additions and 80 deletions
+68 -25
View File
@@ -4,7 +4,7 @@
<meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
<title>Member area | InstantAdPay</title>
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Sora:wght@600;700;800&display=swap">
<link rel="stylesheet" href="/assets/site.css?v=20260905r">
<link rel="stylesheet" href="/assets/site.css?v=20260905u">
</head>
<body class="bo-body">
@@ -67,6 +67,21 @@
</div>
</div>
<!-- ── welcome tour: meet your 3-level line, then unlock welcome credits ── -->
<div id="gauntGate" class="lgate" hidden>
<div class="lgate-bar">
<span class="lg-brand">Instant<em>AdPay</em></span>
<span class="lgate-note small muted" id="ggNote">Welcome tour: meet the three levels your growth pays.</span>
<span class="lg-timer mono" id="ggTimer">…</span>
</div>
<div class="ggmeta small muted" id="ggWho"></div>
<iframe class="lgate-frame" id="ggFrame" sandbox="allow-scripts allow-same-origin allow-forms allow-popups" referrerpolicy="no-referrer" title="Team member site"></iframe>
<div class="lgate-bar" style="border-top:1px solid var(--line);border-bottom:0">
<span class="small muted" id="ggProgress"></span>
<button class="btn small" id="ggClaim" type="button" hidden>Claim your welcome credits</button>
</div>
</div>
<!-- ── signed-in: back-office shell ──────────────────────── -->
<div id="memberArea" class="bo" hidden>
<aside class="bo-side" id="boSide">
@@ -152,15 +167,15 @@
<div class="chart-x" id="chCampX"></div>
</div>
</div>
<div class="card" id="nextCard">
<h3>Your next move</h3>
<p class="muted" id="nextMove">…</p>
<div id="qualBarWrap">
<div class="qualbar"><div id="qualFill"></div>
<span class="qb-mark" style="left:40%">2 · level 2</span>
<span class="qb-mark end">5 · level 3</span>
<div class="card next-card" id="nextCard">
<div class="nc-head">
<div class="pl"><svg viewBox="0 0 24 24"><path d="M6 3v18"/><path d="M6 4h11l-2.5 4 2.5 4H6"/></svg></div>
<div>
<h3 style="margin:0">Your next move</h3>
<p class="muted small" id="nextMove" style="margin:5px 0 0">…</p>
</div>
</div>
<div class="nc-steps" id="ncSteps"></div>
</div>
<div class="grid c2">
<div class="card">
@@ -247,24 +262,29 @@
<button type="button" data-cmd="bold" title="Bold"><b>B</b></button>
<button type="button" data-cmd="italic" title="Italic"><i>I</i></button>
<button type="button" data-cmd="underline" title="Underline"><u>U</u></button>
<button type="button" data-block="h3" title="Heading">Heading</button>
<button type="button" data-block="p" title="Normal text">Normal</button>
<span class="ed-sep"></span>
<button type="button" data-block="h2" title="Heading">H<sub>2</sub></button>
<button type="button" data-block="h3" title="Subheading">H<sub>3</sub></button>
<button type="button" data-block="p" title="Normal text"></button>
<span class="ed-sep"></span>
<button type="button" data-cmd="insertUnorderedList" title="Bullet list">• List</button>
<button type="button" data-cmd="insertOrderedList" title="Numbered list">1. List</button>
<button type="button" id="edLinkBtn" title="Insert link">Link</button>
<button type="button" data-cmd="removeFormat" title="Clear formatting">Clear</button>
<button type="button" id="edLinkBtn" title="Insert link">🔗 Link</button>
<span class="ed-sep"></span>
<button type="button" id="edImgBtn" title="Insert image">🖼 Image</button>
<button type="button" id="edVidBtn" title="Insert video">🎬 Video</button>
<span class="ed-sep"></span>
<button type="button" data-cmd="undo" title="Undo">↺</button>
<button type="button" data-cmd="redo" title="Redo">↻</button>
<button type="button" id="edRawBtn" title="Toggle raw text" style="margin-left:auto">Raw text</button>
</div>
<div id="cSoloEd" class="ed-body" contenteditable="true"
data-ph="Write it like an email worth reading. Bold the promise, list the proof, link the receipts."></div>
<p style="margin:10px 0 0"><input id="cCtaLabel" maxlength="30" style="width:100%"
data-ph="Write it like an email worth reading. Bold the promise, list the proof, drop in an image or video, link the receipts."></div>
<textarea id="cSoloRaw" class="ed-body" hidden style="font-family:var(--mono);font-size:13px"></textarea>
<input type="file" id="cSoloFile" accept="image/png,image/jpeg,image/webp,image/gif,video/mp4,video/webm" hidden>
<span id="edMediaInfo" class="small muted"></span>
<p style="margin:12px 0 0"><input id="cCtaLabel" maxlength="30" style="width:100%"
placeholder="Call-to-action button label (default: Learn more) — the button opens your target URL"></p>
<p class="ed-media">
<input type="file" id="cSoloFile" accept="image/png,image/jpeg,image/webp,image/gif,video/mp4,video/webm" hidden>
<button type="button" class="btn small sec" id="edAttachBtn">Attach image or video</button>
<span id="edMediaInfo" class="small muted"></span>
<button type="button" class="btn small sec" id="edMediaRemove" hidden>Remove</button>
</p>
<div id="edMediaPrev" hidden style="margin-top:8px"></div>
</div>
<p class="small muted" id="cSoloHint" hidden></p>
<button class="btn" id="createCampBtn">Launch campaign</button>
@@ -350,6 +370,15 @@
<h3>Email swipe</h3>
<p class="muted small" id="promoSwipeWrap"></p>
</div>
<div class="card">
<h3>Your banner wall</h3>
<p class="muted small">A public page showing your line banner and your upline ladder, with your
join link front and center. Every visit puts eyes on your whole line — send traffic here and
the wall does the pitching.</p>
<p class="mono small" id="wallLine" style="overflow-wrap:anywhere">Set a username in Profile to claim your wall.</p>
<p><button class="btn small sec" id="wallCopy" type="button" hidden>Copy wall link</button>
<a class="btn small sec" id="wallOpen" target="_blank" rel="noopener" hidden>Open your wall</a></p>
</div>
<div class="card">
<h3>Banners</h3>
<p class="muted small">Branded InstantAdPay banner sets are in production. They will land here
@@ -366,6 +395,20 @@
<button class="btn" id="pfSaveBtn">Save username</button>
<p class="muted small" id="pfCurrent" style="margin-top:10px"></p>
</div>
<div class="card">
<h3>Your line banner</h3>
<p class="muted small">Set a destination link (and a banner image for your wall), and every new
member joining your line meets it on their welcome tour: position 1 for your directs, position 2
for their people, position 3 below that — the same three levels the contract pays you on.</p>
<p><input id="lbTarget" placeholder="Destination URL (https://… — must allow framing)" style="width:100%"></p>
<p><input id="lbBanner" placeholder="Banner image URL (optional — or upload below)" style="width:100%"></p>
<p><input type="file" id="lbFile" accept="image/png,image/jpeg,image/webp,image/gif" hidden>
<button class="btn small sec" id="lbUploadBtn" type="button">Upload banner image</button>
<span class="small muted" id="lbUpInfo"></span></p>
<div id="lbPreview" hidden style="margin:8px 0"></div>
<p><button class="btn" id="lbSaveBtn">Save line banner</button></p>
<p class="muted small" id="lbCurrent"></p>
</div>
<div class="card">
<h3>Account details</h3>
<p class="muted small" id="pfDetails">…</p>
@@ -399,9 +442,9 @@
</div>
</div>
<script src="/assets/common.js?v=20260905r"></script>
<script src="/assets/wallet.js?v=20260905r"></script>
<script src="/assets/my.js?v=20260905r"></script>
<script src="/assets/chat.js?v=20260905r"></script>
<script src="/assets/common.js?v=20260905u"></script>
<script src="/assets/wallet.js?v=20260905u"></script>
<script src="/assets/my.js?v=20260905u"></script>
<script src="/assets/chat.js?v=20260905u"></script>
</body>
</html>