All checks were successful
PR checks / checks (pull_request) Successful in 8m25s
platform.json drops the single protocol/bundle/capability list for a `games` object (uo, rust) plus a `runicnpc` block. checkFacts.mjs loops the protocol, plugin-protocol, capability and bundle checks over both games, reads the schema-2 bundles at v2/<game>/current.json, checks each module's coreApi, and reads RunicNPC's plugin.toml. 41 facts, up from 19; clears the two that were red on main (Module API 1.17.0, installer v0.8.0). D66: the hero, footer and structured data show the Module API only; each game's protocol and bundle go on that game's pages, and the docs landing table splits into shared versions plus one column per game. The re-read section 1 requires found, and this fixes: - three hard-coded "1.6.0" Module API versions in the module docs - module-lifecycle saying modules load alphabetically (the loader now refuses a second module, W19), and the install pages never mentioning the one-module rule - "there is one module" in five places, now two modules both built inside this project; the Integration Kit keeps its draft banner - the homepage diagram's ServUO/uo-link sub-labels (D63 wording now) notBuilt drops `second-module` (resolved by Module-Rust's release) and rewords `multi-module`. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01E14m6SuuY6i1vASFeGDBeY
184 lines
5.9 KiB
Plaintext
184 lines
5.9 KiB
Plaintext
---
|
|
import { brand } from '../../lib/brand.mjs';
|
|
import platform from '../../data/platform.json';
|
|
|
|
/**
|
|
* The hero (PLAN.md §13 phase 3).
|
|
*
|
|
* The org lead chose an emblem hero over a type-only one: the mark carries recognition
|
|
* across the site, the Android launcher icon and the Play listing, and showing it large is
|
|
* what makes those three read as one product (D11, §11).
|
|
*
|
|
* It costs what D16 already accepted — the emblem is raster illustration, so a mounted
|
|
* `theme.css` recolours everything around it and not the mark itself. Replacing the mark
|
|
* means replacing `logo.png`, and because every size here is derived on request from
|
|
* whichever `logo.png` is in force (D14), that one file changes the hero, the header, the
|
|
* tab icon and the installed app icon together.
|
|
*
|
|
* The glow behind it is drawn in CSS from the portal tokens, so it DOES follow a mounted
|
|
* theme. That is deliberate: the part that can track the operator's palette does.
|
|
*
|
|
* The <h1> is the tagline rather than the product name. The name is in the header, in the
|
|
* page title and in the footer; a visitor who has just arrived needs the sentence more than
|
|
* the noun. Both strings are brand fields, rewritten at boot by `applyBrand.mjs` (D15).
|
|
*/
|
|
---
|
|
|
|
<section class="hero">
|
|
<div class="page hero__inner">
|
|
<div class="hero__copy">
|
|
<p class="eyebrow">Self-hosted community platform</p>
|
|
|
|
<h1>{brand.tagline}</h1>
|
|
|
|
<p class="hero__lede">
|
|
{brand.siteName} is a community website for a game server — accounts, teams, forums, a
|
|
wiki, news and a full admin panel — with a one-way bridge that puts the server's live
|
|
world on the public site. The game itself never listens on the internet.
|
|
</p>
|
|
|
|
<div class="hero__actions">
|
|
<a class="btn btn--primary" href="/docs/">Install it</a>
|
|
<a class="btn btn--ghost" href="/features/">See what it does</a>
|
|
|
|
{/*
|
|
The demo slot (§15 / D12). `global.css` hides `[data-demo-url='']`, so a stock
|
|
build renders nothing here; `applyBrand.mjs` fills both attributes at boot when a
|
|
mounted `brand.json` sets `demoUrl`, and the link appears.
|
|
|
|
The attribute pair is a literal contract with that script — `href` immediately
|
|
followed by `data-demo-url`, both empty, in this order. Astro preserves attribute
|
|
order, so what is written here is what ends up in the HTML it searches for. Do not
|
|
insert an attribute between them.
|
|
*/}
|
|
<a class="btn demo-cta" href="" data-demo-url="">See it running</a>
|
|
</div>
|
|
|
|
<div class="chips">
|
|
{/* D66: only the version every deployment shares. A protocol and a bundle belong
|
|
to a game, so they live on that game's pages rather than on the front door. */}
|
|
<span class="chip chip--version">Module API {platform.moduleApi}</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="hero__mark">
|
|
{/*
|
|
`alt=""` because the emblem is the product's mark sitting beside the product's own
|
|
sentence — announcing it would add nothing a reader of the <h1> does not have.
|
|
|
|
Sizes are on `brandAssets.mjs`'s allowlist; `checkBrand.mjs` puts every URL below
|
|
through the route's own classifier, so a plausible-but-underivable size fails the
|
|
build rather than 404ing in production.
|
|
*/}
|
|
<picture>
|
|
<source
|
|
type="image/avif"
|
|
srcset="/brand/logo-256.avif 256w, /brand/logo-384.avif 384w, /brand/logo-512.avif 512w"
|
|
sizes="(max-width: 900px) 176px, 320px"
|
|
/>
|
|
<img
|
|
src="/brand/logo-384.webp"
|
|
srcset="/brand/logo-256.webp 256w, /brand/logo-384.webp 384w, /brand/logo-512.webp 512w"
|
|
sizes="(max-width: 900px) 176px, 320px"
|
|
width="384"
|
|
height="384"
|
|
alt=""
|
|
fetchpriority="high"
|
|
decoding="async"
|
|
/>
|
|
</picture>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<style>
|
|
.hero {
|
|
position: relative;
|
|
overflow: hidden;
|
|
padding-block: clamp(2.5rem, 7vw, 5rem) clamp(2rem, 5vw, 3.5rem);
|
|
}
|
|
|
|
.hero__inner {
|
|
display: grid;
|
|
align-items: center;
|
|
gap: clamp(1.5rem, 5vw, 3.5rem);
|
|
grid-template-columns: minmax(0, 1fr) auto;
|
|
}
|
|
|
|
.hero__copy {
|
|
max-width: 40rem;
|
|
}
|
|
|
|
.hero h1 {
|
|
margin: 0;
|
|
color: var(--gold);
|
|
font-size: clamp(2.1rem, 5.2vw, 3.35rem);
|
|
}
|
|
|
|
.hero__lede {
|
|
margin: 1.15rem 0 0;
|
|
max-width: var(--measure);
|
|
color: var(--muted);
|
|
font-size: clamp(1rem, 1.6vw, 1.13rem);
|
|
}
|
|
|
|
.hero__actions {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
gap: 0.75rem;
|
|
margin-top: 1.9rem;
|
|
}
|
|
|
|
.hero .chips {
|
|
margin-top: 1.75rem;
|
|
}
|
|
|
|
/* ---- The mark ---------------------------------------------------------
|
|
The glow is a radial gradient mixed from the portal tokens rather than a
|
|
literal, so a mounted theme.css moves it with the rest of the palette.
|
|
It is behind the emblem and outside the flow, so it costs no layout. */
|
|
.hero__mark {
|
|
position: relative;
|
|
display: grid;
|
|
place-items: center;
|
|
}
|
|
|
|
.hero__mark::before {
|
|
content: '';
|
|
position: absolute;
|
|
z-index: 0;
|
|
inset: 50% auto auto 50%;
|
|
translate: -50% -50%;
|
|
width: 150%;
|
|
aspect-ratio: 1;
|
|
border-radius: var(--radius-pill);
|
|
background: radial-gradient(
|
|
circle,
|
|
color-mix(in srgb, var(--portal-deep) 34%, transparent) 0%,
|
|
color-mix(in srgb, var(--portal-deep) 8%, transparent) 45%,
|
|
transparent 68%
|
|
);
|
|
}
|
|
|
|
.hero__mark img {
|
|
position: relative;
|
|
z-index: 1;
|
|
display: block;
|
|
width: clamp(176px, 26vw, 320px);
|
|
height: auto;
|
|
}
|
|
|
|
@media (max-width: 900px) {
|
|
.hero__inner {
|
|
grid-template-columns: minmax(0, 1fr);
|
|
justify-items: start;
|
|
}
|
|
|
|
/* The mark leads on a narrow screen: it is the fastest thing to recognise,
|
|
and stacking it under the copy would push it below the fold entirely. */
|
|
.hero__mark {
|
|
order: -1;
|
|
}
|
|
}
|
|
</style>
|