Invite Only
Request a spot in the order. We will reach out to you soon.
A gated invitation form. Inline accessible errors validate on blur, the submit is disabled while a request is in flight, a hidden honeypot field catches bots, and a success state replaces the form once the request lands in the ledger.
The single conversion point. The hero and nav request-access affordances scroll here and focus the email field. This demo simulates the submit; the source posts through an access function that is a mock in dev and a serverless function in production.
No submit without disabled-while-loading. No browser-only validation; inline errors must be reachable by screen readers. Never remove the honeypot.
<style>
:root{
--bg:#0b0a08;--surface:#14110b;--ivory:#efe8d6;--muted:#9c9078;--faint:#5a5446;
--line:#2a2519;--line-faint:rgba(239,232,214,.08);--gold:#c9a24b;--gold-soft:#e7cd8c;
--font-display:'Instrument Serif',ui-serif,Georgia,'Times New Roman',serif;
--font-title:'Libre Caslon Condensed',ui-serif,Georgia,'Times New Roman',serif;
--font-body:'Inter',system-ui,-apple-system,sans-serif;
--font-mono:'JetBrains Mono',ui-monospace,monospace;
--ease:cubic-bezier(.22,1,.36,1);--dur-fast:200ms;--dur-base:400ms;
}
*{margin:0;padding:0;box-sizing:border-box}
body{background:var(--bg);color:var(--ivory);font-family:var(--font-body);min-height:100vh;padding:64px 48px}
.af{max-width:28rem;margin:0 auto;text-align:center}
.af .kick{font-family:var(--font-mono);font-size:.7rem;font-weight:500;text-transform:uppercase;letter-spacing:.42em;color:var(--gold)}
.af h2{margin-top:24px;font-family:var(--font-title);font-weight:400;font-size:clamp(2rem,5vw,3rem);line-height:1.04;color:var(--ivory)}
.af h2 .g{color:var(--gold-soft)}
.af .lede{margin:20px auto 0;max-width:34rem;color:var(--muted);font-size:1rem;font-weight:300;line-height:1.7}
.af form{margin-top:48px;text-align:left;display:flex;flex-direction:column;gap:20px}
.af .hp{position:absolute;left:-9999px;height:0;width:0;opacity:0}
.af label{display:block;margin-bottom:8px;font-family:var(--font-mono);font-size:.75rem;text-transform:uppercase;letter-spacing:.2em;color:var(--faint)}
.af input{width:100%;border-radius:.75rem;border:1px solid var(--line);background:rgba(20,17,11,.6);padding:12px 16px;color:var(--ivory);font-family:var(--font-body);font-size:.9375rem;transition:border-color var(--dur-base) var(--ease)}
.af input::placeholder{color:rgba(90,84,70,.8)}
.af input:focus{outline:none;border-color:rgba(201,162,75,.6)}
.af input[aria-invalid="true"]{border-color:#d9805f}
.af .err{margin-top:8px;font-size:.75rem;color:#d9805f}
.af .submit{display:inline-flex;align-items:center;justify-content:center;gap:10px;border-radius:9999px;border:0;background:var(--ivory);color:var(--bg);padding:14px 32px;font-family:var(--font-body);font-size:.875rem;font-weight:500;letter-spacing:.01em;cursor:pointer;box-shadow:0 0 80px -24px rgba(201,162,75,.5);transition:background-color var(--dur-base) var(--ease)}
.af .submit:hover{background:var(--gold-soft)}
.af .submit:focus-visible{outline:2px solid var(--gold);outline-offset:3px}
.af .submit:disabled{cursor:not-allowed;opacity:.6}
.af .submit svg{transition:transform var(--dur-base) var(--ease)}
.af .submit:hover svg{transform:translateX(2px)}
.af .fine{margin-top:4px;text-align:center;font-size:.75rem;font-weight:300;color:var(--faint)}
.af .note{color:#d9805f;font-size:.875rem}
.af .ok{max-width:28rem;margin:0 auto;border-radius:1rem;border:1px solid rgba(201,162,75,.3);background:rgba(20,17,11,.6);padding:40px 32px;text-align:center}
.af .ok .badge{display:flex;align-items:center;justify-content:center;height:2.5rem;width:2.5rem;margin:0 auto 16px;border-radius:9999px;border:1px solid rgba(201,162,75,.5)}
.af .ok h3{font-family:var(--font-title);font-weight:400;font-size:1.5rem;color:var(--ivory)}
.af .ok p{margin-top:8px;font-size:.875rem;font-weight:300;color:var(--muted)}
</style>
<div class="af" id="af">
<p class="kick">Invite Only</p>
<h2>Membership is by <span class="g">invitation</span>.</h2>
<p class="lede">Request a spot in the order. We will reach out to you soon.</p>
<form id="form" novalidate>
<input class="hp" type="text" name="company" tabindex="-1" autocomplete="off" aria-hidden="true">
<div>
<label for="hf-name">Full name</label>
<input id="hf-name" name="name" type="text" autocomplete="name" placeholder="Ada Lovelace">
<p class="err" id="hf-name-err" hidden></p>
</div>
<div>
<label for="hf-email">Email</label>
<input id="hf-email" name="email" type="email" inputmode="email" autocomplete="email" placeholder="you@firm.com">
<p class="err" id="hf-email-err" hidden></p>
</div>
<p class="note" id="hf-fail" hidden>Your request could not be sent. Please try again.</p>
<button class="submit" id="submit" type="submit">
<span id="submit-label">Request an Invitation</span>
<svg width="15" height="15" viewBox="0 0 16 16" fill="none" aria-hidden="true"><path d="M3 8h10M9 4l4 4-4 4" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>
</button>
<p class="fine">Single opt-in. We will never share your details.</p>
</form>
</div>
<script>
var form = document.getElementById("form");
var nameI = document.getElementById("hf-name");
var emailI = document.getElementById("hf-email");
var submit = document.getElementById("submit");
var label = document.getElementById("submit-label");
function showErr(id, msg){
var el = document.getElementById(id);
if(msg){ el.textContent = msg; el.hidden = false; }
else el.hidden = true;
}
function validEmail(v){ return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(v); }
function validateName(){
var ok = nameI.value.trim().length > 0;
nameI.setAttribute("aria-invalid", ok ? "false" : "true");
showErr("hf-name-err", ok ? "" : "Your full name is required.");
return ok;
}
function validateEmail(){
var v = emailI.value.trim();
var ok = v.length > 0 && validEmail(v);
emailI.setAttribute("aria-invalid", ok ? "false" : "true");
showErr("hf-email-err", !v ? "An email is required." : (!validEmail(v) ? "Enter a valid email address." : ""));
return ok;
}
nameI.addEventListener("blur", validateName);
emailI.addEventListener("blur", validateEmail);
form.addEventListener("submit", function(e){
e.preventDefault();
// Honeypot: if filled, silently drop.
if(form.elements["company"].value) return;
document.getElementById("hf-fail").hidden = true;
var ok = validateName() & validateEmail();
if(!ok) return;
submit.disabled = true;
label.textContent = "Sending…";
// Simulated submit; the source posts through submitAccess().
setTimeout(function(){
submit.disabled = false;
label.textContent = "Request an Invitation";
var af = document.getElementById("af");
af.innerHTML =
'<div class="ok" role="status">' +
'<div class="badge"><svg width="18" height="18" viewBox="0 0 24 24" fill="none" aria-hidden="true"><path d="M5 13l4 4L19 7" stroke="#e7cd8c" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg></div>' +
'<h3>Your request has entered the ledger.</h3>' +
'<p>A steward will reach out when a place opens.</p>' +
'</div>';
}, 900);
});
</script>