Files
rm-circle-team-router/public/suite-traffic.html
T
martbost 26f2c91684 Banners must stop when they have delivered what was bought
Marty: "if it's just gonna keep running, why would anyone use impressions to
place the ad at all?" He is right, and my previous answer — calling the
over-delivery a bonus — papered over a real flaw.

Banner placements on this network have no cap. Left alone, 2,500 impressions
buys an ad that runs until expiry, which makes the allowance decorative and
the whole level ladder (2,500 at Scintilla to 150,000 at Corona) worth
nothing. Nobody would ever spend the larger allowance for an identical
outcome.

Two changes so the impressions are genuinely the thing being spent:

sweepCompleted() deactivates any campaign that has served its purchased
amount. Runs 90s after boot and every 15 minutes, batches its stat reads, and
only touches campaigns that are live, un-stopped and provably at or past what
was bought. Nothing is refunded — they delivered in full. It re-reads the
ledger after the network calls, since deactivating takes real time and
another member may have launched in that window.

New campaigns get days:30 instead of days:365. The allowance is monthly, so a
campaign outliving the month it was paid from is the same bug by another
route. Belt and braces — whichever ends it first.

Copy corrected too: "still serving as a bonus" became "served in full —
closing out", and the footnote now states plainly that a campaign ends when
it has served what was bought.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-30 05:23:38 -05:00

104 lines
8.2 KiB
HTML

