index.astro

   1---
   2import Layout from '../layouts/Layout.astro';
   3import WaitlistForm from '../components/WaitlistForm.astro';
   4import HostingMap from '../components/HostingMap.astro';
   5import Masthead from '../components/Masthead.astro';
   6import Footer from '../components/Footer.astro';
   7
   8const provisions = [
   9	{
  10		term: 'Your domain, your passport to an ecosystem of apps',
  11        body: 'Built on the Atmosphere, an open-web standard that keeps all your data securely in one place. Your email becomes your Atmosphere identity, with single sign-on to dozens of apps for your business.',
  12		machine: '[email protected]',
  13	},
  14	{
  15		term: 'Works with all your apps',
  16		body: 'Use any mail app or our webmail. Speaks every protocol so you can connect anywhere.',
  17		machine: 'Apple Mail · Outlook · Webmail',
  18	},
  19	{
  20		term: 'Mail that hits the inbox',
  21        body: 'Configured to fight spam. Your messages land in inboxes, not the promotions tab.',
  22		machine: 'delivery: reliable',
  23	},
  24	{
  25		term: 'Reliability baked in',
  26        body: 'We know email is a critical service for your business. We expertly run it so you can worry about other things.',
  27		machine: 'status: healthy',
  28	},
  29	{
  30        term: 'No lock-in, no surveillance',
  31        body: 'Open-source infrastructure built on the AT Protocol means you can never be locked in. Good service for a reasonable price, independent of the big players.',
  32		machine: 'lock-in: impossible',
  33	},
  34];
  35
  36const ledger = [
  37	{ topic: 'Your identity', them: 'An account on their platform.', us: 'An Atmosphere identity you control.' },
  38	{ topic: 'Where mail lives', them: 'Wherever their data centres are.', us: 'Inside the EU, if you choose.' },
  39    { topic: 'The rules', them: 'Their terms, worse for you all the time.', us: 'Open protocols and open-source software.' },
  40	{ topic: 'Lock-in', them: 'That\'s their business model.', us: 'Impossible by design.' },
  41];
  42
  43// Exchange grid: identity in the centre, routes out to each kind of app.
  44// Positions are 3×3 cells, row-major; 4 is the centre.
  45const exchange = [
  46	{ key: 'mail', pos: 0, title: 'Business email', line: 'sovrn Mail, on your own domain.', live: true },
  47	{ key: 'blog', pos: 1, title: 'Blogging', line: 'Publish a journal or newsletter under your name.' },
  48	{ key: 'pod', pos: 2, title: 'Podcast production', line: 'Record, publish and keep your feed.' },
  49	{ key: 'chat', pos: 3, title: 'Team chat', line: 'Talk with staff and clients, no extra login.' },
  50	{ key: 'git', pos: 5, title: 'Git forge hosting', line: 'Host code and review changes together.' },
  51	{ key: 'events', pos: 6, title: 'Events & RSVPs', line: 'Invite customers and see who’s coming.' },
  52	{ key: 'social', pos: 7, title: 'Social publishing', line: 'Reach people on open social networks.' },
  53	{ key: 'photos', pos: 8, title: 'Portfolios & photos', line: 'Show your work where you choose.' },
  54];
  55const cellCentre = (pos: number) => ({ x: (pos % 3) * 100 + 50, y: Math.floor(pos / 3) * 100 + 50 });
  56
  57---
  58
  59<Layout>
  60
  61	<Masthead />
  62
  63	<main id="main">
  64		<section class="hero" aria-labelledby="hero-title">
  65			<div class="hero-field">
  66				<h1 id="hero-title" class="hero-title">
  67					<span>Reliable email</span>
  68					<span>for independent</span>
  69					<span>business.</span>
  70				</h1>
  71				<div class="hero-action">
  72					<p class="hero-sub">
  73						<span>Quality email hosting for your domain.</span>
  74						<span>Declare your sovereignty from big-tech bad actors.</span>
  75					</p>
  76					<WaitlistForm id="hero" />
  77				</div>
  78			</div>
  79			<div class="hero-column on-dark" aria-hidden="true">
  80				<img class="speedmark" src="/plates/speedmark.png" alt="" width="1032" height="528" />
  81			</div>
  82		</section>
  83
  84		<section class="chain on-dark" aria-label="What independence means">
  85			<ul class="pledges">
  86				<li>
  87					<strong>Your data stays yours.</strong>
  88                    <span>No surveillance, no lock-in. Kept secure by design.</span>
  89				</li>
  90				<li>
  91					<strong>You decide where it lives.</strong>
  92					<span>Host in the EU or choose another region near you.</span>
  93				</li>
  94				<li>
  95					<strong>Independent infrastructure.</strong>
  96					<span>No more reliance on big-tech companies that don't support your values.</span>
  97				</li>
  98			</ul>
  99			<div class="chain-corner" aria-hidden="true"></div>
 100		</section>
 101
 102		<section id="mail" class="schedule" aria-labelledby="mail-title">
 103			<div class="schedule-head">
 104				<h2 id="mail-title" class="section-title">Mail, run properly.</h2>
 105				<p class="lede">
 106                Hosted email for businesses that want to break free of big tech, built on a protocol that guarantees your independence.
 107				</p>
 108			</div>
 109			<dl class="schedule-list">
 110				{
 111					provisions.map((p) => (
 112						<div class="schedule-row">
 113							<dt>{p.term}</dt>
 114							<dd class="schedule-body">{p.body}</dd>
 115							<dd class="schedule-machine mono">{p.machine}</dd>
 116						</div>
 117					))
 118				}
 119			</dl>
 120		</section>
 121
 122		<section class="ledger on-dark" aria-labelledby="ledger-title">
 123			<h2 id="ledger-title" class="section-title">
 124                Break free of big tech. Nothing lost, but a whole lot gained.
 125			</h2>
 126			<table class="ledger-table">
 127				<caption class="visually-hidden">How a big-tech suite compares with sovrn</caption>
 128				<thead>
 129					<tr>
 130						<th scope="col"><span class="visually-hidden">Topic</span></th>
 131						<th scope="col">With big-tech email</th>
 132						<th scope="col" class="ours">With us</th>
 133					</tr>
 134				</thead>
 135				<tbody>
 136					{
 137						ledger.map((row) => (
 138							<tr>
 139								<th scope="row">{row.topic}</th>
 140								<td>{row.them}</td>
 141								<td class="ours">{row.us}</td>
 142							</tr>
 143						))
 144					}
 145				</tbody>
 146			</table>
 147		</section>
 148
 149		<section id="eu" class="region" aria-labelledby="eu-title">
 150			<div class="region-plate">
 151				<HostingMap />
 152			</div>
 153			<div class="region-copy">
 154				<h2 id="eu-title" class="section-title">Choose where your mail lives.</h2>
 155				<p class="lede">
 156                    Pick the jurisdiction that makes sense for you. Always on independent infrastructure no matter what you choose.
 157				</p>
 158				<figure class="region-form" aria-label="Hosting region choice, illustrated">
 159					<p class="region-form-label">Hosting region, chosen by you.</p>
 160					<div class="tick is-on">
 161						<span class="box" aria-hidden="true">
 162							<svg viewBox="0 0 20 20"><path d="M4 4l12 12M16 4L4 16" fill="none" stroke="currentColor" stroke-width="2.25" /></svg>
 163						</span>
 164						<span><strong>EU</strong>Strong data-protection laws and consumer rights.</span>
 165					</div>
 166					<div class="tick">
 167						<span class="box" aria-hidden="true"></span>
 168						<span><strong>Elsewhere</strong> Outside the EU? Pick somewhere closer, still free of big tech.</span>
 169					</div>
 170				</figure>
 171			</div>
 172		</section>
 173
 174		<section id="atmosphere" class="atmos on-dark" aria-labelledby="atmos-title">
 175			<div class="atmos-copy">
 176				<h2 id="atmos-title" class="section-title">One identity. A whole ecosystem.</h2>
 177				<p class="lede">
 178					Every email account is also an Atmosphere account, built on the open AT Protocol. The same identity works
 179					across a growing network of independent apps, and your data comes with you when you switch.
 180				</p>
 181				<p class="atmos-note">
 182                A whole host of apps to help you run your business, integrated with single sign-on, where your data can't be locked away.
 183				</p>
 184			</div>
 185			<div class="exchange">
 186				<svg class="routes" viewBox="0 0 300 300" preserveAspectRatio="none" aria-hidden="true">
 187					{
 188						exchange.map((c) => {
 189							const { x, y } = cellCentre(c.pos);
 190							return <line class={`route route-${c.key}`} x1="150" y1="150" x2={x} y2={y} />;
 191						})
 192					}
 193				</svg>
 194				<ul class="exchange-grid">
 195					{
 196						exchange.map((c) => (
 197							<li class:list={['cell', { live: c.live }]} style={`--col:${(c.pos % 3) + 1};--row:${Math.floor(c.pos / 3) + 1}`} data-route={c.key} tabindex="0">
 198								<span class="cell-title">{c.title}</span>
 199								<span class="cell-line">{c.line}</span>
 200								{c.live ? <span class="cell-tag">Open for the waitlist</span> : null}
 201							</li>
 202						))
 203					}
 204					<li class="cell hub">
 205						<span class="cell-title">Your identity</span>
 206						<span class="cell-line mono">@yourstudio.eu</span>
 207					</li>
 208				</ul>
 209			</div>
 210		</section>
 211
 212		<section class="steps" aria-labelledby="steps-title">
 213			<h2 id="steps-title" class="section-title">Just three steps to a better email</h2>
 214			<ol class="steps-list">
 215				<li>
 216					<span class="step-n" aria-hidden="true">1</span>
 217					<h3>Sign in</h3>
 218					<p>Use the Atmosphere account you already have, or create one with us.</p>
 219				</li>
 220				<li>
 221					<span class="step-n" aria-hidden="true">2</span>
 222					<h3>Add your domain</h3>
 223					<p>Publish the DNS records we give you. We check them and tell you when each one is ready.</p>
 224					<p class="record mono" aria-label="Example DNS record">
 225						<span class="record-type">MX</span> yourbakery.eu
 226					</p>
 227				</li>
 228				<li>
 229					<span class="step-n" aria-hidden="true">3</span>
 230					<h3>Go live</h3>
 231					<p>Create mailboxes for your team and connect any mail app. Mail starts arriving.</p>
 232				</li>
 233			</ol>
 234		</section>
 235
 236		<section id="join" class="close" aria-labelledby="join-title">
 237			<div class="close-field">
 238				<h2 id="join-title" class="close-title">Take back your sovereignty.</h2>
 239				<p class="close-sub">
 240					Mail is our first service. More tools for running an independent business will follow, all on the
 241					same identity. Join the waitlist and we’ll send an invite when there’s room.
 242				</p>
 243				<WaitlistForm id="close" />
 244			</div>
 245			<div class="close-column on-dark" aria-hidden="true">
 246				<img class="close-mark" src="/plates/speedmark.png" alt="" width="1032" height="528" loading="lazy" />
 247			</div>
 248		</section>
 249	</main>
 250
 251	<Footer />
 252</Layout>
 253
 254<style>
 255	/* ——— Hero ——— */
 256	.hero {
 257		display: grid;
 258		grid-template-columns: 1fr 24.6%;
 259		min-height: clamp(34rem, min(77.6svh, 51.7vw), 54rem);
 260	}
 261
 262	.hero-field {
 263		display: flex;
 264		flex-direction: column;
 265		justify-content: space-between;
 266		gap: 2rem;
 267		padding: clamp(2rem, min(5.6svh, 3.7vw), 4rem) 2.3% clamp(1.25rem, min(3.4svh, 2.3vw), 2.5rem) var(--gutter);
 268		background: var(--gold);
 269		color: var(--ptt);
 270	}
 271
 272	.hero-title {
 273		font-size: clamp(2.3rem, 8.2vw, 7.9rem);
 274		font-weight: 850;
 275		line-height: 0.95;
 276		letter-spacing: -0.042em;
 277		margin-left: -0.05em;
 278	}
 279
 280	.hero-title span,
 281	.hero-sub span {
 282		display: block;
 283	}
 284
 285	.hero-action {
 286		display: grid;
 287		gap: 2.25rem;
 288	}
 289
 290	.hero-sub {
 291		font-size: clamp(1.35rem, 2.6vw, 2.5rem);
 292		font-weight: 700;
 293		line-height: 1.03;
 294		letter-spacing: -0.045em;
 295	}
 296
 297	.hero-column {
 298		position: relative;
 299		background: var(--ptt);
 300		overflow: hidden;
 301	}
 302
 303	.speedmark {
 304		position: absolute;
 305		left: 3.7%;
 306		top: 24%;
 307		width: 91%;
 308		height: auto;
 309		/* the plate's ground is a shade darker than --ptt; lighten keeps only the bars */
 310		mix-blend-mode: lighten;
 311		animation: dispatch 1.1s var(--ease-out) 0.15s both;
 312	}
 313
 314	@keyframes dispatch {
 315		from {
 316			transform: translateX(-18%);
 317			clip-path: inset(0 100% 0 0);
 318		}
 319		to {
 320			transform: none;
 321			clip-path: inset(0 0 0 0);
 322		}
 323	}
 324
 325	@media (prefers-reduced-motion: reduce) {
 326		.speedmark {
 327			animation: none;
 328		}
 329	}
 330
 331	/* ——— Independence strip ——— */
 332	.chain {
 333		display: grid;
 334		grid-template-columns: 1fr 11.8%;
 335		min-height: clamp(5rem, min(12.1svh, 8.1vw), 8.5rem);
 336		background: var(--ptt);
 337		color: var(--paper);
 338	}
 339
 340	.pledges {
 341		display: grid;
 342		grid-template-columns: repeat(3, 1fr);
 343		align-content: center;
 344		gap: 1rem clamp(1.5rem, 3vw, 3rem);
 345		padding: 1.25rem var(--gutter);
 346		min-width: 0;
 347	}
 348
 349	.pledges li {
 350		display: grid;
 351		align-content: start;
 352		gap: 0.2rem;
 353		padding-top: 0.7rem;
 354		border-top: 3px solid var(--gold);
 355		font-size: clamp(0.9375rem, 1vw, 1.0625rem);
 356		line-height: 1.35;
 357		color: var(--ptt-soft);
 358	}
 359
 360	.pledges strong {
 361		color: var(--paper);
 362		font-size: clamp(1.0625rem, 1.35vw, 1.3rem);
 363		font-weight: 750;
 364		letter-spacing: -0.02em;
 365		line-height: 1.15;
 366	}
 367
 368	.chain-corner {
 369		background: var(--signal);
 370	}
 371
 372	/* ——— Shared section type ——— */
 373	.section-title {
 374		font-size: clamp(2.25rem, 5.2vw, 5rem);
 375		font-weight: 850;
 376		line-height: 0.95;
 377		letter-spacing: -0.04em;
 378		text-wrap: balance;
 379	}
 380
 381	.lede {
 382		font-size: clamp(1.125rem, 1.45vw, 1.375rem);
 383		line-height: 1.45;
 384		max-width: 38ch;
 385		text-wrap: pretty;
 386	}
 387
 388	/* ——— Service schedule ——— */
 389	.schedule {
 390		display: grid;
 391		grid-template-columns: 5fr 7fr;
 392		gap: 3rem var(--gutter);
 393		padding: clamp(4.5rem, 10vw, 9rem) var(--gutter) clamp(4rem, 8vw, 7rem);
 394		color: var(--ptt);
 395	}
 396
 397	.schedule-head {
 398		display: grid;
 399		align-content: start;
 400		gap: 1.75rem;
 401		position: sticky;
 402		top: 2rem;
 403		align-self: start;
 404	}
 405
 406	.schedule-head .lede {
 407		color: var(--ink-soft);
 408	}
 409
 410	.schedule-list {
 411		border-top: 3px solid var(--ptt);
 412	}
 413
 414	.schedule-row {
 415		display: grid;
 416		grid-template-columns: 1fr 1.35fr;
 417		gap: 0.5rem 2rem;
 418		padding: 1.75rem 0 1.85rem;
 419		border-bottom: 1px solid var(--paper-rule);
 420	}
 421
 422	.schedule-row dt {
 423		grid-row: span 2;
 424		font-size: clamp(1.25rem, 1.7vw, 1.6rem);
 425		font-weight: 750;
 426		line-height: 1.1;
 427		letter-spacing: -0.025em;
 428	}
 429
 430	.schedule-body {
 431		color: var(--ink);
 432		max-width: 44ch;
 433	}
 434
 435	.schedule-machine {
 436		justify-self: start;
 437		margin-top: 0.5rem;
 438		padding: 0.3rem 0.55rem;
 439		background: var(--gold-wash);
 440		color: var(--gold-ink);
 441		font-size: 0.875rem;
 442		font-weight: 500;
 443	}
 444
 445	/* ——— Ledger ——— */
 446	.ledger {
 447		display: grid;
 448		grid-template-columns: 5fr 7fr;
 449		gap: 3rem var(--gutter);
 450		padding: clamp(4.5rem, 9vw, 8rem) var(--gutter);
 451		background: var(--ptt);
 452		color: var(--paper);
 453	}
 454
 455	.ledger .section-title {
 456		align-self: start;
 457		max-width: 11ch;
 458	}
 459
 460	.ledger-table {
 461		width: 100%;
 462		border-collapse: collapse;
 463		font-size: 1.0625rem;
 464	}
 465
 466	.ledger-table th,
 467	.ledger-table td {
 468		padding: 1.15rem 1.25rem 1.2rem 0;
 469		text-align: left;
 470		vertical-align: top;
 471		border-bottom: 1px solid color-mix(in srgb, var(--ptt-soft) 35%, transparent);
 472	}
 473
 474	.ledger-table thead th {
 475		padding-top: 0;
 476		font-size: 0.9375rem;
 477		font-weight: 700;
 478		letter-spacing: -0.01em;
 479		color: var(--ptt-soft);
 480		border-bottom: 3px solid var(--paper);
 481	}
 482
 483	.ledger-table thead th.ours {
 484		color: var(--gold);
 485	}
 486
 487	.ledger-table tbody th {
 488		width: 24%;
 489		font-weight: 750;
 490		letter-spacing: -0.015em;
 491	}
 492
 493	.ledger-table td {
 494		color: var(--ptt-soft);
 495		width: 38%;
 496	}
 497
 498	.ledger-table td.ours {
 499		color: var(--paper);
 500		font-weight: 650;
 501	}
 502
 503	/* ——— EU region ——— */
 504	.region {
 505		display: grid;
 506		grid-template-columns: 1fr 1fr;
 507		align-items: stretch;
 508		background: var(--paper);
 509		color: var(--ptt);
 510		overflow: hidden;
 511	}
 512
 513	/* The map is printed as a plate: inset on paper and held by a hairline
 514	   frame, so its blue water never runs into the blue bands around it. */
 515	.region-plate {
 516		display: grid;
 517		align-content: center;
 518		padding: clamp(3rem, 6vw, 5.5rem) var(--gutter);
 519	}
 520
 521	.region :global(.hosting-map) {
 522		aspect-ratio: 1000 / 860;
 523		outline: 1px solid var(--ptt);
 524		outline-offset: 0.625rem;
 525	}
 526
 527	.region-copy {
 528		display: grid;
 529		align-content: center;
 530		gap: 1.75rem;
 531		padding: clamp(4rem, 8vw, 7.5rem) var(--gutter);
 532	}
 533
 534	.region-copy .lede {
 535		color: var(--ink);
 536	}
 537
 538	.region-form {
 539		display: grid;
 540		gap: 0.9rem;
 541		margin-top: 0.75rem;
 542		padding-top: 1.25rem;
 543		border-top: 3px solid var(--ptt);
 544		max-width: 34rem;
 545	}
 546
 547	.region-form-label {
 548		font-size: 0.9375rem;
 549		font-weight: 700;
 550		color: var(--ink-soft);
 551	}
 552
 553	.tick {
 554		display: flex;
 555		gap: 1rem;
 556		align-items: flex-start;
 557		color: var(--ink);
 558	}
 559
 560	.tick strong {
 561		display: block;
 562		color: var(--ptt);
 563		font-size: 1.25rem;
 564		letter-spacing: -0.02em;
 565	}
 566
 567	.box {
 568		flex: none;
 569		display: grid;
 570		place-items: center;
 571		width: 1.75rem;
 572		height: 1.75rem;
 573		margin-top: 0.15rem;
 574		border: 1px solid var(--ptt);
 575		color: var(--signal);
 576	}
 577
 578	.box svg {
 579		width: 1.25rem;
 580		height: 1.25rem;
 581	}
 582
 583	/* ——— Atmosphere exchange ——— */
 584	.atmos {
 585		display: grid;
 586		grid-template-columns: 5fr 7fr;
 587		gap: 3rem var(--gutter);
 588		padding: clamp(4.5rem, 9vw, 8rem) var(--gutter);
 589		background: var(--ptt-deep);
 590		color: var(--paper);
 591	}
 592
 593	.atmos-copy {
 594		display: grid;
 595		align-content: start;
 596		gap: 1.75rem;
 597	}
 598
 599	.atmos-copy .lede {
 600		color: var(--ptt-soft);
 601	}
 602
 603	.atmos-note {
 604		font-size: 1rem;
 605		font-weight: 700;
 606		letter-spacing: -0.01em;
 607		color: var(--gold);
 608	}
 609
 610	.exchange {
 611		position: relative;
 612		align-self: start;
 613		max-width: 44rem;
 614		width: 100%;
 615		justify-self: end;
 616	}
 617
 618	.routes {
 619		position: absolute;
 620		inset: 0;
 621		width: 100%;
 622		height: 100%;
 623	}
 624
 625	.route {
 626		stroke: var(--paper);
 627		stroke-opacity: 0.28;
 628		stroke-width: 6;
 629		vector-effect: non-scaling-stroke;
 630		transition:
 631			stroke 0.3s var(--ease-out),
 632			stroke-opacity 0.3s var(--ease-out),
 633			stroke-width 0.3s var(--ease-out);
 634	}
 635
 636	.route-mail {
 637		stroke: var(--gold);
 638		stroke-opacity: 1;
 639	}
 640
 641	.exchange-grid {
 642		position: relative;
 643		display: grid;
 644		grid-template-columns: repeat(3, 1fr);
 645		/* in an auto-height grid, 1fr rows all take the tallest row's height: one module */
 646		grid-template-rows: repeat(3, 1fr);
 647		gap: clamp(1.5rem, 4vw, 3.5rem);
 648	}
 649
 650	.cell {
 651		display: flex;
 652		flex-direction: column;
 653		justify-content: center;
 654		gap: 0.4rem;
 655		padding: clamp(0.75rem, 1.4vw, 1.25rem);
 656		background: var(--ptt-deep);
 657		border: 1px solid var(--ptt-soft);
 658		color: var(--paper);
 659		outline-offset: 4px;
 660		transition:
 661			background-color 0.3s var(--ease-out),
 662			transform 0.3s var(--ease-out);
 663	}
 664
 665	.cell {
 666		grid-column: var(--col, 2);
 667		grid-row: var(--row, 2);
 668	}
 669
 670	.cell-title {
 671		font-size: clamp(1rem, 1.5vw, 1.45rem);
 672		font-weight: 800;
 673		line-height: 1.02;
 674		letter-spacing: -0.03em;
 675	}
 676
 677	.cell-line {
 678		font-size: clamp(0.8rem, 0.95vw, 0.9375rem);
 679		line-height: 1.3;
 680		color: var(--ptt-soft);
 681	}
 682
 683	.cell-tag {
 684		margin-top: 0.35rem;
 685		font-size: 0.8125rem;
 686		font-weight: 700;
 687	}
 688
 689	.cell.live {
 690		background: var(--gold);
 691		border-color: var(--gold);
 692		color: var(--ptt);
 693	}
 694
 695	.cell.live .cell-line {
 696		color: var(--ptt);
 697	}
 698
 699	.cell.live .cell-tag {
 700		color: var(--ptt);
 701	}
 702
 703	.cell.hub {
 704		justify-content: center;
 705		background: var(--signal);
 706		border-color: var(--signal);
 707		color: #fff;
 708	}
 709
 710	.cell.hub .cell-title {
 711		font-size: clamp(1.25rem, 2.2vw, 2.1rem);
 712	}
 713
 714	.cell.hub .cell-line {
 715		color: var(--ink);
 716		font-size: clamp(0.75rem, 0.9vw, 0.875rem);
 717		overflow-wrap: anywhere;
 718	}
 719
 720	.cell:not(.hub):hover,
 721	.cell:not(.hub):focus-visible {
 722		border-color: var(--signal);
 723		box-shadow: inset 0 0 0 2px var(--signal);
 724	}
 725
 726	.cell.live:hover,
 727	.cell.live:focus-visible {
 728		border-color: var(--signal);
 729	}
 730
 731	/* the exchange patches a route when a line of work is pointed at */
 732	.exchange:has(.cell[data-route='mail']:is(:hover, :focus-visible)) .route-mail,
 733	.exchange:has(.cell[data-route='blog']:is(:hover, :focus-visible)) .route-blog,
 734	.exchange:has(.cell[data-route='pod']:is(:hover, :focus-visible)) .route-pod,
 735	.exchange:has(.cell[data-route='chat']:is(:hover, :focus-visible)) .route-chat,
 736	.exchange:has(.cell[data-route='git']:is(:hover, :focus-visible)) .route-git,
 737	.exchange:has(.cell[data-route='events']:is(:hover, :focus-visible)) .route-events,
 738	.exchange:has(.cell[data-route='social']:is(:hover, :focus-visible)) .route-social,
 739	.exchange:has(.cell[data-route='photos']:is(:hover, :focus-visible)) .route-photos {
 740		stroke: var(--signal);
 741		stroke-opacity: 1;
 742		stroke-width: 10;
 743	}
 744
 745	/* ——— Steps ——— */
 746	.steps {
 747		padding: clamp(4.5rem, 9vw, 8rem) var(--gutter);
 748		color: var(--ptt);
 749	}
 750
 751	.steps-list {
 752		display: grid;
 753		grid-template-columns: repeat(3, 1fr);
 754		margin-top: clamp(2.5rem, 5vw, 4rem);
 755		border-top: 3px solid var(--ptt);
 756	}
 757
 758	.steps-list li {
 759		display: grid;
 760		align-content: start;
 761		gap: 0.75rem;
 762		padding: 1.5rem 2rem 0 0;
 763	}
 764
 765	.steps-list li + li {
 766		padding-left: 2rem;
 767		border-left: 1px solid var(--paper-rule);
 768	}
 769
 770	.step-n {
 771		font-size: clamp(4.5rem, 8vw, 7.5rem);
 772		font-weight: 900;
 773		line-height: 0.85;
 774		letter-spacing: -0.06em;
 775		color: var(--ptt);
 776	}
 777
 778	.steps-list h3 {
 779		font-size: clamp(1.4rem, 2vw, 1.9rem);
 780		font-weight: 800;
 781		letter-spacing: -0.03em;
 782		line-height: 1.05;
 783	}
 784
 785	.steps-list p {
 786		color: var(--ink);
 787		max-width: 34ch;
 788	}
 789
 790	.steps-list .record {
 791		color: var(--ptt);
 792	}
 793
 794	.record {
 795		justify-self: start;
 796		display: inline-flex;
 797		gap: 0.75rem;
 798		align-items: center;
 799		margin-top: 0.25rem;
 800		padding: 0.45rem 0.7rem;
 801		border: 1px solid var(--ptt);
 802		font-size: 0.875rem;
 803
 804	}
 805
 806	.record-type {
 807		padding: 0.1rem 0.4rem;
 808		background: var(--ptt);
 809		color: var(--paper);
 810	}
 811
 812	/* ——— Close ——— */
 813	.close {
 814		display: grid;
 815		grid-template-columns: 1fr 24.6%;
 816	}
 817
 818	.close-field {
 819		display: grid;
 820		gap: 2rem;
 821		padding: clamp(4.5rem, 9vw, 8rem) var(--gutter);
 822		background: var(--gold);
 823		color: var(--ptt);
 824	}
 825
 826	.close-title {
 827		font-size: clamp(2.75rem, 7.5vw, 7.25rem);
 828		font-weight: 850;
 829		line-height: 0.93;
 830		letter-spacing: -0.04em;
 831	}
 832
 833	.close-sub {
 834		font-size: clamp(1.125rem, 1.6vw, 1.5rem);
 835		font-weight: 600;
 836		line-height: 1.35;
 837		letter-spacing: -0.015em;
 838		max-width: 40ch;
 839		margin-bottom: 0.75rem;
 840	}
 841
 842	.close-column {
 843		position: relative;
 844		background: var(--ptt);
 845	}
 846
 847	.close-mark {
 848		position: absolute;
 849		left: 3.7%;
 850		bottom: 12%;
 851		width: 91%;
 852		height: auto;
 853		mix-blend-mode: lighten;
 854	}
 855
 856	/* ——— Responsive ——— */
 857	@media (max-width: 1100px) {
 858		/* the postmark column only earns its place beside a wide hero */
 859		.hero,
 860		.close {
 861			grid-template-columns: 1fr;
 862		}
 863		.hero {
 864			min-height: 0;
 865		}
 866		.hero-column,
 867		.close-column {
 868			display: none;
 869		}
 870		.schedule,
 871		.ledger,
 872		.atmos {
 873			grid-template-columns: 1fr;
 874		}
 875		.schedule-head {
 876			position: static;
 877		}
 878		.exchange {
 879			justify-self: start;
 880		}
 881		.region {
 882			grid-template-columns: 1fr;
 883		}
 884		.region-plate {
 885			padding-bottom: 0;
 886		}
 887		.region :global(.hosting-map) {
 888			max-height: 40rem;
 889		}
 890	}
 891
 892	@media (max-width: 800px) {
 893		.region :global(.hosting-map) {
 894			outline-offset: 0.375rem;
 895		}
 896		.pledges {
 897			grid-template-columns: 1fr;
 898			padding-block: 1.75rem;
 899			gap: 1.25rem;
 900		}
 901		.chain {
 902			grid-template-columns: 1fr 3rem;
 903		}
 904		.schedule-row {
 905			grid-template-columns: 1fr;
 906		}
 907		.schedule-row dt {
 908			grid-row: auto;
 909		}
 910		.ledger-table thead {
 911			display: none;
 912		}
 913		.ledger-table,
 914		.ledger-table tbody,
 915		.ledger-table tr,
 916		.ledger-table th,
 917		.ledger-table td {
 918			display: block;
 919			width: auto;
 920		}
 921		.ledger-table tr {
 922			padding: 1.1rem 0;
 923			border-bottom: 1px solid color-mix(in srgb, var(--ptt-soft) 35%, transparent);
 924		}
 925		.ledger-table th,
 926		.ledger-table td {
 927			padding: 0.15rem 0;
 928			border: 0;
 929		}
 930		.ledger-table tbody th {
 931			width: auto;
 932			padding-bottom: 0.4rem;
 933		}
 934		.ledger-table td::before {
 935			display: block;
 936			font-size: 0.8125rem;
 937			font-weight: 700;
 938			color: var(--ptt-soft);
 939		}
 940		.ledger-table td:not(.ours)::before {
 941			content: 'Big-tech suite';
 942		}
 943		.ledger-table td.ours::before {
 944			content: 'sovrn';
 945			color: var(--gold);
 946		}
 947		.ledger-table td + td {
 948			margin-top: 0.5rem;
 949		}
 950		.routes {
 951			display: none;
 952		}
 953		/* mobile: a trunk runs down from the identity, one branch per line of work */
 954		.exchange-grid {
 955			display: flex;
 956			flex-direction: column;
 957			gap: 0.75rem;
 958			padding-left: 1.5rem;
 959			background: linear-gradient(var(--ptt-soft), var(--ptt-soft)) 0.5rem 0 / 2px calc(100% - 2.25rem) no-repeat;
 960		}
 961		.cell {
 962			position: relative;
 963			min-height: 0;
 964			padding: 0.85rem 1rem;
 965		}
 966		.cell::before {
 967			content: '';
 968			position: absolute;
 969			left: calc(-1rem - 1px);
 970			top: 50%;
 971			width: 1rem;
 972			height: 2px;
 973			background: var(--ptt-soft);
 974			transition: background-color 0.3s var(--ease-out), transform 0.3s var(--ease-out);
 975		}
 976		.cell.live::before {
 977			background: var(--gold);
 978		}
 979		.cell:not(.hub):is(:hover, :focus-visible)::before {
 980			background: var(--signal);
 981			transform: scaleY(2);
 982		}
 983		.cell.hub {
 984			order: -1;
 985			margin-left: -1.5rem;
 986		}
 987		.cell.hub::before {
 988			display: none;
 989		}
 990		.steps-list {
 991			grid-template-columns: 1fr;
 992		}
 993		.steps-list li,
 994		.steps-list li + li {
 995			padding: 1.75rem 0;
 996			border-left: 0;
 997			border-bottom: 1px solid var(--paper-rule);
 998		}
 999
1000	}
1001</style>