PageSourceSearch

https://www.dwellprotocol.com/portal

html dwellprotocol.com collected 2026-10-02 01:27:48 UTC 36,870 bytes, 727 lines download raw bytes

1<!doctype html>
2<html lang="en">
3<head>
4  <meta charset="utf-8" />
5  <meta name="viewport" content="width=device-width, initial-scale=1" />
6  <!-- Decide the first paint synchronously, before the body renders: a returning
7       user (session token in localStorage) gets the loading splash, never a flash
8       of the login form while we confirm the session. portal.js clears this class
9       once it takes over. Keep the keys in sync with SESSION_KEY / DEV_KEY in
10       portal.js — dev mode (?dev=1, sticky) also skips straight past login. -->
11  
11<script>
12    try {
13      if (
14        localStorage.getItem("dwell_session") ||
15        localStorage.getItem("dwell_dev") === "1" ||
16        /[?&]dev=1(&|$)/.test(location.search)
17      ) {
18        document.documentElement.classList.add("auth-pending");
19      }
20    } catch (e) {}
21  </script>
21
22  <!-- Production API for login, earnings, and activity. In dev mode (?dev=1)
23       portal.js never calls it — every view renders from seeded mock data. -->
24  <meta name="dwell-api" content="https://wpjfhezklpczxzocgxsb.supabase.co/functions/v1/dwell-api" />
25  <title>DWELL — Portal</title>
26  <meta name="description" content="Sign in to see your dwells and recent activity." />
27
28  <!-- Link previews (OpenGraph + Twitter). This is the page a member's referral
29       link (portal?ref=…) points at, and that's how it gets shared — so the
30       preview is the invite card (og-referral.png from tools/gen-og.mjs). It
31       promises only what the invited friend actually gets: they earn USDC
32       for watching ads while their AI thinks (the referrer's 10% share is the
33       referrer's business, not the pitch; dwells never convert to $DWELL, so
34       the card never mentions the token). Crawlers ignore the ?ref query and
35       don't run JS, so the framing lives here in the static head. -->
36  <link rel="canonical" href="https://www.dwellprotocol.com/portal" />
37  <meta name="theme-color" content="#ff0000" />
38  <meta property="og:type" content="website" />
39  <meta property="og:site_name" content="DWELL" />
40  <meta property="og:url" content="https://www.dwellprotocol.com/portal" />
41  <meta property="og:title" content="Earn USDC while you use AI" />
42  <meta property="og:description" content="A friend invited you to DWELL. One sponsored line shows while ChatGPT, Claude, or Gemini thinks — you earn USDC for watching it." />
43  <meta property="og:image" content="https://www.dwellprotocol.com/og-referral.png?v=20260710" />
44  <meta property="og:image:alt" content="A friend invited you — earn USDC while you use AI." />
45  <meta name="twitter:card" content="summary_large_image" />
46
47  <link rel="preconnect" href="https://fonts.googleapis.com" />
48  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
49  <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800;900&family=JetBrains+Mono:wght@400;500;700&display=swap" rel="stylesheet" />
50  <link rel="stylesheet" href="theme.css" />
51  <link rel="stylesheet" href="portal.css" />
52  <link rel="icon" href="assets/favicon.svg" type="image/svg+xml" />
53</head>
54<body class="portal-body">
55
56  <!-- ══════════════════════════════════════════════════
57       LOADING SPLASH (shown to returning users while we
58       confirm their session — prevents a flash of login)
59  ══════════════════════════════════════════════════ -->
60  <div id="portal-loading" aria-hidden="true" hidden>
61    <div class="portal-spinner"></div>
62  </div>
63
64  <!-- ══════════════════════════════════════════════════
65       LOGIN PAGE (shown when signed out)
66  ══════════════════════════════════════════════════ -->
67  <div class="portal-split" id="login-page">
68
69    <!-- LEFT — hero / brand -->
70    <div class="portal-left">
71      <header class="portal-nav">
72        <a class="brand" href="index.html">
73          <span class="logo"><img src="assets/logo.svg" alt="" /></span>
74          <span class="brand-name">Dwell Protocol</span>
75        </a>
76        <nav class="portal-nav-links">
77          <a href="index.html">Home</a>
78        </nav>
79      </header>
80
81      <div class="portal-hero">
82        <h1 class="portal-h1">Sign in to see your dwells.</h1>
83      </div>
84    </div>
85
86    <!-- RIGHT — auth card -->
87    <div class="portal-right">
88      <div class="auth-card" id="auth-card">
89
90        <p class="auth-referral-note" id="referral-note" hidden></p>
91
92        <!-- Step 1: Google + email magic link -->
93        <div id="auth-step-providers">
94          <a class="auth-btn-provider" id="google-btn" href="#">
95            <svg class="provider-icon" viewBox="0 0 48 48" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
96              <path fill="currentColor" d="M24 9.5c3.54 0 6.71 1.22 9.21 3.6l6.85-6.85C35.9 2.38 30.47 0 24 0 14.62 0 6.51 5.38 2.56 13.22l7.98 6.19C12.43 13.72 17.74 9.5 24 9.5z"/>
97              <path fill="currentColor" d="M46.98 24.55c0-1.57-.15-3.09-.38-4.55H24v9.02h12.94c-.58 2.96-2.26 5.48-4.78 7.18l7.73 6c4.51-4.18 7.09-10.36 7.09-17.65z"/>
98              <path fill="currentColor" d="M10.53 28.59c-.48-1.45-.76-2.99-.76-4.59s.27-3.14.76-4.59l-7.98-6.19C.92 16.46 0 20.12 0 24c0 3.88.92 7.54 2.56 10.78l7.97-6.19z"/>
99              <path fill="currentColor" d="M24 48c6.48 0 11.93-2.13 15.89-5.81l-7.73-6c-2.18 1.48-4.97 2.31-8.16 2.31-6.26 0-11.57-4.22-13.47-9.91l-7.98 6.19C6.51 42.62 14.62 48 24 48z"/>
100            </svg>
101            Continue with Google
102          </a>
103
104          <a class="auth-btn-provider" id="twitter-btn" href="#">
105            <svg class="provider-icon" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
106              <path fill="currentColor" d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z"/>
107            </svg>
108            Continue with X
109          </a>
110
111          <div class="auth-divider"><span>Sign in with email</span></div>
112          <input
113            class="auth-input"
114            type="email"
115            id="login-email"
116            placeholder="[email protected]"
117            autocomplete="email"
118          />
119          <input
120            class="auth-input"
121            type="text"
122            id="referral-code"
123            placeholder="Referral code (optional)"
124            autocomplete="off"
125            maxlength="16"
126          />
127          <button class="auth-btn-primary" id="login-btn" type="button">
128            Email me a sign-in link
129          </button>
130          <button class="auth-btn-secondary" id="resend-btn" type="button" hidden>
131            Resend sign-in email
132          </button>
133        </div>
134
135        <!-- Step 2: sent confirmation -->
136        <div id="auth-step-sent" hidden>
137          <div class="auth-sent-icon">✉</div>
138          <p class="auth-sent-msg" id="auth-sent-msg"></p>
139          <button class="auth-btn-secondary" id="resend-btn-2" type="button">
140            Resend sign-in email
141          </button>
142          <button class="auth-link-btn" id="back-btn" type="button">← back</button>
143        </div>
144
145        <p class="auth-error" id="auth-error" hidden></p>
146      </div>
147    </div>
148
149  </div><!-- /portal-split -->
150
151
152  <!-- ══════════════════════════════════════════════════
153       ONBOARDING SURVEY (first login — two questions, each
154       its own screen, shown before the refer-a-friend step).
155       Both questions are multi-select.
156  ══════════════════════════════════════════════════ -->
157  <div class="portal-onboard" id="survey-page" hidden>
158
159    <header class="nav onboard-nav">
160      <a class="brand" href="index.html">
161        <span class="logo"><img src="assets/logo.svg" alt="" /></span>
162        <span class="brand-name">Dwell Protocol</span>
163        <span class="brand-sub">— Portal</span>
164      </a>
165      <div class="dash-account">
166        <a href="index.html" class="dash-account-link dash-home">Home</a>
167        <button class="dash-account-link dash-signout js-signout" type="button">Sign out</button>
168      </div>
169    </header>
170
171    <div class="portal-split">
172
173    <!-- LEFT — hero / brand -->
174    <div class="portal-left">
175      <div class="portal-hero">
176        <h1 class="portal-h1">Tell us how you use AI.</h1>
177      </div>
178    </div>
179
180    <!-- RIGHT — survey card (two steps, one visible at a time) -->
181    <div class="portal-right">
182      <div class="auth-card">
183
184        <!-- Step 1: which models -->
185        <div id="survey-step-models">
186          <span class="onboard-step">Step 1 of 2</span>
187          <h2 class="onboard-title">What models do you use?</h2>
188          <p class="auth-sent-msg">Select all that apply.</p>
189          <div class="survey-options" id="survey-models" role="group" aria-label="AI models you use">
190            <button class="survey-opt" type="button" data-value="claude">Claude</button>
191            <button class="survey-opt" type="button" data-value="chatgpt">ChatGPT</button>
192            <button class="survey-opt" type="button" data-value="gemini">Gemini</button>
193            <button class="survey-opt" type="button" data-value="other">Other</button>
194          </div>
195          <button class="auth-btn-primary" id="survey-models-next" type="button">Continue</button>
196          <p class="auth-error" id="survey-models-error" hidden></p>
197        </div>
198
199        <!-- Step 2: where -->
200        <div id="survey-step-surfaces" hidden>
201          <span class="onboard-step">Step 2 of 2</span>
202          <h2 class="onboard-title">Where do you use them?</h2>
203          <p class="auth-sent-msg">Select all that apply.</p>
204          <div class="survey-options" id="survey-surfaces" role="group" aria-label="Where you use AI">
205            <button class="survey-opt" type="button" data-value="browser_chrome">Browser — Chrome</button>
206            <button class="survey-opt" type="button" data-value="browser_other">Browser — other</button>
207            <button class="survey-opt" type="button" data-value="desktop_app">Desktop app</button>
208            <button class="survey-opt" type="button" data-value="cursor">Cursor extension</button>
209            <button class="survey-opt" type="button" data-value="terminal">Terminal</button>
210            <button class="survey-opt" type="button" data-value="other">Other</button>
211          </div>
212          <input
213            class="auth-input"
214            type="text"
215            id="survey-surface-other"
216            placeholder="Tell us where (optional)"
217            autocomplete="off"
218            maxlength="200"
219            hidden
220          />
221          <button class="auth-btn-primary" id="survey-surfaces-next" type="button">Continue</button>
222          <button class="auth-link-btn" id="survey-back" type="button">← back</button>
223          <p class="auth-error" id="survey-surfaces-error" hidden></p>
224        </div>
225
226      </div>
227    </div>
228
229    </div><!-- /.portal-split -->
230  </div><!-- /survey-page -->
231
232
233  <!-- ══════════════════════════════════════════════════
234       ONBOARDING PAGE (first login — post the prebuilt DWELL
235       note to your X timeline before reaching the dashboard).
236       The "continue" button stays hidden until the user has
237       opened the X composer; continuing asks for an explicit
238       confirmation that the post is live.
239  ══════════════════════════════════════════════════ -->
240  <div class="portal-onboard" id="onboarding-page" hidden>
241
242    <header class="nav onboard-nav">
243      <a class="brand" href="index.html">
244        <span class="logo"><img src="assets/logo.svg" alt="" /></span>
245        <span class="brand-name">Dwell Protocol</span>
246        <span class="brand-sub">— Portal</span>
247      </a>
248      <div class="dash-account">
249        <a href="index.html" class="dash-account-link dash-home">Home</a>
250        <button class="dash-account-link dash-signout js-signout" type="button">Sign out</button>
251      </div>
252    </header>
253
254    <div class="portal-split">
255
256    <!-- LEFT — hero / brand -->
257    <div class="portal-left">
258      <div class="portal-hero">
259        <h1 class="portal-h1">Post to start earning USDC.</h1>
260      </div>
261    </div>
262
263    <!-- RIGHT — post-to-X card -->
264    <div class="portal-right">
265      <div class="auth-card">
266
267        <!-- Step 1: compose + post -->
268        <div id="onboard-step-post">
269          <div class="auth-sent-icon onboard-x-icon">
270            <svg viewBox="0 0 24 24" aria-hidden="true">
270<path fill="currentColor" d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z"/></svg>
271          </div>
272          <h2 class="onboard-title">Post on X to earn USDC</h2>
273          <p class="auth-sent-msg">Start earning 10% of all your friends' USDC earnings.</p>
274
275          <blockquote class="onboard-tweet-preview" id="onboard-tweet-preview"></blockquote>
276
277          <a class="auth-btn-primary onboard-post-btn" id="onboard-post-btn" href="#" target="_blank" rel="noopener noreferrer">
278            <svg class="onboard-x-glyph" viewBox="0 0 24 24" aria-hidden="true"><path fill="currentColor" d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z"/></svg>
279            Post to X
280          </a>
281
282          <!-- Hidden until the composer has been opened -->
283          <button class="auth-btn-secondary" id="onboard-next-btn" type="button" hidden>
284            I've posted — continue
285          </button>
286        </div>
287
288        <!-- Step 2: confirm the post is live -->
289        <div id="onboard-step-confirm" hidden>
290          <div class="auth-sent-icon">✅</div>
291          <h2 class="onboard-title">Is your post live?</h2>
292          <p class="auth-sent-msg">
293            Confirm the post is on your X timeline. Accounts without an onboarding
294            post in their timeline may have their payouts delayed or withheld.
295          </p>
296          <button class="auth-btn-primary" id="onboard-confirm-yes" type="button">
297            Yes, it's on my timeline
298          </button>
299        </div>
300
301        <p class="auth-error" id="onboard-error" hidden></p>
302      </div>
303    </div>
304
305    </div><!-- /.portal-split -->
306  </div><!-- /onboarding-page -->
307
308
309  <!-- ══════════════════════════════════════════════════
310       AUTHENTICATED PORTAL (shown when signed in)
311  ══════════════════════════════════════════════════ -->
312  <div id="portal-page" hidden>
313
314    <header class="nav dash-nav">
315      <a class="brand" href="index.html">
316        <span class="logo"><img src="assets/logo.svg" alt="" /></span>
317        <span class="brand-name">Dwell Protocol</span>
318      </a>
319      <div class="dash-account">
320        <span class="dash-account-who" id="nav-signed-in" hidden></span>
321        <a href="index.html" class="dash-account-link dash-home">Home</a>
322        <button class="dash-account-link dash-signout js-signout" id="signout" type="button">Sign out</button>
323      </div>
324    </header>
325
326    <!-- Ad-notice banner — hidden by default. An admin toggle (Settings →
327         "Ad notice") flips the `adNoticeVisible` flag in /v1/config; portal.js
328         checkInventory() reads it and shows this banner when it's on. -->
329    <div class="dash-notice" id="inventory-notice" hidden>
330      <span class="dash-notice-ico" aria-hidden="true">⏳</span>
331      <span>Not serving ads until after launch.</span>
332    </div>
333
334    <!-- Primary section nav — one active view at a time. Same order as the
335         legacy dashboard; Cash out sits in the Redeem slot. -->
336    <nav class="dash-tabs" id="dash-tabs" role="tablist" aria-label="Portal sections">
337      <button class="dash-tab active" data-section="earnings" type="button" role="tab" aria-selected="true">
338        <span class="dash-tab-ico" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 17l6-6 4 4 7-7"/><path d="M17 8h4v4"/></svg></span>
339        <span class="dash-tab-label">Earnings</span>
340      </button>
341      <button class="dash-tab" data-section="referrals" type="button" role="tab" aria-selected="false">
342        <span class="dash-tab-ico" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="9" cy="8" r="3.2"/>
342<path d="M3.5 19a5.5 5.5 0 0 1 11 0"/><path d="M16 5.5a3 3 0 0 1 0 5.5"/><path d="M17.5 19a5 5 0 0 0-3-4.6"/></svg></span>
343        <span class="dash-tab-label">Referrals</span>
344      </button>
345      <button class="dash-tab" data-section="activity" type="button" role="tab" aria-selected="false">
346        <span class="dash-tab-ico" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M8 6h12"/><path d="M8 12h12"/><path d="M8 18h12"/><circle cx="3.5" cy="6" r="1.2"/><circle cx="3.5" cy="12" r="1.2"/><circle cx="3.5" cy="18" r="1.2"/></svg></span>
347        <span class="dash-tab-label">Activity</span>
348      </button>
349      <button class="dash-tab" data-section="cashout" type="button" role="tab" aria-selected="false">
350        <span class="dash-tab-ico" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3.5" y="6" width="17" height="12" rx="2"/><path d="M3.5 10h17"/><path d="M7 14.5h4"/></svg></span>
351        <span class="dash-tab-label">Redeem</span>
352      </button>
353      <button class="dash-tab" data-section="install" type="button" role="tab" aria-selected="false">
354        <span class="dash-tab-ico" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3v12"/><path d="m7.5 10.5 4.5 4.5 4.5-4.5"/><path d="M4.5 20.5h15"/></svg></span>
355        <span class="dash-tab-label">Install</span>
356      </button>
357    </nav>
358
359    <main class="portal-main">
360      <!-- ── EARNINGS ── -->
361      <section class="portal-card" id="earnings-view">
362        <div class="balance-row">
363          <div>
364            <span class="eyebrow">Dwells balance</span>
365            <div class="balance" id="balance">0 <span class="balance-unit">dwells</span></div>
366            <div class="balance-sub" id="balance-email"></div>
367          </div>
368        </div>
369
370        <h2 class="earn-title">How much you've earned with DWELL</h2>
371        <p class="portal-copy">
372          Each sponsored line you watch while your AI assistant thinks credits
373          you the viewer's 60% share of that campaign's pool in dwells.
374        </p>
375
376        <div class="earn-stats">
377          <div class="earn-stat">
378            <span class="es-label">Today</span>
379            <span class="es-num" id="earn-today">0</span>
380            <span class="es-sub">dwells credited today</span>
381          </div>
382          <div class="earn-stat">
383            <span class="es-label">This month</span>
384            <span class="es-num" id="earn-month">0</span>
385            <span class="es-sub">dwells month-to-date</span>
386          </div>
387          <div class="earn-stat">
388            <span class="es-label">Lifetime</span>
389            <span class="es-num" id="earn-lifetime">0</span>
390            <span class="es-sub">all-time dwells</span>
391          </div>
392        </div>
393
394        <div class="earn-chart-card">
395          <div class="ecc-head">
396            <div>
397              <h3 class="ecc-title">Earnings activity</h3>
398              <p class="ecc-sub" id="earn-chart-sub">Cumulative points over the selected window.</p>
399            </div>
400            <div class="ecc-controls">
401              <div class="earn-mode" id="earn-mode" role="group" aria-label="Chart mode">
402                <button class="em-btn active" data-mode="cumulative" type="button">Cumulative</button>
403                <button class="em-btn" data-mode="period" type="button">Per period</button>
404              </div>
405              <div class="earn-window" id="earn-window" role="group" aria-label="Chart window">
406                <button class="ew-btn active" data-window="24h" type="button">24h</button>
407                <button class="ew-btn" data-window="7d" type="button">7d</button>
408                <button class="ew-btn" data-window="30d" type="button">30d</button>
409              </div>
410            </div>
411          </div>
412          <div class="earn-chart" id="earn-chart"><!-- SVG drawn by portal.js --></div>
413          <p class="earn-chart-foot" id="earn-chart-foot">0 dwells across 0 events</p>
414        </div>
415
416        <div class="earn-surfaces-card">
417          <h3 class="ess-title">Where you're earning</h3>
418          <p class="ess-sub">Each surface lights up once it sends its first dwells credit.</p>
419          <div class="earn-surfaces">
420            <div class="earn-surface">
421              <span class="es-surface-name">Chrome</span>
422              <span class="logo is-inactive" data-active="chrome" aria-hidden="true"><img src="assets/logo.svg" alt="" /></span>
423              <span class="ia-label" data-active-label="chrome">Inactive</span>
424            </div>
425            <div class="earn-surface">
426              <span class="es-surface-name">Terminal</span>
427              <span class="logo is-inactive" data-active="claude_code" aria-hidden="true"><img src="assets/logo.svg" alt="" /></span>
428              <span class="ia-label" data-active-label="claude_code">Inactive</span>
429            </div>
430            <div class="earn-surface">
431              <span class="es-surface-name">Desktop</span>
432              <span class="logo is-inactive" data-active="desktop" aria-hidden="true"><img src="assets/logo.svg" alt="" /></span>
433              <span class="ia-label" data-active-label="desktop">Inactive</span>
434            </div>
435          </div>
436        </div>
437      </section>
438
439      <!-- ── ACTIVITY LEDGER ── -->
440      <section class="portal-card" id="activity-view">
441        <div class="act-head">
442          <div>
443            <span class="eyebrow">Activity ledger</span>
444            <h2 class="earn-title">Your dwells ledger</h2>
445            <p class="portal-copy">
446              Ledger entries from this account, retrieved on demand. Search and
447              filter happen locally on the retrieved rows.
448            </p>
449          </div>
450          <span class="act-status" id="act-status">Loading…</span>
451        </div>
452
453        <div class="act-controls">
454          <input type="text" id="act-search" class="act-search"
455                 placeholder="Search sponsor, entry id, entry type…" disabled />
456          <select id="act-filter" class="act-filter" disabled>
457            <option value="all">All entries</option>
458            <option value="points_credit">Sponsored lines</option>
459            <option value="referral_points_credit">Referral share</option>
460          </select>
461          <span class="act-count" id="act-count">0 of 0 rows</span>
462        </div>
463
464        <div class="act-body" id="act-body">
465          <div class="act-loading">
466            <div class="portal-spinner"></div>
467            <p>Loading your activity…</p>
468          </div>
469        </div>
470        <div class="act-pager" id="act-pager" hidden></div>
471      </section>
472
473      <!-- ── REDEEM ── -->
474      <section class="portal-card" id="cashout-view" hidden>
475        <div class="balance-row">
476          <div>
477            <span class="eyebrow">Your dwells</span>
478            <div class="balance" id="co-points">0 <span class="balance-unit">dwells</span></div>
479          </div>
480        </div>
481
482        <h2>Redeem your dwells</h2>
483
484        <!-- (a) Claude credits — live. Grid rendered by portal.js from
485             GET /v1/giftcards; prices shown in dwells at the 10% redemption
486             boost (dwells buy 110% of face value), mirroring exactly what
487             POST /v1/web/redemptions charges. -->
488        <div class="redeem-block" id="gift-block">
489          <div class="rb-head">
490            <h3 class="rb-title">Claude credits</h3>
491            <span class="rb-badge" id="gift-fee-badge"></span>
492          </div>
493          <p class="portal-copy">
494            Pick a plan and term. The credit is emailed to your account
495            address within <strong>48 hours</strong>, and the dwells are
496            deducted when you redeem.
497          </p>
498          <div class="gift-menu" id="gift-menu"><!-- rendered by portal.js --></div>
499          <div class="redeem-foot">
500            <div class="redeem-delivery">
501              <span class="rd-text">
502                <span class="rd-label">Credit delivered to</span>
503                <span class="rd-email" id="recipient-email"></span>
504              </span>
505            </div>
506            <div class="redeem-summary" id="gift-summary">Select a gift above to continue.</div>
507            <button class="btn-accent" id="redeem-btn" type="button" disabled>Redeem</button>
508          </div>
509          <p class="redeem-result" id="redeem-result" hidden></p>
510        </div>
511
512        <!-- (b) Cash payout via Stripe — disabled pre-launch. Static "coming
513             soon" state; portal.js loadPayoutStatus() early-returns so it
514             never renders the live Stripe flow into #payout-body. -->
515        <div class="redeem-block is-disabled" id="payout-block">
516          <div class="rb-head">
517            <h3 class="rb-title">Cash out to your bank</h3>
518            <span class="rb-badge" id="payout-fee-badge">Coming soon</span>
519          </div>
520          <div id="payout-body">
521            <div class="payout-state">
522              <p>Cashing out to your bank arrives after token launch.</p>
523              <button class="btn-accent" type="button" disabled>Coming soon</button>
524            </div>
525          </div>
526          <div class="payout-history" id="payout-history" hidden></div>
527          <p class="redeem-result" id="payout-result" hidden></p>
528        </div>
529
530        <!-- (c) USDC to your wallet — preview until the rail opens; no live
531             calls. Mirrors the tokenomics page: face value less the 10%
532             protocol fee, $100 minimum. Dwells never convert to $DWELL. -->
533        <div class="launch-preview">
534          <div class="lp-head">
535            <h3 class="lp-title">USDC to your wallet</h3>
536            <span class="lp-badge">Coming soon</span>
537          </div>
538          <ol class="lp-steps">
539            <li><strong>Link a Solana wallet.</strong> Redemptions are sent
540              onchain, on Solana, to an external wallet you link.</li>
541            <li><strong>Redeem for USDC.</strong> Face value less the
542              <strong>10% protocol fee</strong>, $100 minimum. Transfers are
543              executed by licensed partners as counterparty of record.</li>
544          </ol>
545        </div>
546
547        <!-- (d) Factual note on transferability. -->
548        <p class="cashout-note">
549          Dwells themselves are non-transferable; redeeming spends them and is
550          recorded on the ledger like every other entry.
551        </p>
552      </section>
553
554      <!-- ── REFERRALS ── -->
555      <section class="portal-card" id="referrals-view" hidden>
556        <!-- Every signed-in earner is auto-enrolled at the protocol's 10%
557             referrer share (self-serve, no application). The form below is the
558             partner upgrade — apply for uncapped referrals + a custom link. -->
559        <div class="affiliate-block" id="affiliate-block" hidden>
560          <h2>Earn from referrals</h2>
561          <p class="portal-copy">
562            You earn <strong id="aff-pct">10%</strong> of every friend's earnings,
563            forever — credited as dwells, for up to
564            <span id="aff-cap">1,000 friends</span>. That 10% is the referrer share
565            carved from each campaign's pool (viewer 60%, referrer 10%,
566            protocol 30% — the referrer share joins the treasury when there's
567            no referrer) — never deducted from your friends' 60%.
568          </p>
569
570          <!-- Auto-enrolled: your code + shareable link + stats. -->
571          <div class="aff-approved" id="aff-approved" hidden>
572            <h3 class="ref-invite-h">Your referral code</h3>
573            <div class="ref-link-row">
574              <input type="text" id="aff-link" readonly aria-label="Your referral link" />
575              <button class="btn-accent" id="aff-copy" type="button">Copy link</button>
576            </div>
577            <div class="ref-stats">
578              <div class="ref-stat">
579                <span class="rs-num" id="aff-users">0</span>
580                <span class="rs-label">friends joined</span>
581              </div>
582              <div class="ref-stat">
583                <span class="rs-num" id="aff-earned">0</span>
584                <span class="rs-label">dwells earned</span>
585              </div>
586              <div class="ref-stat">
587                <span class="rs-num" id="aff-remaining">1,000</span>
588                <span class="rs-label">friends remaining</span>
589              </div>
590            </div>
591
592            <h3 class="ref-invite-h">Your friends</h3>
593            <div class="fr-table" id="ref-friends">
594              <p class="ref-empty">No friends joined yet — share your link above.</p>
595            </div>
596          </div>
597
598          <!-- Retroactively attach someone else's referral code. -->
599          <div class="aff-have-code" id="aff-have-code" hidden>
600            <h3 class="ref-invite-h">Have a referral code?</h3>
601            <form class="ref-invite-row" id="aff-code-form">
602              <input
603                type="text"
604                id="aff-code-input"
605                class="auth-input"
606                placeholder="REFERRAL CODE"
607                autocomplete="off"
608                aria-label="Referral code"
609              />
610              <button class="btn-accent" id="aff-code-btn" type="submit">Apply code</button>
611            </form>
612            <p class="ref-invite-msg" id="aff-code-msg" hidden></p>
613          </div>
614
615          <!-- Partner upgrade — apply for uncapped referrals + a custom link.
616               The referrer share itself is fixed by the protocol split at 10%. -->
617          <div class="aff-upgrade aff-upgrade-box" id="aff-upgrade" hidden>
618            <form class="aff-apply" id="aff-apply-form">
619              <h3 class="ref-invite-h">Want to join the partner program?</h3>
620              <p class="aff-hint">Apply for better referrals and more earnings.</p>
621              <div class="aff-row">
622                <input type="text" id="aff-ig" class="auth-input" placeholder="Instagram @handle" autocomplete="off" />
623                <input type="number" min="0" id="aff-ig-f" class="auth-input aff-followers" placeholder="Followers" autocomplete="off" />
624              </div>
625              <div class="aff-row">
626                <input type="text" id="aff-li" class="auth-input" placeholder="LinkedIn handle" autocomplete="off" />
627                <input type="number" min="0" id="aff-li-f" class="auth-input aff-followers" placeholder="Followers" autocomplete="off" />
628              </div>
629              <div class="aff-row">
630                <input type="text" id="aff-tw" class="auth-input" placeholder="Twitter / X @handle" autocomplete="off" />
631                <input type="number" min="0" id="aff-tw-f" class="auth-input aff-followers" placeholder="Followers" autocomplete="off" />
632              </div>
633              <button class="btn-accent" id="aff-apply-btn" type="submit">Apply for the partner program</button>
634              <p class="ref-invite-msg" id="aff-apply-msg" hidden></p>
635            </form>
636          </div>
637
638          <!-- Upgrade requested (socials submitted, awaiting review). -->
639          <div class="aff-status" id="aff-upgrade-requested" hidden>
640            <p class="portal-copy">✅ Upgrade requested — we'll review your socials and email you about your partner plan.</p>
641          </div>
642
643          <!-- Upgrade granted (uncapped partner plan). -->
644          <div class="aff-status" id="aff-upgrade-granted" hidden>
645            <p class="portal-copy">🎉 You're on a partner plan — <strong id="aff-custom-pct">10%</strong> referrer share, uncapped friends.</p>
646          </div>
647        </div>
648      </section>
649
650      <!-- ── INSTALL ── -->
651      <section class="portal-card" id="install-view" hidden>
652        <!-- "Active" status — a greyed brand-mark chip that fills into the colored logo
653             the moment this account earns its first dwells from any service.
654             Per-service activation comes from GET /v1/web/sources (see portal.js). -->
655        <div class="install-hero">
656          <span class="logo install-hero-logo is-inactive" id="install-hero-logo" aria-hidden="true"><img src="assets/logo.svg" alt="" /></span>
657          <div class="install-hero-text">
658            <span class="eyebrow">Earning status</span>
659            <h2 class="earn-title" id="install-hero-title">Not earning yet</h2>
660          </div>
661        </div>
662
663        <h3 class="install-h">Set up DWELL</h3>
664        <p class="portal-copy">
665          Earning is in dwells, wherever you use your assistant. Each logo
666          turns from grey to color once you earn your first dwells from that
667          service.
668        </p>
669
670        <div class="install-list" id="install-list">
671          <!-- 01 · Chrome extension (top priority) -->
672          <div class="install-row" data-product="chrome">
673            <div class="survey-opt install-check" data-product="chrome" aria-checked="false">
674              <span class="ic-text">
675                <span class="ic-name">Chrome extension</span>
676                <span class="ic-sub">Most popular · works in ChatGPT, Claude &amp; Gemini</span>
677              </span>
678              <a class="ic-link" href="index.html">Install guide →</a>
679            </div>
680            <div class="install-active">
681              <span class="logo is-inactive" data-active="chrome" aria-hidden="true"><img src="assets/logo.svg" alt="" /></span>
682              <span class="ia-label" data-active-label="chrome">Inactive</span>
683            </div>
684          </div>
685
686          <!-- 02 · Terminal -->
687          <div class="install-row" data-product="claude_code">
688            <div class="survey-opt install-check" data-product="claude_code" aria-checked="false">
689              <span class="ic-text">
690                <span class="ic-name">Terminal</span>
691                <span class="ic-sub">A reversible <code>claude</code> alias for your terminal</span>
692              </span>
693              <a class="ic-link" href="index.html">Install guide →</a>
694            </div>
695            <div class="install-active">
696              <span class="logo is-inactive" data-active="claude_code" aria-hidden="true"><img src="assets/logo.svg" alt="" /></span>
697              <span class="ia-label" data-active-label="claude_code">Inactive</span>
698            </div>
699          </div>
700
701          <!-- 03 · Desktop -->
702          <div class="install-row" data-product="desktop">
703            <div class="survey-opt install-check" data-product="desktop" aria-checked="false">
704              <span class="ic-text">
705                <span class="ic-name">Desktop app</span>
706                <span class="ic-sub">macOS overlay for Claude &amp; ChatGPT Desktop · macOS 13+</span>
707              </span>
708              <a class="ic-link" href="index.html">Download →</a>
709            </div>
710            <div class="install-active">
711              <span class="logo is-inactive" data-active="desktop" aria-hidden="true"><img src="assets/logo.svg" alt="" /></span>
712              <span class="ia-label" data-active-label="desktop">Inactive</span>
713            </div>
714          </div>
715        </div>
716      </section>
717    </main>
718
719    <footer class="footer">
720      <p>© 2025 Dwell Protocol · <a href="/privacy">Privacy</a> · <a href="/terms">Terms</a></p>
721    </footer>
722
723  </div><!-- /portal-page -->
724
725  
725<script src="portal.js"></script>
725
726</body>
727</html>

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.