<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><meta name="robots" content="noindex"><meta name="description" content="Traffic Desk — put a team banner on our own ad network, pointed at your invite link. Monthly impressions included with your position."><title>Traffic Desk | The Circle Suite</title><link rel="icon" type="image/png" href="/favicon.png"><link rel="stylesheet" href="/styles.css">
<style>
.tw{max-width:940px;margin:0 auto;padding:24px 20px 70px}
.tw h1{font-size:clamp(26px,4.5vw,36px);margin:6px 0 8px}
.tw .lede{color:var(--muted);line-height:1.6;margin-bottom:18px}
#tfGate{display:none;border:2px solid var(--gold);border-radius:12px;padding:16px 20px;margin-bottom:18px;line-height:1.6}
.tf-bal{display:flex;gap:18px;flex-wrap:wrap;align-items:center;border:2px solid var(--teal);border-radius:14px;padding:14px 18px;margin-bottom:18px}
.tf-bal .big{font-size:30px;font-weight:900;color:var(--gold);font-variant-numeric:tabular-nums;line-height:1}
.tf-bal .lab{font-size:12px;font-weight:800;letter-spacing:1.4px;text-transform:uppercase;color:var(--muted);margin-top:3px}
.tf-bal .note{color:var(--muted);font-size:13px;line-height:1.5;flex:1;min-width:220px}
.tf-card{background:var(--card,#0d2236);border:1px solid var(--line,#24425d);border-radius:14px;padding:18px 20px;margin-bottom:16px}
label.tf-lab{display:block;font-weight:700;font-size:14px;margin:14px 0 6px}
label.tf-lab:first-of-type{margin-top:0}
.tf-chips{display:flex;flex-wrap:wrap;gap:8px}
.tf-chip{border:1px solid var(--line);background:transparent;color:var(--muted);border-radius:999px;
padding:7px 14px;font-size:13.5px;font-weight:700;cursor:pointer}
.tf-chip.on{border-color:var(--teal);background:rgba(78,214,203,.12);color:var(--teal)}
.tf-creatives{display:flex;flex-wrap:wrap;gap:10px;margin-top:4px}
.tf-cre{border:2px solid var(--line);border-radius:10px;padding:6px;cursor:pointer;background:var(--bg,#0b1d2e);line-height:0}
.tf-cre.on{border-color:var(--gold)}
.tf-cre img{max-width:230px;max-height:120px;width:auto;height:auto;display:block}
#tfImp{width:150px;background:var(--bg,#0b1d2e);border:1px solid var(--line);border-radius:10px;color:var(--text);padding:10px 12px;font-size:15px}
.tf-hint{color:var(--muted);font-size:12.5px;margin-top:6px}
.tf-row{display:flex;gap:12px;align-items:center;flex-wrap:wrap;margin-top:16px}
#tfErr{display:none;color:#f0a05a;margin-top:12px;font-size:14px;line-height:1.55}
#tfOk{display:none;border:2px solid var(--teal);border-radius:12px;padding:14px 18px;margin-top:14px;line-height:1.6}
.tf-live{margin-top:22px}
.tf-live table{width:100%;border-collapse:collapse;font-size:14px}
.tf-live th{text-align:left;padding:8px 10px;font-size:11px;letter-spacing:1px;text-transform:uppercase;color:var(--muted);border-bottom:2px solid var(--line)}
.tf-live td{padding:9px 10px;border-bottom:1px solid var(--line);color:var(--muted);font-variant-numeric:tabular-nums}
.tf-live td b{color:var(--text)}
.tf-ads{display:grid;grid-template-columns:repeat(auto-fill,minmax(215px,1fr));gap:10px;margin-top:14px}
.tf-ad{border:2px solid var(--line);border-radius:10px;padding:12px 13px;cursor:pointer;
background:var(--bg,#0b1d2e);transition:border-color .12s}
.tf-ad:hover{border-color:var(--muted)}
.tf-ad.on{border-color:var(--gold);background:rgba(212,175,55,.07)}
.tf-ad .s{font-weight:800;font-size:15px;color:var(--gold);line-height:1.25;margin-bottom:5px;word-break:break-word}
.tf-ad .l{font-size:13px;line-height:1.5;color:var(--text);word-break:break-word}
.tf-ad .cnt{margin-top:8px;font-size:11px;color:var(--muted);font-variant-numeric:tabular-nums}
.tf-note{margin-top:22px;font-size:12.5px;color:var(--muted);line-height:1.6;border-top:1px solid var(--line);padding-top:12px}
.spin{display:inline-block;width:13px;height:13px;border:2px solid rgba(255,255,255,.25);border-top-color:var(--gold);
border-radius:50%;animation:sp .8s linear infinite;vertical-align:-2px;margin-right:7px}
@keyframes sp{to{transform:rotate(360deg)}}
@media (prefers-reduced-motion:reduce){.spin{animation:none}}
</style></head>
<body>
<header class="wrap nav"><a class="brand" href="/suite"><img class="brand-mark" src="/logo.jpg" alt="The RM Circle" width="42" height="42"><span><span id="brandName">RM Circle</span><small>Traffic Desk</small></span></a><div class="nav-actions"><a class="btn btn-secondary hide-mobile" href="/suite">← The Suite</a><a class="btn btn-primary" href="/my">My Dashboard</a></div></header>
<main class="tw">
<div class="eyebrow" style="color:var(--gold)">CIRCLE SUITE · INCLUDED AT EVERY PAID LEVEL</div>
<h1>Traffic <span class="gold">Desk.</span></h1>
<p class="lede">Run a team banner or an AI-written text ad on our own advertising network, pointed at your invite link. Impressions are included with your position and scale as you level up — nothing to buy, nothing to configure.</p>
<div id="tfGate"></div>
<div class="tf-bal" id="tfBal" style="display:none">
<div><div class="big" id="tfRemain">—</div><div class="lab">impressions left this month</div></div>
<div><div class="big" id="tfLimit" style="color:var(--teal)">—</div><div class="lab">your monthly allowance</div></div>
<div class="note" id="tfNote"></div>
</div>
<div class="tf-card" id="tfCard">
<label class="tf-lab">Ad format</label>
<div class="tf-chips" id="tfFormat"></div>
<div id="tfBannerPane">
<label class="tf-lab">Banner size</label>
<div class="tf-chips" id="tfSizes"></div>
<label class="tf-lab">Pick a design</label>
<div class="tf-creatives" id="tfCreatives"></div>
</div>
<div id="tfTextPane" style="display:none">
<label class="tf-lab">What angle should they take?</label>
<div class="tf-chips" id="tfAngles"></div>
<div class="tf-row">
<button id="tfWrite" class="btn btn-secondary">&#9997;&#65039; Write me 5 ads</button>
<span class="tf-hint" id="tfWriteMeter" style="margin:0"></span>
</div>
<div id="tfVariants"></div>
</div>
<label class="tf-lab">Where should it send people?</label>
<div class="tf-chips" id="tfTargets"></div>
<label class="tf-lab" for="tfImp">How many impressions?</label>
<input type="number" id="tfImp" min="100" step="100" value="2500">
<div class="tf-hint">Comes out of this month's allowance. It refills on the 1st.</div>
<div class="tf-row">
<button id="tfGo" class="btn btn-primary">🚦 Launch my banner</button>
</div>
<div id="tfErr"></div>
<div id="tfOk"></div>
</div>
<div class="tf-live" id="tfLiveWrap" style="display:none">
<h2 style="font-size:20px;margin:0 0 8px">Your running banners</h2>
<div class="table-wrap"><table><thead><tr><th>Size</th><th>Sends to</th><th>Bought</th><th>Served</th><th>Left</th><th>Clicks</th><th>Status</th><th></th></tr></thead><tbody id="tfLive"></tbody></table></div>
</div>
<p class="tf-note"><strong style="color:var(--text)">When a campaign ends:</strong> it stops once it has served the impressions you bought, and closes itself out within a few minutes of getting there. You can Stop one early at any time and the impressions it has not used go straight back into your balance. <br><br><strong style="color:var(--text)">What this is, honestly:</strong> display advertising is <strong style="color:var(--text)">awareness volume</strong> — it puts your link in front of people browsing the network. It is not a lead list, and click rates on display inventory are low by nature. The conversations you have with people you know are still what actually builds a team; this runs quietly in the background while you do that. <br><br>All banners use approved team creative, so every ad on the network stays on-brand. Independent team resource · No income is guaranteed · Cryptocurrency involves risk.</p>
</main>
<script src="/suite-traffic.js"></script>
<script src="/tool-video.js" data-video="/tv/suite-traffic-desk.mp4" data-secs="· 74 sec" data-title="Watch the Traffic Desk walkthrough" data-key="traffic" defer></script>
<script src="/chat.js" defer></script>
<script src="/translate.js" defer></script><script src="/tg-app.js" defer></script><script src="/nav-dash.js" defer></script></body></html>