boilerplate

This commit is contained in:
2026-05-23 12:15:03 -04:00
commit 554a88106f
10 changed files with 1174 additions and 0 deletions
+38
View File
@@ -0,0 +1,38 @@
# Spaces StartOS Guide
A simple, static setup-guide website for a fictional product called **Spaces on StartOS**. Built as a self-contained demo with boilerplate content and AI-generated placeholder screenshots.
## Structure
```
.
├── index.html # Single-page guide with sidebar TOC
├── styles.css # Styling (modern, responsive, light theme)
├── script.js # Scrollspy for the table-of-contents
├── images/ # Placeholder screenshots
└── README.md
```
## Running locally
No build step is required — open `index.html` in a browser, or serve the folder with any static server:
```bash
python3 -m http.server 8000
# then visit http://localhost:8000
```
## What's inside
The guide walks through:
1. Introduction to Spaces
2. Prerequisites
3. Installing StartOS
4. Configuring the instance
5. Creating your first Space
6. Verifying the installation
7. Troubleshooting
8. Next steps
All content, product details, and screenshots are illustrative.
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

+335
View File
@@ -0,0 +1,335 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content="The official setup guide for Spaces on StartOS — installation, configuration, and your first workspace." />
<title>Spaces StartOS Guide — Setup &amp; Configuration</title>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet" />
<link rel="stylesheet" href="styles.css" />
</head>
<body>
<header class="site-header">
<div class="container header-inner">
<a href="#top" class="brand" aria-label="Spaces StartOS Guide home">
<span class="brand-mark" aria-hidden="true">
<svg viewBox="0 0 32 32" width="28" height="28" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="2" y="2" width="28" height="28" rx="8" fill="url(#g)" />
<path d="M10 12.5C10 11.1193 11.1193 10 12.5 10H17C19.7614 10 22 12.2386 22 15V15C22 17.7614 19.7614 20 17 20H14V22.5C14 22.7761 13.7761 23 13.5 23H10.5C10.2239 23 10 22.7761 10 22.5V12.5Z" fill="white"/>
<defs>
<linearGradient id="g" x1="0" y1="0" x2="32" y2="32" gradientUnits="userSpaceOnUse">
<stop stop-color="#7C3AED"/>
<stop offset="1" stop-color="#4F46E5"/>
</linearGradient>
</defs>
</svg>
</span>
<span class="brand-text">
<span class="brand-name">Spaces</span>
<span class="brand-sub">StartOS Guide</span>
</span>
</a>
<nav class="top-nav" aria-label="Primary">
<a href="#introduction">Introduction</a>
<a href="#install">Install</a>
<a href="#configure">Configure</a>
<a href="#first-space">First Space</a>
<a href="#troubleshooting">Help</a>
</nav>
<a class="btn btn-outline btn-sm" href="#install">Get started →</a>
</div>
</header>
<main id="top">
<section class="hero">
<div class="container hero-inner">
<span class="eyebrow">Setup Guide · v2.4</span>
<h1>Get up and running with <span class="grad">Spaces</span> on StartOS</h1>
<p class="lead">
A step-by-step walkthrough to install StartOS, configure your environment, and
launch your first Space — typically in under ten minutes.
</p>
<div class="hero-actions">
<a class="btn btn-primary" href="#install">Start the setup</a>
<a class="btn btn-ghost" href="#introduction">Read the intro</a>
</div>
<ul class="hero-meta">
<li><span></span> ~10 minutes</li>
<li><span>💻</span> macOS · Linux · Windows</li>
<li><span>📦</span> No prior setup required</li>
</ul>
</div>
</section>
<div class="container layout">
<aside class="toc" aria-label="On this page">
<p class="toc-title">On this page</p>
<ol>
<li><a href="#introduction" class="active">Introduction</a></li>
<li><a href="#prerequisites">Prerequisites</a></li>
<li><a href="#install">1. Install StartOS</a></li>
<li><a href="#configure">2. Configure your instance</a></li>
<li><a href="#first-space">3. Create your first Space</a></li>
<li><a href="#verify">4. Verify the installation</a></li>
<li><a href="#troubleshooting">Troubleshooting</a></li>
<li><a href="#next-steps">Next steps</a></li>
</ol>
<div class="toc-card">
<p class="toc-card-title">Need a hand?</p>
<p class="toc-card-body">Reach the team in our community Slack or open a ticket — we usually respond within a business day.</p>
<a href="#" class="btn btn-outline btn-sm">Contact support</a>
</div>
</aside>
<article class="content">
<section id="introduction" class="doc-section">
<h2>Introduction</h2>
<p>
<strong>Spaces</strong> is the workspace layer of StartOS — a lightweight
runtime for organizing services, data, and collaborators into isolated
environments you can spin up, snapshot, and tear down on demand. Whether
you're prototyping a side project or operating a fleet of production
deployments, Spaces gives you a consistent, reproducible foundation.
</p>
<p>
This guide will walk you through installing StartOS, performing the initial
setup, and launching your first Space. By the end, you'll have a running
instance with one workspace ready for work.
</p>
<figure>
<img src="images/screenshot-dashboard.png" alt="StartOS Spaces dashboard showing the welcome screen with a Create Your First Space button" />
<figcaption>The StartOS dashboard after a fresh install.</figcaption>
</figure>
<div class="callout callout-info">
<strong>Heads up:</strong> StartOS is still moving fast. If something looks
different from a screenshot, check the version badge in the bottom-left
corner of the dashboard.
</div>
</section>
<section id="prerequisites" class="doc-section">
<h2>Prerequisites</h2>
<p>Before you begin, make sure you have:</p>
<ul class="check-list">
<li>A machine running macOS 12+, Ubuntu 20.04+, or Windows 10+ (with WSL2).</li>
<li>At least <strong>4 GB of RAM</strong> and <strong>10 GB of free disk space</strong>.</li>
<li>Administrator (sudo) access on the target machine.</li>
<li>Network access to <code>downloads.startos.example</code>.</li>
<li>A StartOS account — <a href="#">create one for free</a> if you don't have one.</li>
</ul>
</section>
<section id="install" class="doc-section">
<h2>1. Install StartOS</h2>
<p>
The fastest way to install StartOS is via the official installer. It
bundles the runtime, CLI, and a local control plane into a single setup
flow.
</p>
<h3>Download the installer</h3>
<p>Open a terminal and run the install script:</p>
<pre><code><span class="prompt">$</span> curl -fsSL https://get.startos.example | sh</code></pre>
<p>
The installer will detect your platform, fetch the appropriate package, and
guide you through a four-step wizard. When prompted, select
<strong>Standard Installation</strong> unless you have specific
infrastructure requirements.
</p>
<figure>
<img src="images/screenshot-install.png" alt="The StartOS installation wizard showing step 2 of 4, with Standard Installation selected" />
<figcaption>The installation wizard — step 2 of 4.</figcaption>
</figure>
<div class="callout callout-warn">
<strong>Tip:</strong> On Linux servers without a desktop environment, pass
<code>--headless</code> to skip the GUI wizard:
<code>sh -c "$(curl -fsSL https://get.startos.example) --headless"</code>.
</div>
</section>
<section id="configure" class="doc-section">
<h2>2. Configure your instance</h2>
<p>
Once StartOS is installed, open the dashboard at
<code>http://localhost:8080</code>. You'll be guided through a short
first-run configuration. Most users only need to set a hostname, choose a
port, and enable HTTPS.
</p>
<figure>
<img src="images/screenshot-config.png" alt="StartOS configuration page on the Networking tab, with hostname, port, HTTPS toggle, and domain fields" />
<figcaption>Configuring networking from the Settings panel.</figcaption>
</figure>
<h3>Recommended defaults</h3>
<div class="table-wrap">
<table>
<thead>
<tr>
<th>Setting</th>
<th>Recommended value</th>
<th>Notes</th>
</tr>
</thead>
<tbody>
<tr>
<td>Hostname</td>
<td><code>startos-spaces</code></td>
<td>Used for service discovery.</td>
</tr>
<tr>
<td>Port</td>
<td><code>8080</code></td>
<td>Change if another service is bound.</td>
</tr>
<tr>
<td>Enable HTTPS</td>
<td>On</td>
<td>StartOS will provision a self-signed cert.</td>
</tr>
<tr>
<td>Domain</td>
<td><code>spaces.example.com</code></td>
<td>Optional — leave blank for local-only access.</td>
</tr>
</tbody>
</table>
</div>
</section>
<section id="first-space" class="doc-section">
<h2>3. Create your first Space</h2>
<p>
From the dashboard, click <strong>Create Your First Space</strong>. Give
your Space a name, pick the region closest to you, and choose a resource
tier. The <em>Medium</em> tier is a good starting point for most projects.
</p>
<figure>
<img src="images/screenshot-create-space.png" alt="The Create New Space form with fields for name, region, resource tier, and tags" />
<figcaption>Creating a new Space takes about 30 seconds.</figcaption>
</figure>
<ol class="numbered">
<li><strong>Name your Space.</strong> Use something descriptive like <code>my-workspace</code> or <code>acme-prod</code>.</li>
<li><strong>Pick a region.</strong> Latency-sensitive workloads should run closest to their users.</li>
<li><strong>Choose a tier.</strong> You can resize the Space later without downtime.</li>
<li><strong>(Optional) Add tags.</strong> Tags make it easier to filter Spaces in larger teams.</li>
<li>Click <strong>Create Space</strong>. You'll be redirected to the Space's overview page.</li>
</ol>
<p>After a few moments, your Space will appear in the Spaces list with a green <strong>Running</strong> badge.</p>
<figure>
<img src="images/screenshot-spaces-list.png" alt="The Spaces list showing Production, Staging, and Development workspaces, all with Running status" />
<figcaption>Multiple Spaces, each with live CPU and memory metrics.</figcaption>
</figure>
</section>
<section id="verify" class="doc-section">
<h2>4. Verify the installation</h2>
<p>
From any terminal, you can confirm that StartOS is healthy and that all
services are reporting in:
</p>
<figure>
<img src="images/screenshot-terminal.png" alt="A terminal showing startos --version and startos status commands with healthy OK output for every service" />
<figcaption><code>startos status</code> should report every service as OK.</figcaption>
</figure>
<p>
If any service is in a <code>DEGRADED</code> or <code>DOWN</code> state, jump
to the <a href="#troubleshooting">Troubleshooting</a> section below.
</p>
</section>
<section id="troubleshooting" class="doc-section">
<h2>Troubleshooting</h2>
<details>
<summary>The installer fails with "port 8080 is in use"</summary>
<p>
Another service is already bound to port 8080. Either stop the
conflicting service or re-run the installer with
<code>--port 9090</code> to use a different port.
</p>
</details>
<details>
<summary>The dashboard won't load at <code>http://localhost:8080</code></summary>
<p>
Run <code>startos status</code> in a terminal. If the
<code>web</code> service is not reporting OK, restart it with
<code>startos restart web</code>.
</p>
</details>
<details>
<summary>I see "Permission denied" during install on Linux</summary>
<p>
The installer needs to write to <code>/usr/local/bin</code>. Re-run the
script with <code>sudo</code>, or specify a writable prefix with
<code>--prefix=$HOME/.local</code>.
</p>
</details>
<details>
<summary>My Space is stuck on "Provisioning"</summary>
<p>
Provisioning typically completes in under a minute. If it takes longer,
check the activity log on the Space's overview page. Most often this
indicates a temporary region capacity issue — try a different region.
</p>
</details>
</section>
<section id="next-steps" class="doc-section">
<h2>Next steps</h2>
<p>You're up and running. Here are some good places to go from here:</p>
<div class="cards">
<a href="#" class="card">
<h4>Deploy a service</h4>
<p>Drop a service into your Space from the template gallery.</p>
<span class="card-link">Browse templates →</span>
</a>
<a href="#" class="card">
<h4>Invite your team</h4>
<p>Add collaborators and set role-based permissions.</p>
<span class="card-link">Manage members →</span>
</a>
<a href="#" class="card">
<h4>Automate with the CLI</h4>
<p>Use the <code>startos</code> CLI to script common tasks.</p>
<span class="card-link">Read the CLI docs →</span>
</a>
</div>
</section>
</article>
</div>
</main>
<footer class="site-footer">
<div class="container footer-inner">
<div class="footer-brand">
<span class="brand-name">Spaces · StartOS Guide</span>
<p>A fictional setup guide built as a static-site demo.</p>
</div>
<div class="footer-links">
<a href="#introduction">Docs</a>
<a href="#troubleshooting">Help</a>
<a href="#">Changelog</a>
<a href="#">Status</a>
</div>
<p class="footer-meta">© 2026 StartOS Spaces · Made with care</p>
</div>
</footer>
<script src="script.js" defer></script>
</body>
</html>
+39
View File
@@ -0,0 +1,39 @@
(() => {
const tocLinks = Array.from(document.querySelectorAll('.toc a'));
if (tocLinks.length === 0) return;
const idToLink = new Map();
tocLinks.forEach((link) => {
const id = link.getAttribute('href').slice(1);
idToLink.set(id, link);
});
const sections = Array.from(document.querySelectorAll('.doc-section'));
const setActive = (id) => {
tocLinks.forEach((l) => l.classList.remove('active'));
const link = idToLink.get(id);
if (link) link.classList.add('active');
};
const observer = new IntersectionObserver(
(entries) => {
const visible = entries
.filter((entry) => entry.isIntersecting)
.sort((a, b) => a.target.getBoundingClientRect().top - b.target.getBoundingClientRect().top);
if (visible[0]) setActive(visible[0].target.id);
},
{
rootMargin: '-30% 0px -60% 0px',
threshold: 0,
}
);
sections.forEach((section) => observer.observe(section));
tocLinks.forEach((link) => {
link.addEventListener('click', () => {
setActive(link.getAttribute('href').slice(1));
});
});
})();
+762
View File
@@ -0,0 +1,762 @@
/* ============================================================
Spaces StartOS Guide — styles
============================================================ */
:root {
--bg: #fafafb;
--bg-elevated: #ffffff;
--bg-muted: #f4f4f7;
--border: #e6e6ec;
--border-strong: #d4d4dc;
--text: #1a1b2e;
--text-muted: #585a73;
--text-soft: #8a8ca0;
--primary: #6366f1;
--primary-dark: #4f46e5;
--primary-soft: #eef0ff;
--accent: #7c3aed;
--warn-bg: #fff8e6;
--warn-border: #f5d27a;
--info-bg: #eff6ff;
--info-border: #93c5fd;
--radius-sm: 6px;
--radius: 10px;
--radius-lg: 16px;
--shadow-sm: 0 1px 2px rgba(15, 17, 39, 0.04), 0 1px 1px rgba(15, 17, 39, 0.03);
--shadow-md: 0 4px 14px rgba(15, 17, 39, 0.06), 0 1px 3px rgba(15, 17, 39, 0.04);
--shadow-lg: 0 16px 40px rgba(15, 17, 39, 0.08), 0 4px 12px rgba(15, 17, 39, 0.04);
--font-sans: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
--font-mono: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
}
* {
box-sizing: border-box;
}
html {
scroll-behavior: smooth;
}
body {
margin: 0;
background: var(--bg);
color: var(--text);
font-family: var(--font-sans);
font-size: 16px;
line-height: 1.65;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
img {
max-width: 100%;
display: block;
}
a {
color: var(--primary-dark);
text-decoration: none;
}
a:hover {
color: var(--accent);
text-decoration: underline;
}
code {
font-family: var(--font-mono);
font-size: 0.88em;
padding: 0.15em 0.4em;
background: var(--bg-muted);
border-radius: 4px;
border: 1px solid var(--border);
color: #2d2f4a;
}
pre {
background: #0f1023;
color: #e8e8f6;
padding: 18px 22px;
border-radius: var(--radius);
overflow-x: auto;
font-family: var(--font-mono);
font-size: 14px;
line-height: 1.6;
box-shadow: var(--shadow-md);
}
pre code {
background: transparent;
border: 0;
padding: 0;
color: inherit;
font-size: inherit;
}
pre .prompt {
color: #8b9eff;
user-select: none;
margin-right: 0.5em;
}
.container {
width: 100%;
max-width: 1180px;
margin: 0 auto;
padding: 0 24px;
}
/* ---------- Header ---------- */
.site-header {
position: sticky;
top: 0;
z-index: 30;
background: rgba(255, 255, 255, 0.85);
backdrop-filter: saturate(150%) blur(10px);
-webkit-backdrop-filter: saturate(150%) blur(10px);
border-bottom: 1px solid var(--border);
}
.header-inner {
display: flex;
align-items: center;
justify-content: space-between;
gap: 24px;
padding: 14px 24px;
}
.brand {
display: inline-flex;
align-items: center;
gap: 12px;
color: var(--text);
}
.brand:hover {
text-decoration: none;
}
.brand-mark {
display: inline-flex;
align-items: center;
justify-content: center;
border-radius: 8px;
box-shadow: var(--shadow-sm);
}
.brand-text {
display: flex;
flex-direction: column;
line-height: 1.1;
}
.brand-name {
font-weight: 700;
font-size: 16px;
}
.brand-sub {
color: var(--text-soft);
font-size: 12px;
letter-spacing: 0.02em;
}
.top-nav {
display: flex;
gap: 28px;
}
.top-nav a {
color: var(--text-muted);
font-weight: 500;
font-size: 14.5px;
}
.top-nav a:hover {
color: var(--text);
text-decoration: none;
}
/* ---------- Buttons ---------- */
.btn {
display: inline-flex;
align-items: center;
justify-content: center;
gap: 6px;
padding: 11px 18px;
border-radius: var(--radius);
font-weight: 600;
font-size: 14.5px;
cursor: pointer;
border: 1px solid transparent;
transition: transform 80ms ease, background 160ms ease, color 160ms ease, border-color 160ms ease;
}
.btn:hover {
text-decoration: none;
transform: translateY(-1px);
}
.btn-sm {
padding: 7px 14px;
font-size: 13px;
}
.btn-primary {
background: linear-gradient(180deg, var(--primary), var(--primary-dark));
color: white;
box-shadow: 0 6px 16px rgba(99, 102, 241, 0.28);
}
.btn-primary:hover {
color: white;
box-shadow: 0 10px 24px rgba(99, 102, 241, 0.34);
}
.btn-outline {
background: white;
border-color: var(--border-strong);
color: var(--text);
}
.btn-outline:hover {
border-color: var(--primary);
color: var(--primary-dark);
}
.btn-ghost {
background: transparent;
color: var(--text);
}
.btn-ghost:hover {
background: var(--bg-muted);
color: var(--text);
}
/* ---------- Hero ---------- */
.hero {
padding: 72px 0 56px;
background:
radial-gradient(1200px 360px at 50% -10%, rgba(124, 58, 237, 0.12), transparent 60%),
radial-gradient(900px 320px at 10% 20%, rgba(99, 102, 241, 0.10), transparent 60%),
linear-gradient(180deg, #ffffff 0%, var(--bg) 100%);
border-bottom: 1px solid var(--border);
}
.hero-inner {
text-align: center;
}
.eyebrow {
display: inline-block;
padding: 5px 12px;
border-radius: 999px;
background: var(--primary-soft);
color: var(--primary-dark);
font-weight: 600;
font-size: 12.5px;
letter-spacing: 0.04em;
text-transform: uppercase;
margin-bottom: 18px;
}
.hero h1 {
font-size: clamp(34px, 5.5vw, 56px);
line-height: 1.08;
letter-spacing: -0.02em;
margin: 0 auto 18px;
max-width: 880px;
font-weight: 800;
}
.grad {
background: linear-gradient(90deg, #7c3aed, #6366f1 60%, #06b6d4);
-webkit-background-clip: text;
background-clip: text;
color: transparent;
}
.lead {
font-size: 18px;
color: var(--text-muted);
max-width: 680px;
margin: 0 auto 28px;
}
.hero-actions {
display: flex;
justify-content: center;
gap: 12px;
flex-wrap: wrap;
margin-bottom: 32px;
}
.hero-meta {
display: flex;
justify-content: center;
gap: 28px;
list-style: none;
padding: 0;
margin: 0;
color: var(--text-muted);
font-size: 14px;
flex-wrap: wrap;
}
.hero-meta li {
display: inline-flex;
align-items: center;
gap: 8px;
}
.hero-meta span {
font-size: 16px;
}
/* ---------- Layout ---------- */
.layout {
display: grid;
grid-template-columns: 260px 1fr;
gap: 56px;
padding: 56px 24px 96px;
align-items: start;
}
/* ---------- TOC ---------- */
.toc {
position: sticky;
top: 88px;
align-self: start;
font-size: 14px;
}
.toc-title {
text-transform: uppercase;
font-size: 12px;
font-weight: 700;
color: var(--text-soft);
letter-spacing: 0.08em;
margin: 0 0 12px;
}
.toc ol {
list-style: none;
padding: 0;
margin: 0 0 28px;
border-left: 1px solid var(--border);
}
.toc li {
margin: 0;
}
.toc a {
display: block;
padding: 7px 14px;
color: var(--text-muted);
border-left: 2px solid transparent;
margin-left: -1px;
transition: color 120ms ease, border-color 120ms ease, background 120ms ease;
}
.toc a:hover {
color: var(--text);
text-decoration: none;
background: var(--bg-muted);
}
.toc a.active {
color: var(--primary-dark);
border-left-color: var(--primary);
font-weight: 600;
}
.toc-card {
background: var(--bg-elevated);
border: 1px solid var(--border);
border-radius: var(--radius);
padding: 16px;
box-shadow: var(--shadow-sm);
}
.toc-card-title {
font-weight: 700;
font-size: 14px;
margin: 0 0 6px;
}
.toc-card-body {
color: var(--text-muted);
font-size: 13.5px;
margin: 0 0 12px;
line-height: 1.55;
}
/* ---------- Content ---------- */
.content {
min-width: 0;
}
.doc-section {
padding-bottom: 56px;
border-bottom: 1px solid var(--border);
margin-bottom: 56px;
scroll-margin-top: 96px;
}
.doc-section:last-child {
border-bottom: 0;
margin-bottom: 0;
}
.doc-section h2 {
font-size: 30px;
letter-spacing: -0.01em;
margin: 0 0 18px;
font-weight: 700;
}
.doc-section h3 {
font-size: 20px;
margin: 32px 0 12px;
font-weight: 700;
}
.doc-section p,
.doc-section ul,
.doc-section ol {
color: #2c2e44;
}
.doc-section p {
margin: 0 0 16px;
}
.check-list,
.numbered {
padding-left: 0;
list-style: none;
}
.check-list li {
position: relative;
padding: 6px 0 6px 30px;
}
.check-list li::before {
content: "";
position: absolute;
left: 0;
top: 13px;
width: 18px;
height: 18px;
border-radius: 50%;
background: var(--primary-soft) url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'><path fill='none' stroke='%234f46e5' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' d='M2 6.5l2.6 2.6L10 3'/></svg>") center / 12px no-repeat;
}
.numbered {
counter-reset: step;
}
.numbered > li {
counter-increment: step;
position: relative;
padding: 6px 0 6px 42px;
margin-bottom: 4px;
}
.numbered > li::before {
content: counter(step);
position: absolute;
left: 0;
top: 6px;
width: 26px;
height: 26px;
border-radius: 50%;
background: var(--primary);
color: white;
font-weight: 700;
font-size: 13px;
display: inline-flex;
align-items: center;
justify-content: center;
}
/* Figures */
figure {
margin: 24px 0 28px;
}
figure img {
width: 100%;
border-radius: var(--radius);
border: 1px solid var(--border);
box-shadow: var(--shadow-md);
}
figcaption {
margin-top: 10px;
color: var(--text-soft);
font-size: 13.5px;
text-align: center;
font-style: italic;
}
/* Callouts */
.callout {
border: 1px solid var(--border);
border-left-width: 4px;
border-radius: var(--radius);
padding: 14px 18px;
margin: 20px 0;
font-size: 15px;
line-height: 1.6;
background: var(--bg-elevated);
}
.callout strong {
margin-right: 4px;
}
.callout-info {
background: var(--info-bg);
border-color: var(--info-border);
}
.callout-warn {
background: var(--warn-bg);
border-color: var(--warn-border);
}
/* Tables */
.table-wrap {
overflow-x: auto;
border: 1px solid var(--border);
border-radius: var(--radius);
margin: 16px 0 24px;
background: var(--bg-elevated);
}
table {
width: 100%;
border-collapse: collapse;
font-size: 14.5px;
}
thead {
background: var(--bg-muted);
}
th,
td {
text-align: left;
padding: 12px 16px;
border-bottom: 1px solid var(--border);
}
tbody tr:last-child td {
border-bottom: 0;
}
th {
font-weight: 700;
color: var(--text);
font-size: 13px;
text-transform: uppercase;
letter-spacing: 0.04em;
}
/* Details (FAQ) */
details {
border: 1px solid var(--border);
border-radius: var(--radius);
padding: 0;
margin: 12px 0;
background: var(--bg-elevated);
box-shadow: var(--shadow-sm);
overflow: hidden;
}
details summary {
list-style: none;
cursor: pointer;
padding: 14px 18px;
font-weight: 600;
color: var(--text);
position: relative;
padding-right: 44px;
user-select: none;
}
details summary::-webkit-details-marker {
display: none;
}
details summary::after {
content: "+";
position: absolute;
right: 18px;
top: 50%;
transform: translateY(-50%);
width: 22px;
height: 22px;
border-radius: 50%;
background: var(--primary-soft);
color: var(--primary-dark);
text-align: center;
line-height: 22px;
font-weight: 700;
transition: transform 160ms ease;
}
details[open] summary::after {
content: "";
}
details p {
padding: 0 18px 16px;
margin: 0;
color: var(--text-muted);
}
/* Next-step cards */
.cards {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
gap: 16px;
margin-top: 18px;
}
.card {
display: block;
background: var(--bg-elevated);
border: 1px solid var(--border);
border-radius: var(--radius);
padding: 20px;
color: var(--text);
box-shadow: var(--shadow-sm);
transition: transform 120ms ease, box-shadow 160ms ease, border-color 160ms ease;
}
.card:hover {
text-decoration: none;
transform: translateY(-2px);
border-color: var(--primary);
box-shadow: var(--shadow-md);
}
.card h4 {
margin: 0 0 6px;
font-size: 16px;
font-weight: 700;
}
.card p {
margin: 0 0 12px;
color: var(--text-muted);
font-size: 14px;
}
.card-link {
color: var(--primary-dark);
font-weight: 600;
font-size: 13.5px;
}
/* ---------- Footer ---------- */
.site-footer {
border-top: 1px solid var(--border);
background: var(--bg-elevated);
padding: 40px 0 56px;
}
.footer-inner {
display: grid;
grid-template-columns: 1fr auto;
align-items: center;
gap: 24px;
}
.footer-brand p {
margin: 4px 0 0;
color: var(--text-soft);
font-size: 13.5px;
}
.footer-links {
display: flex;
gap: 24px;
}
.footer-links a {
color: var(--text-muted);
font-size: 14px;
}
.footer-meta {
grid-column: 1 / -1;
color: var(--text-soft);
font-size: 13px;
margin: 16px 0 0;
}
/* ---------- Responsive ---------- */
@media (max-width: 960px) {
.layout {
grid-template-columns: 1fr;
gap: 24px;
padding-top: 32px;
}
.toc {
position: static;
order: 2;
}
.content {
order: 1;
}
.top-nav {
display: none;
}
}
@media (max-width: 560px) {
.hero {
padding: 48px 0 36px;
}
.hero-meta {
gap: 14px;
font-size: 13.5px;
}
.doc-section h2 {
font-size: 24px;
}
.footer-inner {
grid-template-columns: 1fr;
text-align: left;
}
}