Member pages: house heading treatment; clearer no-wallet message

Two things Marty raised.

1. Member pages did not look like the rest of the site. The byline is now the
   gold uppercase eyebrow used above every other h1, the heading is larger and
   tighter with the last beat in gold (house style is "Team <gold>Grants</gold>"),
   and the subhead steps up from 18px to a fluid 19-22px in a brighter colour.
   The headline is model-written so the gold split cannot be hand-picked —
   goldTail() takes the final two words, or one on a short line. Everything is
   escaped before the span is added; the only markup is ours.

2. The "no wallet found" error listed five wallet names and described a DApp
   tab without saying the thing that matters: you are in the wrong browser,
   and here is the address to type. It now says exactly that, names the page
   address, and warns that Trust on iPhone has no browser at all any more —
   previously those members were reading instructions they could not follow.

Diagnosed from a real case (#34): the company dApp at thermcircle.com supports
WalletConnect, so it connects from any browser; this site is injected-provider
only, so it needs the wallet's own browser. That is the whole difference, and
WalletConnect is the actual fix — this is the stopgap.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
martbost
2026-08-29 05:42:58 -05:00
parent 6838ab3845
commit 90b03c16f9
3 changed files with 27 additions and 7 deletions
+1 -1
View File
@@ -325,7 +325,7 @@
const err=document.getElementById('msgAuthErr'); const err=document.getElementById('msgAuthErr');
try{ try{
const eth=await window.RMCWallet.pick(); const eth=await window.RMCWallet.pick();
if(!eth){err.textContent='No wallet found in this browser. On a phone, open your wallet app (SafePal, Phantom, MetaMask, Trust, Coinbase…), go to its Browser or DApp tab, and type this page\'s address there — your wallet connects automatically.';return;} if(!eth){err.textContent='This browser has no wallet in it. Open this page INSIDE your wallet app instead: open Trust, MetaMask, SafePal or Coinbase, find its Browser (or DApps) tab, and type rmcircle.team/my into that address bar. On iPhone, Trust no longer has a browser — use MetaMask or SafePal, or ask your sponsor to link you instead.';return;}
const accs=await eth.request({method:'eth_requestAccounts'});const account=accs[0]; const accs=await eth.request({method:'eth_requestAccounts'});const account=accs[0];
// Match the wallet's active chain to the SIWE message's Chain ID (137), // Match the wallet's active chain to the SIWE message's Chain ID (137),
// or the wallet rejects the signature ("chain ID does not match"). // or the wallet rejects the signature ("chain ID does not match").
+1 -1
View File
@@ -104,7 +104,7 @@
btn.disabled = true; btn.textContent = 'Connecting…'; btn.disabled = true; btn.textContent = 'Connecting…';
try { try {
var eth = await window.RMCWallet.pick(); var eth = await window.RMCWallet.pick();
if (!eth) { err.textContent = 'No wallet found in this browser. On a phone, open this page inside your wallet app’s browser (the DApps tab) — type rmcircle.team/suite there.'; err.style.display = 'block'; btn.disabled = false; btn.textContent = '🔑 Connect wallet — light up my tools'; return; } if (!eth) { err.textContent = 'This browser has no wallet in it. Open this page INSIDE your wallet app instead: open Trust, MetaMask, SafePal or Coinbase, find its Browser (or DApps) tab, and type rmcircle.team/suite into that address bar. On iPhone, Trust no longer has a browser — use MetaMask or SafePal, or ask your sponsor to link you instead.'; err.style.display = 'block'; btn.disabled = false; btn.textContent = '🔑 Connect wallet — light up my tools'; return; }
var accs = await eth.request({ method: 'eth_requestAccounts' }); var accs = await eth.request({ method: 'eth_requestAccounts' });
var account = accs[0]; var account = accs[0];
try { await window.RMCWallet.ensureChain(eth); } catch (ce) {} try { await window.RMCWallet.ensureChain(eth); } catch (ce) {}
+25 -5
View File
@@ -147,6 +147,21 @@ function esc(s) {
}); });
} }
// House style puts the last beat of a heading in gold ("Team <gold>Grants.</gold>").
// These headlines are written by the model, so we cannot hand-pick the split —
// take the final two words, or the last one when the line is short. Everything
// is escaped first; the only markup added is our own span.
function goldTail(text) {
const t = String(text || '').trim();
if (!t) return '';
const words = t.split(/\s+/);
if (words.length < 3) return esc(t);
const take = words.length >= 6 ? 2 : 1;
const head = words.slice(0, words.length - take).join(' ');
const tail = words.slice(words.length - take).join(' ');
return esc(head) + ' <span class="gold">' + esc(tail) + '</span>';
}
function render(rec) { function render(rec) {
const a = ANGLES[rec.angle] || ANGLES.overview; const a = ANGLES[rec.angle] || ANGLES.overview;
// The button and the QR go to DIFFERENT places on purpose. // The button and the QR go to DIFFERENT places on purpose.
@@ -177,10 +192,15 @@ function render(rec) {
'<link rel="icon" type="image/png" href="/favicon.png"><link rel="stylesheet" href="/styles.css">' + '<link rel="icon" type="image/png" href="/favicon.png"><link rel="stylesheet" href="/styles.css">' +
'<style>' + '<style>' +
'.pp{max-width:760px;margin:0 auto;padding:30px 20px 70px}' + '.pp{max-width:760px;margin:0 auto;padding:30px 20px 70px}' +
'.pp h1{font-size:clamp(28px,5.5vw,44px);line-height:1.1;margin:10px 0 10px}' + '.pp h1{font-size:clamp(30px,6vw,48px);line-height:1.06;letter-spacing:-.8px;margin:8px 0 12px;text-wrap:balance}' +
'.pp .sub{color:var(--muted);font-size:18px;line-height:1.6;margin-bottom:22px}' + '.pp h1 .gold{color:var(--gold)}' +
'.pp .by{display:flex;align-items:center;gap:10px;color:var(--muted);font-size:14px;margin-bottom:8px}' + '.pp .sub{color:#dbe6ef;font-size:clamp(19px,2.4vw,22px);line-height:1.55;margin-bottom:24px;max-width:46ch}' +
'.pp .by b{color:var(--text)}' + // The byline becomes the gold eyebrow the rest of the site uses above
// an h1, so a member page reads as part of the same family instead of
// a stray document.
'.pp .by{display:flex;align-items:center;gap:8px;color:var(--gold);font-size:12px;font-weight:700;' +
'letter-spacing:1.6px;text-transform:uppercase;margin-bottom:6px}' +
'.pp .by b{color:var(--gold);font-weight:800}' +
'.pp .vid{border-radius:14px;overflow:hidden;border:1px solid var(--line);margin:0 0 24px}' + '.pp .vid{border-radius:14px;overflow:hidden;border:1px solid var(--line);margin:0 0 24px}' +
'.pp .vid video{display:block;width:100%;height:auto;aspect-ratio:16/9}' + '.pp .vid video{display:block;width:100%;height:auto;aspect-ratio:16/9}' +
'.pp p{color:var(--muted);line-height:1.7;margin-bottom:14px;font-size:16.5px}' + '.pp p{color:var(--muted);line-height:1.7;margin-bottom:14px;font-size:16.5px}' +
@@ -194,7 +214,7 @@ function render(rec) {
'<header class="wrap nav"><a class="brand" href="/"><img class="brand-mark" src="/logo.jpg" alt="The RM Circle" width="42" height="42"><span><span>RM Circle</span><small>A personal invitation</small></span></a></header>' + '<header class="wrap nav"><a class="brand" href="/"><img class="brand-mark" src="/logo.jpg" alt="The RM Circle" width="42" height="42"><span><span>RM Circle</span><small>A personal invitation</small></span></a></header>' +
'<main class="pp">' + '<main class="pp">' +
'<div class="by">Shared by <b>' + who + '</b> · Member #' + esc(rec.id) + '</div>' + '<div class="by">Shared by <b>' + who + '</b> · Member #' + esc(rec.id) + '</div>' +
'<h1>' + esc(c.headline || '') + '</h1>' + '<h1>' + goldTail(c.headline || '') + '</h1>' +
(c.subhead ? '<p class="sub">' + esc(c.subhead) + '</p>' : '') + (c.subhead ? '<p class="sub">' + esc(c.subhead) + '</p>' : '') +
'<div class="vid"><video controls preload="metadata" poster="' + a.poster + '" src="' + a.video + '"></video></div>' + '<div class="vid"><video controls preload="metadata" poster="' + a.poster + '" src="' + a.video + '"></video></div>' +
story + story +