← back to Coming Soon Template
template.html
305 lines
<!doctype html>
<html lang="en" data-theme="light">
<head>
<!--
Coming-soon template — Gucci-aesthetic editorial landing.
Per-domain swap points (case-sensitive, double-curly):
{{WORDMARK}} — domain stem, no TLD → e.g. "abramsos"
{{TAGLINE}} — italic line under wordmark → e.g. "the operating system"
{{HERO_URL}} — 2560×1600 editorial photo URL → CC0 or Steve-owned
{{HERO_ALT}} — accessible alt text
{{DOMAIN}} — full domain incl. TLD → posted as `source` to /api/email-signup
{{PAGE_TITLE}} — <title> + og:title → e.g. "abramsos — coming soon"
{{ACCENT_HEX}} — single accent hex for chrome → keep neutral or pull from hero
Paper-design specs:
container max-width: 1440px center, 24px gutters
grid: hero 100vh, wordmark zone 480px below
type scale (modular 1.25): 11→14→18→22→28→36→48 (px)
wordmark: clamp(56px, 9vw, 128px), Cormorant Garamond display, weight 300
tagline: 12px, sans, +0.06em tracked, uppercase, opacity .6
email input: 14px monospace, hairline 1px underline, no border
breakpoints: <=720 mobile (wordmark→clamp 44px,12vw,96px; hero 70vh)
Standing rules honored:
- Logo upper-left (initial only)
- Hamburger upper-right (decorative — no menu wired)
- Sun/moon toggle next to hamburger (anti-flash inline script)
- Wordmark BELOW the hero photo, never overlapping
- Viewport meta required (mobile @media depends on it)
- No AI-vendor names visible
-->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="robots" content="noindex,nofollow">
<title>{{PAGE_TITLE}}</title>
<meta property="og:title" content="{{PAGE_TITLE}}">
<meta property="og:image" content="{{HERO_URL}}">
<meta name="theme-color" content="#faf8f3">
<link rel="preload" as="image" href="{{HERO_URL}}">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Cormorant+Garamond:ital,wght@0,300;0,500;1,300&family=Inter:wght@300;400&family=JetBrains+Mono:wght@300;400&display=swap">
<script>
// Anti-flash theme hydration — must run before paint
(function(){
try {
var t = localStorage.getItem('cs-theme');
if (t === 'dark' || (t === null && window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
document.documentElement.setAttribute('data-theme', 'dark');
}
} catch(e) {}
})();
</script>
<style>
:root {
--bg: #faf8f3;
--ink: #0f0e0c;
--ink-soft: #57544c;
--ink-faint: #9b958a;
--line: #e5dfd0;
--card: #ffffff;
--accent: {{ACCENT_HEX}};
--serif: 'Cormorant Garamond', Georgia, 'Times New Roman', serif;
--sans: 'Inter', -apple-system, system-ui, sans-serif;
--mono: 'JetBrains Mono', ui-monospace, Menlo, monospace;
}
html[data-theme="dark"] {
--bg: #0f0e0c;
--ink: #faf8f3;
--ink-soft: #b5ab98;
--ink-faint: #6c6557;
--line: #2a2820;
--card: #18170f;
}
* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; background: var(--bg); color: var(--ink); }
body { font-family: var(--sans); font-weight: 300; -webkit-font-smoothing: antialiased; line-height: 1.5; min-height: 100vh; }
a { color: inherit; text-decoration: none; }
/* HEADER — fixed bar, transparent over hero, fades to bg on scroll */
header.gh {
position: fixed; top: 0; left: 0; right: 0; z-index: 10;
display: flex; justify-content: space-between; align-items: center;
padding: 22px 28px;
pointer-events: none;
}
header.gh > * { pointer-events: auto; }
.glyph {
font-family: var(--serif); font-weight: 300; font-size: 32px; line-height: 1;
color: var(--ink); letter-spacing: -0.02em;
text-shadow: 0 1px 12px rgba(0,0,0,.22);
}
html[data-theme="dark"] .glyph { text-shadow: 0 1px 12px rgba(0,0,0,.55); }
.top-right { display: flex; align-items: center; gap: 18px; }
.theme-toggle, .ham, .login {
background: transparent; border: 0; padding: 6px; cursor: pointer;
color: var(--ink); width: 32px; height: 32px;
display: flex; align-items: center; justify-content: center;
filter: drop-shadow(0 1px 8px rgba(0,0,0,.22));
}
.ham svg, .theme-toggle svg, .login svg { width: 22px; height: 22px; }
/* HERO — full-bleed editorial photo */
.hero {
width: 100%; height: 100vh; min-height: 560px;
background: var(--card) center/cover no-repeat;
background-image: url('{{HERO_URL}}');
position: relative;
}
.hero::after {
/* Subtle bottom-fade so the wordmark zone reads cleanly when content peeks */
content: ''; position: absolute; inset: auto 0 0 0; height: 24%;
background: linear-gradient(to bottom, transparent, var(--bg));
pointer-events: none;
}
/* WORDMARK ZONE — center column under hero */
.meta {
max-width: 720px; margin: 0 auto; padding: 64px 24px 96px;
text-align: center;
}
.wordmark {
font-family: var(--serif); font-weight: 300; font-style: normal;
font-size: clamp(56px, 9vw, 128px); line-height: 1.02;
letter-spacing: -0.01em; color: var(--ink);
margin: 0 0 14px;
}
.tagline {
font-family: var(--serif); font-style: italic; font-weight: 300;
font-size: clamp(16px, 2.4vw, 22px);
color: var(--ink-soft); margin: 0 0 4px;
}
.eyebrow {
font-family: var(--sans); font-size: 11px; font-weight: 400;
text-transform: uppercase; letter-spacing: 0.18em;
color: var(--ink-faint); margin: 0 0 24px;
}
/* EMAIL CAPTURE — hairline, monospace, link-style submit */
form.signup {
margin: 40px auto 0; max-width: 420px;
display: flex; align-items: baseline; gap: 18px;
border-bottom: 1px solid var(--line);
padding-bottom: 6px;
}
form.signup input[type=email] {
flex: 1; min-width: 0;
background: transparent; border: 0; outline: none;
font-family: var(--mono); font-size: 14px; font-weight: 400;
color: var(--ink); padding: 10px 0;
}
form.signup input[type=email]::placeholder { color: var(--ink-faint); }
form.signup button {
background: transparent; border: 0; padding: 0; cursor: pointer;
font-family: var(--sans); font-size: 11px; font-weight: 400;
text-transform: uppercase; letter-spacing: 0.18em;
color: var(--ink); border-bottom: 1px solid var(--ink);
padding-bottom: 2px;
transition: opacity .15s ease;
}
form.signup button:hover { opacity: 0.6; }
form.signup button:disabled { color: var(--ink-faint); border-color: var(--ink-faint); cursor: progress; }
.signup-msg {
margin: 14px auto 0; max-width: 420px;
font-family: var(--sans); font-size: 12px; color: var(--ink-soft);
min-height: 18px;
text-align: center;
}
.signup-msg.err { color: #c0392b; }
.signup-msg.ok { color: #1e6b3a; }
/* FOOTER */
footer.gf {
margin-top: 40px; padding: 28px 24px 36px;
border-top: 1px solid var(--line);
text-align: center;
font-family: var(--sans); font-size: 11px; letter-spacing: 0.08em; text-transform: uppercase;
color: var(--ink-faint);
}
footer.gf a {
color: var(--ink-soft); border-bottom: 1px solid transparent;
transition: border-color .15s ease;
}
footer.gf a:hover { border-color: var(--ink-soft); }
.gf-domain {
font-family: var(--serif); font-style: italic; font-size: 14px;
text-transform: none; letter-spacing: 0; color: var(--ink-soft);
margin-right: 14px;
}
/* Mobile */
@media (max-width: 720px) {
.hero { height: 70vh; min-height: 480px; }
.meta { padding: 48px 20px 72px; }
header.gh { padding: 16px 18px; }
.glyph { font-size: 26px; }
}
/* Print — keep wordmark + tagline readable; suppress chrome */
@media print {
header.gh, .theme-toggle, .ham, .login, form.signup, .signup-msg { display: none; }
.hero { height: 60vh; }
}
</style>
</head>
<body>
<header class="gh">
<a href="/" class="glyph" aria-label="{{WORDMARK}} home">{{WORDMARK_INITIAL}}</a>
<div class="top-right">
<button class="theme-toggle" id="themeToggle" aria-label="Toggle light/dark theme">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.4">
<circle cx="12" cy="12" r="4"/>
<path d="M12 2v2M12 20v2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M2 12h2M20 12h2M4.93 19.07l1.41-1.41M17.66 6.34l1.41-1.41"/>
</svg>
</button>
<a class="login" href="https://admin.agentabrams.com/" aria-label="Admin login">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.4">
<circle cx="12" cy="8" r="4"/>
<path d="M4 21c0-4.4 3.6-8 8-8s8 3.6 8 8"/>
</svg>
</a>
<button class="ham" aria-label="Menu (coming soon)">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.4">
<path d="M3 7h18M3 12h18M3 17h18"/>
</svg>
</button>
</div>
</header>
<section class="hero" role="img" aria-label="{{HERO_ALT}}"></section>
<main class="meta">
<p class="eyebrow">Coming soon</p>
<h1 class="wordmark">{{WORDMARK}}</h1>
<p class="tagline">{{TAGLINE}}</p>
<form class="signup" id="signupForm" novalidate>
<input type="email" name="email" id="emailInput" placeholder="your@email.com" required autocomplete="email" inputmode="email">
<button type="submit" id="signupBtn">Notify me</button>
</form>
<div class="signup-msg" id="signupMsg" role="status" aria-live="polite"></div>
</main>
<footer class="gf">
<a href="https://agentabrams.com" class="gf-domain">agentabrams.com</a>
<span>© {{YEAR}} · {{DOMAIN}}</span>
</footer>
<script>
// Theme toggle
(function(){
var btn = document.getElementById('themeToggle');
btn.addEventListener('click', function(){
var cur = document.documentElement.getAttribute('data-theme') || 'light';
var next = cur === 'dark' ? 'light' : 'dark';
document.documentElement.setAttribute('data-theme', next);
try { localStorage.setItem('cs-theme', next); } catch(e){}
});
})();
// Email capture
(function(){
var form = document.getElementById('signupForm');
var input = document.getElementById('emailInput');
var btn = document.getElementById('signupBtn');
var msg = document.getElementById('signupMsg');
var ENDPOINT = 'https://agentabrams.com/api/email-signup';
var SOURCE = '{{DOMAIN}}';
function setMsg(text, cls) {
msg.textContent = text || '';
msg.classList.remove('err', 'ok');
if (cls) msg.classList.add(cls);
}
form.addEventListener('submit', async function(e){
e.preventDefault();
var email = (input.value || '').trim();
if (!email || !/.+@.+\..+/.test(email)) {
setMsg('Please enter a valid email.', 'err'); return;
}
btn.disabled = true; setMsg('');
try {
var r = await fetch(ENDPOINT, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ email: email, source: SOURCE, timestamp: new Date().toISOString() })
});
if (r.ok) {
form.style.display = 'none';
setMsg('Thank you. We will be in touch.', 'ok');
} else {
setMsg('Could not save right now — please try again shortly.', 'err');
btn.disabled = false;
}
} catch (err) {
setMsg('Network error — please try again shortly.', 'err');
btn.disabled = false;
}
});
})();
</script>
</body>
</html>