polish: inviting logged-out gates + full regression QA (0.67.0)

- the booth and account logged-out gates were the last plain 'Log in' surfaces
  (one line + a tiny pixel button). Reworked both into branded, inviting cards
  with an icon, a real pitch, and prominent CTAs (Log in/Sign up + Browse
  agents) — consistent with the gatehouse and hero
- regression QA: smoke-tested all 9 public surfaces (tavern, browse, mansion,
  booth gate, gatehouse, status, changelog, docs, PM gate) — every one renders
  with zero console errors; API, Git, Webagent all 200
- verified live: rich booth gate renders with both CTAs
This commit is contained in:
artheru 2026-06-10 09:12:00 +08:00
parent 26030b0a13
commit 2bbe9b9043
6 changed files with 27 additions and 5 deletions

View File

@ -4,7 +4,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="theme-color" content="#0e0a14" /> <meta name="theme-color" content="#0e0a14" />
<meta name="description" content="amerc is the agent mercenary tavern — hire, run, publish, and remotely deliver AI agents across software boundaries. No infrastructure, just skills." /> <meta name="description" content="amerc is the agent mercenary tavern — hire, run, publish, and remotely deliver AI agents across software boundaries. No infrastructure, just skills." />
<meta name="version" content="0.66.0-backtotop" /> <meta name="version" content="0.67.0-gates" />
<link rel="icon" href="/favicon.svg" type="image/svg+xml" /> <link rel="icon" href="/favicon.svg" type="image/svg+xml" />
<link rel="icon" href="/app-192.png" type="image/png" sizes="192x192" /> <link rel="icon" href="/app-192.png" type="image/png" sizes="192x192" />
<link rel="apple-touch-icon" href="/apple-touch-icon.png" /> <link rel="apple-touch-icon" href="/apple-touch-icon.png" />

View File

@ -1,6 +1,6 @@
{ {
"name": "amerc-site", "name": "amerc-site",
"version": "0.66.0-backtotop", "version": "0.67.0-gates",
"private": true, "private": true,
"type": "module", "type": "module",
"scripts": { "scripts": {

View File

@ -10,7 +10,14 @@ export default function Account({ auth, setRoute }) {
const [nw, setNw] = useState(''); const [nw, setNw] = useState('');
const [err, setErr] = useState(''); const [err, setErr] = useState('');
if (!auth.ready) return <div className="ap"><p>Loading</p></div>; if (!auth.ready) return <div className="ap"><p>Loading</p></div>;
if (!auth.user) return <div className="ap ap-gate"><h2>Account</h2><p>Log in to manage your account.</p><button className="px-action" onClick={() => setRoute('signin')}>Go to Login</button></div>; if (!auth.user) return (
<div className="ap ap-gate ap-gate-rich">
<span className="ap-gate-ico" aria-hidden="true">👤</span>
<h2>Your account</h2>
<p>Log in to manage your profile and password, mint agent keys, and view your showcases.</p>
<div className="ap-gate-cta"><button className="gm-cta-btn gm-cta-primary" onClick={() => setRoute('signin')}>Log in / Sign up</button></div>
</div>
);
const u = auth.user; const u = auth.user;
const changePw = async (e) => { const changePw = async (e) => {
e.preventDefault(); setErr(''); e.preventDefault(); setErr('');

View File

@ -238,7 +238,15 @@ export function BoothDashboard({ auth, setRoute }) {
if (!auth.ready) return <div className="ap"><p>Loading</p></div>; if (!auth.ready) return <div className="ap"><p>Loading</p></div>;
if (!auth.user) return ( if (!auth.user) return (
<div className="ap ap-gate"><h2>My Booth</h2><p>Log in to publish and run agents.</p><button className="px-action" onClick={() => setRoute('signin')}>Go to Login</button></div> <div className="ap ap-gate ap-gate-rich">
<span className="ap-gate-ico" aria-hidden="true">🗡</span>
<h2>Your booth awaits</h2>
<p>Log in to publish agent classes, run instances, and put your mercenaries to work as an embedded chatbox, a live web terminal, or behind a public URL.</p>
<div className="ap-gate-cta">
<button className="gm-cta-btn gm-cta-primary" onClick={() => setRoute('signin')}>Log in / Sign up</button>
<button className="gm-cta-btn gm-cta-secondary" onClick={() => setRoute('agents')}>Browse agents</button>
</div>
</div>
); );
const publishClass = async (e) => { const publishClass = async (e) => {

View File

@ -7,7 +7,7 @@ import Account from './Account.jsx';
import TavernGame from './TavernGame.jsx'; import TavernGame from './TavernGame.jsx';
import { api } from './api.js'; import { api } from './api.js';
const RELEASE = '0.66.0-backtotop'; const RELEASE = '0.67.0-gates';
const NAV = [ const NAV = [
{ id: 'home', label: 'Tavern' }, { id: 'home', label: 'Tavern' },

View File

@ -1457,3 +1457,10 @@ button {
.gm-totop.show { opacity: 0.92; transform: none; pointer-events: auto; } .gm-totop.show { opacity: 0.92; transform: none; pointer-events: auto; }
.gm-totop.show:hover { opacity: 1; background: linear-gradient(180deg, #46c8e0, #2aa7d8); } .gm-totop.show:hover { opacity: 1; background: linear-gradient(180deg, #46c8e0, #2aa7d8); }
@media (prefers-reduced-motion: reduce) { .gm-totop { transition: opacity .2s; transform: none; } } @media (prefers-reduced-motion: reduce) { .gm-totop { transition: opacity .2s; transform: none; } }
/* polished logged-out gates (0.67) */
.ap-gate-rich { max-width: 480px; margin: 44px auto 0; text-align: center; }
.ap-gate-ico { font-size: 40px; display: block; margin-bottom: 12px; filter: drop-shadow(0 4px 10px rgba(0,0,0,0.4)); }
.ap-gate-rich h2 { font-family: Georgia, "Times New Roman", serif; font-size: 24px; color: #fff; margin: 0 0 10px; }
.ap-gate-rich p { color: #b6a7d4; font-size: 14px; line-height: 1.65; margin: 0 0 22px; }
.ap-gate-cta { display: flex; gap: 12px; justify-content: center; flex-wrap: wrap; }