1
0

feat: add field-guide landing page and agentic-environment guide

This commit is contained in:
Pouya
2026-06-04 16:31:18 +02:00
parent 0ab003ec84
commit d403aa0467
3 changed files with 2452 additions and 0 deletions
+227
View File
@@ -0,0 +1,227 @@
# Agentic Environment — Bootstrap Instructions for Claude Code
> **You are Claude Code. A user has handed you this document to set up a personal, multi-domain "agentic environment" from scratch.**
> Your job is to (1) understand the architecture below, (2) **interview the user** to capture *their* domains, stack, conventions, and guardrails, then (3) **scaffold a clean, greenfield setup** for them — committing as you go.
>
> This is a *clean-room* design. Do **not** import any one person's accumulated tech debt. Build it right from day one: committed + backed up, self-describing, no dead config, security and governance baked in. Adapt every concrete detail to the user via the interview — the patterns are fixed, the specifics are theirs.
---
## 0. How to use this document
**User:** place this file where your Claude Code can read it, then say: *"Read agentic-setup-bootstrap.md and set up my agentic environment."*
**Claude Code:** Work through this in order — **Principles → Interview → Scaffold → Phased rollout**. Do not scaffold before interviewing. Show the user a plan and get approval before writing files. Commit after each coherent step. Never invent the user's conventions — ask.
---
## 1. What you're building (the mental model)
A **source-of-truth git repo** (call it `agentic-dev/` or similar) that is **symlinked into `~/.claude/`**, containing:
```
agentic-dev/
├── agents/<name>.md # expert subagents (focused roles)
├── skills/<name>/SKILL.md # auto-triggering capabilities
├── commands/<name>.md # slash commands (explicit workflows)
├── agent-memory/<name>/ # each agent's persistent memory (MEMORY.md index + notes)
├── shared-knowledge/ # facts referenced by multiple agents
├── hooks/ # lifecycle scripts (session start, capture, etc.)
├── githooks/pre-commit # secret-scan gate
├── sync.sh / uninstall.sh # symlink installer/remover
├── manifest.* (generated) # the system's accurate self-description
├── CLAUDE.md # global governance rules (always loaded)
└── README.md
```
The repo is the truth; `~/.claude/` is a set of symlinks into it. Edit the repo → it's live. This makes the whole environment **versioned, reviewable, revertible, and portable across machines**.
### The five pillars
1. **Expert subagents** — narrow, role-scoped agents with their own memory and tool permissions, instead of one do-everything prompt.
2. **Layered memory***semantic* (current facts), *episodic* (what happened / a decision journal), *procedural* (skills/checklists), with explicit time-awareness so it doesn't silently rot.
3. **Governance** — hard rules that always load: no silent behavioral change, secret hygiene, human-approval gates for anything risky.
4. **The self-improving loop** — agents capture friction → a periodic human-triggered review coaches them → they get sharper. Compounding capability, no daemon.
5. **Grounding** — agents observe reality (repos, and optionally live systems via MCP) rather than guessing, with the blast radius the user is comfortable with.
---
## 2. Design principles (these are fixed — do not compromise them)
- **Committed + backed up from commit #1.** `git init`, add a remote, push. Never let the source-of-truth live only as uncommitted local files.
- **Self-describing, never lying.** Generate the manifest (counts/inventory of agents/skills/commands) from disk; never hand-maintain a number that will drift.
- **No dead config.** Every agent in `agents/` must be a registered, reachable agent type. Every skill must trigger. If it isn't used, remove it — don't accrete.
- **Read-only by default; write is a privilege.** Agents that *analyze* (auditors, critics, planners, the reviewer) get non-mutating tools only. Agents that *change things* get write tools and a tighter leash.
- **Reviewer ≠ applier.** The agent that decides *what* to change never also *applies* it unattended. Propose → human approves the literal diff → a separate step applies + commits.
- **Memory captures the non-derivable.** Don't store what's re-readable from code/docs. Store hard-won facts: quirks, gotchas, decisions, "we tried X, it failed because Y." Notes record their own deprecations.
- **Episodic ≠ boot-loaded.** The decision/retro journal is read *on demand* (at review), never loaded into every agent's startup context — or it bloats and dilutes the high-signal rules.
- **Human-triggered autonomy only** (per this user's class of setup): nudges and scheduled *reminders* are fine; unattended self-modifying action is not.
- **Governance > convenience.** When a fix would also change behavior the user can observe, stop and surface options; never silently "improve."
### Anti-patterns to actively avoid (the tech debt that kills these systems)
- Source-of-truth repo with **no remote** and a pile of uncommitted changes → one bad `git` command from total loss.
- **Hand-maintained snapshots** (topology docs, project lists, counts) that rot silently while reality moves on.
- **Self-description that lies** ("7 agents" when there are 8) → mis-routes work, hides capabilities.
- **Orphaned/dead agents** referenced everywhere but never actually invocable.
- **Capture without review** → a journal that grows forever and is never read = "dormancy with a token tax."
- **Self-graded retros** ("everything went great") = landfill. The gold is the *human's correction*.
---
## 3. The interview (run this WITH the user before building anything)
Capture answers into `shared-knowledge/profile.md` as you go. Teach while you ask — the user may be newer than this document assumes.
**A. Domains & priorities**
1. Which domains do you want agents for? (e.g. homelab/infra ops, software development, UI/UX, product/idea development, research/consultation, writing, data.) Rank them.
2. For each domain: what does a *good outcome* look like? What recurring task or pain motivated this?
**B. Stack & conventions (per domain)**
3. What's your actual stack in each domain? (OS, languages/frameworks, infra platform, container runtime, git host, CI, deployment style.) — *Do not assume; this is where their setup differs from any template.*
4. Any house conventions you want enforced? (file layout, naming, commit format, code style, where things get deployed.)
5. Where does your code/config live (paths, repos)? What should agents be allowed to read vs. never touch?
**C. Risk & access posture**
6. For infra/ops: do you want agents to **act** (make changes, run commands, SSH) or only **advise** (read + propose)? Start advisory unless the user is confident.
7. Do you want any **live-system grounding** (MCP servers for metrics/SSH/browser/GitHub), or repo-only to start? Default repo-only; add grounding deliberately.
8. Always-on / scheduled autonomy: usually **no** — confirm. Reminders and human-triggered reviews only?
**D. Guardrails & secrets**
9. Your secrets policy: which files/paths must never be read? How should a leaked secret be handled if one is seen?
10. Any hard "never do this" rules? (e.g. never modify the host package manager, never force-push, never change behavior without asking.)
**E. Cost/quality**
11. What's your model budget posture? (Subscription vs API; tolerance for using the strongest model.) This sets the model tiering (§5).
**F. Self-improving loop**
12. Do you want the learning loop (capture friction → periodic review → coaching)? Explain the dormancy risk honestly. If yes, what review cadence feels realistic?
Summarize the captured profile back to the user and confirm before scaffolding.
---
## 4. Scaffold procedure (build in this order; commit after each)
### Step 1 — Foundation
- `git init`; create the repo structure (§1).
- Add a **remote** and push immediately. Confirm the remote is **private** if anything sensitive may land there.
- `.gitignore`: exclude the episodic journal (`agent-memory/_journal/`), local overrides, OS cruft.
- `githooks/pre-commit`: a **blocking** secret scanner (gitleaks-class) on staged memory/skill/journal files; `git config core.hooksPath githooks`. Install the scanner per the user's OS (ask; respect immutable-OS constraints if any).
- `CLAUDE.md` (global governance — see §6).
- `sync.sh` (symlink repo → `~/.claude/`, idempotent, prunes orphaned links, dry-run flag) + matching `uninstall.sh`.
- A **manifest generator** (small script) that writes `manifest.md` from disk so counts never drift; wire it into `sync.sh`.
### Step 2 — The agent roster (generic archetypes → instantiate per the user's domains)
Create only the agents the interview justified. For each agent file (`agents/<name>.md`) set frontmatter: `name`, `description` (when to invoke — be specific, this drives auto-delegation), `tools` (scope tightly), `model` (per §5). Seed each with a starter memory note.
Recommended archetypes (rename/drop to fit):
| Archetype | Mode | Purpose |
|---|---|---|
| **infra/ops expert** | RO→RW (user's choice) | the user's infra platform; conventions, deploy patterns |
| **dev expert(s)** | RW | per primary language/framework; build/test conventions |
| **UI/UX designer** | RW | interfaces; reads existing design system before inventing |
| **security-auditor** | read-only | OWASP-style review, secrets, misconfig; never edits |
| **devil's-advocate** | read-only | stress-tests plans; no false critique |
| **product/idea partner** | read-only | clarifies value, sequences by impact, fights scope creep |
| **remediation-planner** | read-only | turns audit findings into a sequenced, validated fix plan |
| **engineering-manager** | read-only-proposing | runs the self-improving review (§7); proposes, never applies |
Rules: read-only agents get `Read, Grep, Glob, Bash`(non-mutating). RW agents get edit/write but inherit the governance rules. The auditor, critic, planner, product, and engineering-manager are **always read-only**.
### Step 3 — Skills & commands
- **Skills** (`skills/<name>/SKILL.md`): auto-trigger on context (e.g. "editing a Dockerfile" → compose skill). Thin wrappers that load domain conventions.
- **Commands** (`commands/<name>.md`): explicit workflows. Useful starters: `/audit-all` (fan-out review → aggregate), a remediation flow (audit → human → separate applier), `/note` and `/eng-review` (§7).
### Step 4 — Shared knowledge
- `shared-knowledge/profile.md` (the interview output) and any cross-agent facts (topology, domains, conventions). **Prefer generated over hand-maintained**; if hand-maintained, stamp `last_verified` and have an agent reconcile it on demand.
### Step 5 — Memory seeding
- For each agent: `agent-memory/<name>/MEMORY.md` = a flat index of one-line pointers to detail notes. Seed 24 starter notes from the interview (conventions, guardrails, known gotchas). Keep a per-agent size budget.
### Step 6 — Optional grounding (only if the user opted in)
- MCP servers for the chosen surfaces (GitHub, browser/Playwright for UI, metrics/SSH for infra). Scope credentials tightly. Repo-only is a fine starting posture.
---
## 5. Model tiering (cost vs. capability)
Match model strength to the *judgment* each step needs, not to importance:
| Work | Model tier | Why |
|---|---|---|
| Counting/format/file ops, nudges | **none** (scripts) | zero cost; can't be "dumb" |
| High-frequency mechanical capture | **cheapest model** (Haiku-class) | short, structured, low-stakes |
| Routine coding/analysis | **mid model** (Sonnet-class) | the workhorse |
| High-judgment review, security, architecture, **editing instructions** | **strongest model** (Opus-class), used sparingly | mistakes here compound |
Make the **frequent** things cheap or model-free, and reserve the strongest model for **infrequent, high-stakes judgment** (the periodic review, security audits, design). Set `model:` in each agent's frontmatter accordingly.
---
## 6. Governance (`CLAUDE.md` — always loaded, non-negotiable)
Draft this WITH the user; it must include at minimum:
- **No silent behavioral change.** A fix may only fix the reported problem. Anything that changes observable behavior, disables a feature, swaps a design choice, or changes defaults is OFF-LIMITS without explicit prior approval — even if "obviously better." Surface options, wait for approval, implement only what was approved.
- **Secret hygiene.** Never read files likely to contain secrets (`.env`, `*secret*`, `*token*`, credentials, vaults). If a secret is seen anyway (by you or a subagent), **immediately and prominently** tell the user, name what leaked, and prompt rotation. Pass this rule into every subagent brief.
- **Human-approval gates.** Destructive, outward-facing, or hard-to-reverse actions require confirmation. Approval in one context doesn't extend to the next.
- **Honesty.** Report outcomes faithfully — failed tests, skipped steps, uncertainty — without hedging or false confidence.
- The user's own hard "never" rules from interview Q10.
---
## 7. The self-improving loop (first-class, but done right)
A human-triggered loop that makes agents compound capability over time. **No daemon. No auto-apply. No self-grading landfill.**
### Components
1. **`/note` command** — the user fires it the moment an agent gets something wrong: appends one ground-truth line `{agent, what was wrong, the fix}` to a **local-only** journal (`agent-memory/_journal/YYYY-MM.md`). Human-authored = highest signal, zero per-run cost.
2. **Friction-only auto-capture** (add *after* the review loop is proven to run): a directive that makes each subagent emit a `## Mini-Retro` block **only when there was friction** (a fact it had to discover that should've been in memory, a stale note, a missing skill, a human correction) — silence on clean success. A `SubagentStop` hook parses + appends it. Rides on the subagent's own model → near-zero added cost.
3. **SessionStart nudge** — a **fail-open** script (no model) that prints one line: `N unreviewed retros since <date> — run /eng-review`, escalating by count/age. This is the forcing function that fights dormancy without a daemon.
4. **`engineering-manager` agent + `/eng-review`** — periodic, human-run. Reads the journal, clusters by agent + recurring theme, and **proposes coaching as literal diffs** (new/updated skills, memory edits, instruction tweaks, **deletions of stale notes**). It is **read-only-proposing**. The user approves specific diffs; a **separate** step applies + commits with a note on what behavior changed.
5. **Skill distillation** — recurring *trusted* patterns become a proposed `SKILL.md`, ratified at review, never auto-applied.
### Mandatory security controls (the loop is a self-modifying-instructions pipeline — these are not optional)
- **No auto-apply.** The user reviews the **literal diff**, never a summary, before anything is written to `agents/`, `skills/`, `agent-memory/`, `shared-knowledge/`.
- **Reviewer ≠ applier.** The engineering-manager has no write/commit tools.
- **Provenance tagging.** Every retro records whether the content the agent saw was *trusted* (the user's own repos/config) or *untrusted* (third-party code, audited targets, remote content). Proposals derived from untrusted content are **quarantined** — shown as flagged quotes, never auto-distilled into instructions. (A malicious README an agent audited must not be able to write itself into an agent's permanent instructions.)
- **Observations ≠ instructions.** The journal stores escaped, quoted *observations*, never imperatives a future agent will obey. Neutralize directive-shaped text captured from targets.
- **Redaction + the secret-scan pre-commit gate** apply to everything the loop writes. Journal stays **local-only** unless the user explicitly opts into committing it (then only behind the scan gate).
- **Hooks never interpolate model output into a shell command.** Pass payloads via stdin/temp-file to a non-shell handler; schema-validate, size-cap, fence-escape. Hooks must **fail open** (never block a session) — they're global blast radius.
- **Governance surface is privileged.** Proposed edits to the engineering-manager's own prompt, the auditor's rules, the secret policy, or the redaction/gate logic are a separate highest-attention review category — never silently applied or pruned.
### Phased rollout (do NOT build it all at once)
- **Phase 1:** `/note` + SessionStart nudge + engineering-manager + `/eng-review`. Prove the user actually runs the review.
- **Phase 2:** add friction-only `SubagentStop` auto-capture *after* `/eng-review` has run ≥2×. (Prove you'll review before you pay to capture.)
- **Phase 3:** skill distillation + a crude "did the coaching help?" check (did the friction recur?) + per-agent memory budgets.
### Must-verify before relying on hooks (don't assume — check current behavior)
- Does `SubagentStop` fire for *all* subagent kinds the user spawns (including any orchestrated/workflow agents)?
- Does it fire reliably on long sessions?
- Are concurrent hook appends serialized, or do parallel agents race on the journal? (Use a lock or per-agent temp files.)
- Does SessionStart fire reliably after resume/clear?
- Confirm a hung/erroring hook cannot block session start in *any* project.
---
## 8. Sequencing summary (what to actually do, in order)
1. **Interview** (§3) → confirm captured profile.
2. **Foundation** (§4.1): repo + remote + secret-scan + CLAUDE.md + sync.sh + manifest. Commit & push.
3. **23 highest-priority agents** (not all at once) + their memory seeds. Use them for real for a bit.
4. **Skills/commands** for those domains; `/audit-all` + remediation flow if relevant.
5. **Self-improving loop Phase 1** (§7) once there are agents worth coaching.
6. **Grounding (MCP)** only if/when repo-only proves limiting.
7. **Expand** domains and the loop's later phases as the system earns it.
> Build the smallest thing that's genuinely useful, use it, and let real friction tell you what to add next. A lean environment that's actually used beats a comprehensive one that rots.
---
## 9. Health checklist (keep it from rotting)
- [ ] Repo committed + pushed; no long-lived uncommitted source-of-truth.
- [ ] Manifest matches reality (generated, not hand-typed).
- [ ] Every agent is reachable; no dead config.
- [ ] Hand-maintained docs carry `last_verified` and get reconciled.
- [ ] The review loop is actually being run (the nudge isn't being ignored).
- [ ] Memory isn't bloating boot context; stale notes get pruned at review.
- [ ] Secret-scan gate is active on every commit path.
File diff suppressed because it is too large Load Diff
+860
View File
@@ -0,0 +1,860 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Field Guides — Plain-English Tutorials</title>
<meta name="description" content="A small library of plain-English field guides for people who don't (and shouldn't have to) think about tech all day. Start with the guide to password managers and Bitwarden.">
<style>
/* =========================================================================
FIELD GUIDES — INDEX / COVER (single-file, standalone draft)
Direction: editorial engineering field-guide cover. Reuses the established
password-guide design system VERBATIM: cool lavender-paper / midnight-indigo
palette, violet-indigo signature accent (#6d4aff light / #8c6bff dark),
Georgia display serif + system sans body + ui-monospace labels, faint
engineering grid, inline-SVG art, calm single reveal.
Semantic colour language: good = teal · bad = red · warn = amber
accent = violet/indigo (the signature move)
Theme: respects prefers-color-scheme; an explicit toggle overrides via
:root[data-theme] and persists to the SAME localStorage key as the guide
('pwguide-theme') so the choice carries across the whole site.
========================================================================= */
:root{
/* --- light: cool lavender paper, navy ink, violet/indigo signature ------ */
--bg: #eef0fb;
--bg-grain: #e4e6f7;
--surface: #f7f8ff;
--surface-2: #eaecf9;
--ink: #15172b;
--ink-soft: #383b58;
--muted: #5d6080;
--faint: #8b8ead;
--border: #d4d6ee;
--border-strong: #bfc1e3;
--rule: #cdcfeb;
--accent: #6d4aff; /* violet/indigo signature */
--accent-ink: #5634d6;
--accent-wash: #e4ddff;
--good: #0f7a73; /* teal */
--good-wash: #d4ece9;
--bad: #d62828; /* danger red */
--bad-wash: #f7dcdc;
--warn: #b06a00; /* amber-bronze warn (kept warm for semantics) */
--warn-wash: #f6e7cd;
--slate: #3f5180; /* neutral / domain */
--slate-wash: #dde2f1;
--shadow: 0 1px 0 rgba(21,23,43,.04), 0 10px 30px -22px rgba(21,23,43,.45);
--shadow-lift: 0 2px 0 rgba(21,23,43,.05), 0 24px 50px -28px rgba(21,23,43,.5);
--serif: Georgia, "Iowan Old Style", "Palatino Linotype", "Times New Roman", serif;
--sans: -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, "Helvetica Neue", sans-serif;
--mono: ui-monospace, "SF Mono", "Cascadia Code", "JetBrains Mono", "Menlo", "Consolas", monospace;
--step--1: clamp(.78rem, .76rem + .12vw, .85rem);
--step-0: clamp(.95rem, .92rem + .2vw, 1.05rem);
--step-1: clamp(1.15rem, 1.05rem + .4vw, 1.4rem);
--step-2: clamp(1.5rem, 1.3rem + .8vw, 2rem);
--step-3: clamp(2rem, 1.6rem + 1.6vw, 3rem);
--step-4: clamp(2.6rem, 2rem + 3vw, 4.4rem);
--maxw: 1080px;
--gap: clamp(1.5rem, 1rem + 2vw, 3rem);
}
/* ----- dark palette, applied both by system default and explicit toggle -- */
@media (prefers-color-scheme: dark){
:root:not([data-theme="light"]){
--bg: #0c0e1c;
--bg-grain: #12152a;
--surface: #161a32;
--surface-2: #1e2240;
--ink: #eceefb;
--ink-soft: #c4c8e6;
--muted: #9094bd;
--faint: #62668c;
--border: #2a2f52;
--border-strong: #3a4068;
--rule: #232845;
--accent: #8c6bff;
--accent-ink: #a78cff;
--accent-wash: #241d4a;
--good: #46c2b6;
--good-wash: #102e2a;
--bad: #ff6b6b;
--bad-wash: #3a1b1f;
--warn: #e0a64a;
--warn-wash: #392b16;
--slate: #9aa9d6;
--slate-wash: #1c2240;
--shadow: 0 1px 0 rgba(0,0,0,.4), 0 14px 36px -24px rgba(0,0,0,.9);
--shadow-lift: 0 2px 0 rgba(0,0,0,.5), 0 30px 60px -30px rgba(0,0,0,.95);
}
}
:root[data-theme="dark"]{
--bg: #0c0e1c;
--bg-grain: #12152a;
--surface: #161a32;
--surface-2: #1e2240;
--ink: #eceefb;
--ink-soft: #c4c8e6;
--muted: #9094bd;
--faint: #62668c;
--border: #2a2f52;
--border-strong: #3a4068;
--rule: #232845;
--accent: #8c6bff;
--accent-ink: #a78cff;
--accent-wash: #241d4a;
--good: #46c2b6;
--good-wash: #102e2a;
--bad: #ff6b6b;
--bad-wash: #3a1b1f;
--warn: #e0a64a;
--warn-wash: #392b16;
--slate: #9aa9d6;
--slate-wash: #1c2240;
--shadow: 0 1px 0 rgba(0,0,0,.4), 0 14px 36px -24px rgba(0,0,0,.9);
--shadow-lift: 0 2px 0 rgba(0,0,0,.5), 0 30px 60px -30px rgba(0,0,0,.95);
}
*{box-sizing:border-box}
html{-webkit-text-size-adjust:100%;scroll-behavior:smooth}
@media (prefers-reduced-motion: reduce){html{scroll-behavior:auto}}
body{
margin:0;
background:
radial-gradient(120% 80% at 100% 0%, var(--bg-grain) 0%, transparent 55%),
var(--bg);
color:var(--ink);
font-family:var(--sans);
font-size:var(--step-0);
line-height:1.6;
letter-spacing:.005em;
-webkit-font-smoothing:antialiased;
text-rendering:optimizeLegibility;
}
::selection{background:var(--accent);color:#fff}
:root[data-theme="dark"] ::selection{color:#fff}
@media (prefers-color-scheme: dark){:root:not([data-theme="light"]) ::selection{color:#fff}}
a{color:var(--accent-ink);text-underline-offset:.18em}
:focus-visible{outline:2.5px solid var(--accent);outline-offset:3px;border-radius:3px}
.wrap{max-width:var(--maxw);margin:0 auto;padding:0 clamp(1.1rem,4vw,3rem)}
/* faint engineering grid behind everything */
body::before{
content:"";position:fixed;inset:0;z-index:-1;pointer-events:none;
background-image:
linear-gradient(to right, var(--rule) 1px, transparent 1px),
linear-gradient(to bottom, var(--rule) 1px, transparent 1px);
background-size:46px 46px;
opacity:.22;
mask-image:radial-gradient(120% 90% at 50% 0%, #000 10%, transparent 80%);
-webkit-mask-image:radial-gradient(120% 90% at 50% 0%, #000 10%, transparent 80%);
}
/* skip link */
.skip{position:absolute;top:0;left:0;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;
clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap;border:0}
.skip:focus{width:auto;height:auto;margin:0;overflow:visible;clip:auto;clip-path:none;
inset-inline-start:1rem;top:1rem;z-index:50;background:var(--ink);color:var(--bg);
padding:.6rem 1rem;border-radius:6px;font-family:var(--mono);font-size:var(--step--1)}
/* ---- type helpers ------------------------------------------------------- */
.mono{font-family:var(--mono)}
.num{font-family:var(--mono);font-variant-numeric:tabular-nums lining-nums}
.kicker{
font-family:var(--mono);font-size:var(--step--1);
letter-spacing:.22em;text-transform:uppercase;color:var(--accent);font-weight:600;
}
h1,h2,h3,h4{font-family:var(--serif);font-weight:700;line-height:1.06;letter-spacing:-.01em}
code{font-family:var(--mono);font-size:.88em;background:var(--surface-2);
padding:.06em .36em;border-radius:4px;color:var(--accent-ink);border:1px solid var(--border)}
/* =========================================================================
MASTHEAD — editorial cover treatment
========================================================================= */
.masthead{position:relative;padding:clamp(2.4rem,6vw,5rem) 0 0}
.masthead .topline{
display:flex;flex-wrap:wrap;gap:.6rem 1.4rem;align-items:baseline;
font-family:var(--mono);font-size:var(--step--1);
color:var(--muted);letter-spacing:.04em;
border-bottom:1px solid var(--border-strong);
padding-bottom:.9rem;margin-bottom:clamp(1.6rem,4vw,2.8rem);
}
.masthead .topline strong{color:var(--ink);font-weight:600}
.masthead .topline .sep{color:var(--faint)}
.masthead .doc-id{margin-left:auto;color:var(--accent)}
.masthead h1{font-size:var(--step-4);margin:0 0 .5rem;max-width:16ch}
.masthead h1 .accent{color:var(--accent)}
.masthead .sub{
font-family:var(--mono);color:var(--muted);font-size:var(--step-0);letter-spacing:.02em;
}
.masthead .lede{
margin:1.6rem 0 0;max-width:62ch;font-size:var(--step-1);line-height:1.45;
color:var(--ink-soft);font-family:var(--serif);
}
.masthead .lede b{color:var(--ink)}
/* ---- theme toggle (segmented pill, matches mono label system) ----- */
.themebar{
position:absolute;top:clamp(1rem,3vw,1.8rem);right:clamp(1.1rem,4vw,3rem);
display:flex;align-items:center;gap:.9rem;z-index:5;flex-wrap:wrap;justify-content:flex-end;
}
.themebar .tgctl{display:inline-flex;align-items:center;gap:.55rem}
.themebar .tglabel{
font-family:var(--mono);font-size:.6rem;letter-spacing:.18em;text-transform:uppercase;
color:var(--faint);font-weight:700;
}
.themeseg{
display:inline-flex;border:1px solid var(--border-strong);border-radius:99px;
background:var(--surface);box-shadow:var(--shadow);overflow:hidden;
padding:2px;gap:2px;
}
.themeseg button{
appearance:none;border:0;cursor:pointer;background:transparent;
font-family:var(--mono);font-size:.72rem;font-weight:700;letter-spacing:.1em;
color:var(--muted);padding:.32em .82em;border-radius:99px;
transition:background-color .16s ease, color .16s ease;
line-height:1;display:inline-flex;align-items:center;gap:.35em;
}
.themeseg button:hover{color:var(--accent-ink)}
.themeseg button[aria-pressed="true"]{
background:var(--accent);color:#fff;box-shadow:0 1px 6px -2px rgba(0,0,0,.4);
}
:root[data-theme="dark"] .themeseg button[aria-pressed="true"]{color:#fff}
@media (prefers-color-scheme: dark){
:root:not([data-theme="light"]) .themeseg button[aria-pressed="true"]{color:#fff}
}
.themeseg button:focus-visible{outline:2.5px solid var(--accent);outline-offset:2px}
@media(max-width:560px){
.themebar .tglabel{display:none}
.themebar{top:.7rem;right:.9rem}
}
/* =========================================================================
SECTION SHELL
========================================================================= */
section{padding:clamp(2.6rem,6vw,4.4rem) 0;border-top:1px solid var(--rule)}
.sec-head{display:flex;align-items:baseline;gap:1rem;margin-bottom:2rem;flex-wrap:wrap}
.sec-head .tag{
font-family:var(--mono);font-weight:700;font-size:var(--step--1);
color:var(--bg);background:var(--ink);
padding:.28em .7em;border-radius:3px;letter-spacing:.1em;flex:none;
}
.sec-head h2{font-size:var(--step-2);margin:0;max-width:26ch}
.sec-head .note{
margin-left:auto;font-family:var(--mono);font-size:var(--step--1);
color:var(--muted);align-self:flex-end;text-align:right;max-width:36ch;line-height:1.5;
}
/* =========================================================================
FEATURED HERO CARD — the cover's centerpiece
========================================================================= */
.featured{
display:grid;grid-template-columns:1fr;gap:0;
border:1px solid var(--border);border-radius:18px;overflow:hidden;
box-shadow:var(--shadow-lift);background:var(--surface);
text-decoration:none;color:inherit;
position:relative;
transition:border-color .2s ease, transform .25s cubic-bezier(.2,.7,.2,1), box-shadow .25s ease;
}
@media(min-width:820px){.featured{grid-template-columns:1.15fr .85fr}}
.featured:hover{border-color:var(--accent)}
@media (prefers-reduced-motion: no-preference){
.featured:hover{transform:translateY(-3px)}
}
.featured:focus-visible{outline:2.5px solid var(--accent);outline-offset:4px}
.featured .ft-body{
padding:clamp(1.8rem,4vw,3rem);display:flex;flex-direction:column;
}
.featured .ft-stamp{
display:flex;align-items:center;gap:.7rem;flex-wrap:wrap;margin-bottom:1.3rem;
font-family:var(--mono);font-size:var(--step--1);
}
.featured .ft-stamp .ft-tag{
font-weight:700;letter-spacing:.16em;text-transform:uppercase;
color:#fff;background:var(--accent);border-radius:99px;padding:.4em .9em;flex:none;
}
:root[data-theme="dark"] .featured .ft-stamp .ft-tag{color:#fff}
.featured .ft-stamp .ft-no{
color:var(--accent);font-weight:700;font-variant-numeric:tabular-nums lining-nums;letter-spacing:.06em;
}
.featured .ft-stamp .ft-avail{
margin-left:auto;color:var(--muted);letter-spacing:.06em;
border:1px solid var(--border-strong);border-radius:99px;padding:.32em .7em;
display:inline-flex;align-items:center;gap:.4em;
}
.featured .ft-stamp .ft-avail .lc{color:var(--accent-ink);font-weight:700}
.featured .ft-stamp .ft-avail .sep{color:var(--faint)}
.featured h3{
font-size:clamp(1.7rem,1.2rem+2vw,2.7rem);margin:0;line-height:1.08;letter-spacing:-.015em;
max-width:18ch;color:var(--ink);
}
.featured .ft-premise{
margin:1.1rem 0 0;font-family:var(--serif);font-size:var(--step-1);line-height:1.45;
color:var(--ink-soft);max-width:46ch;
}
.featured .ft-premise b{color:var(--ink)}
.featured .ft-meta{
margin-top:1.3rem;display:flex;flex-wrap:wrap;gap:.5rem;
font-family:var(--mono);font-size:var(--step--1);color:var(--muted);
}
.featured .ft-meta .chip{
border:1px solid var(--border);background:var(--surface-2);border-radius:99px;
padding:.3em .7em;letter-spacing:.02em;
}
.featured .ft-cta{
margin-top:auto;padding-top:1.6rem;display:inline-flex;align-items:center;
}
.featured .gobtn{
display:inline-flex;align-items:center;gap:.6rem;
font-family:var(--mono);font-weight:700;font-size:var(--step-0);letter-spacing:.04em;
color:#fff;background:var(--accent);border:1px solid var(--accent);
padding:.7em 1.2em;border-radius:11px;box-shadow:var(--shadow);
transition:gap .18s ease, box-shadow .2s ease;
}
:root[data-theme="dark"] .featured .gobtn{color:#fff}
.featured:hover .gobtn{gap:.95rem;box-shadow:var(--shadow-lift)}
.featured .gobtn svg{width:1.05em;height:1.05em}
/* the illustration panel — the visual centerpiece */
.featured .ft-art{
background:
radial-gradient(120% 130% at 100% 0%, var(--accent-wash) 0%, transparent 60%),
repeating-linear-gradient(135deg, var(--surface-2) 0 2px, transparent 2px 11px),
var(--surface-2);
display:grid;place-items:center;padding:clamp(1.8rem,4vw,2.8rem);
border-top:1px solid var(--border);
position:relative;overflow:hidden;
}
@media(min-width:820px){.featured .ft-art{border-top:none;border-left:1px solid var(--border)}}
.featured .ft-art svg{width:100%;max-width:340px;height:auto;color:var(--accent);display:block}
/* =========================================================================
THE SHELF — flat grid of numbered specimen cards
(ported from the catalog variant; tokens are identical so it themes 1:1)
========================================================================= */
/* The grid: auto-fill so a single card sits naturally at the start and the
row simply fills out as more specimens are added — no empty placeholders. */
.specimens{
display:grid;gap:clamp(1rem,2.5vw,1.4rem);
grid-template-columns:repeat(auto-fill, minmax(min(100%, 340px), 1fr));
align-items:start;
}
/* ---- one specimen card -------------------------------------------------- */
.specimen{
position:relative;display:flex;flex-direction:column;
text-decoration:none;color:inherit;
background:
radial-gradient(130% 120% at 100% 0%, var(--accent-wash) 0%, transparent 42%),
var(--surface);
border:1px solid var(--border);border-radius:16px;
box-shadow:var(--shadow);overflow:hidden;
transition:border-color .18s ease, box-shadow .25s ease, transform .25s cubic-bezier(.2,.7,.2,1);
}
.specimen:hover{
border-color:var(--accent);box-shadow:var(--shadow-lift);transform:translateY(-3px);
}
.specimen:focus-visible{outline:2.5px solid var(--accent);outline-offset:3px}
@media (prefers-reduced-motion: reduce){
.specimen{transition:border-color .18s ease}
.specimen:hover{transform:none}
}
/* code rail across the top: index + doc-id + topic — the datasheet header */
.specimen .sp-rail{
display:grid;grid-template-columns:auto 1fr auto;align-items:center;gap:.9rem;
padding:.9rem 1.15rem;border-bottom:1px solid var(--border);
background:var(--surface-2);
font-family:var(--mono);
}
.specimen .sp-index{
font-family:var(--mono);font-variant-numeric:tabular-nums lining-nums;
font-weight:700;font-size:clamp(2.2rem,1.6rem+2vw,3rem);line-height:.9;
color:var(--accent);letter-spacing:-.02em;
}
.specimen .sp-codes{display:flex;flex-direction:column;gap:.2rem;min-width:0}
.specimen .sp-docid{
font-size:var(--step--1);font-weight:700;letter-spacing:.06em;color:var(--ink-soft);
font-variant-numeric:tabular-nums;
}
.specimen .sp-topic{
font-size:.62rem;letter-spacing:.2em;text-transform:uppercase;font-weight:700;color:var(--accent);
}
.specimen .sp-rail-glyph{color:var(--faint);flex:none}
/* the prominent motif panel */
.specimen .sp-art{
display:grid;place-items:center;
padding:clamp(1.3rem,4vw,2rem) 1.15rem clamp(.6rem,2vw,1rem);
background:repeating-linear-gradient(135deg, var(--surface-2) 0 2px, transparent 2px 9px), transparent;
border-bottom:1px solid var(--border);
}
.specimen .sp-art svg{width:100%;max-width:188px;height:auto;color:var(--accent);display:block}
.specimen .sp-body{padding:1.2rem 1.2rem 0;flex:1 1 auto}
.specimen .sp-title{
font-family:var(--serif);font-weight:700;font-size:var(--step-2);line-height:1.1;
letter-spacing:-.01em;margin:0 0 .55rem;color:var(--ink);
}
.specimen:hover .sp-title{color:var(--accent-ink)}
.specimen .sp-premise{
margin:0;color:var(--ink-soft);font-size:var(--step--1);line-height:1.55;
}
/* mono metadata chip row — truthful descriptors only */
.specimen .sp-meta{
display:flex;flex-wrap:wrap;gap:.4rem;margin:1.1rem 1.2rem 0;
font-family:var(--mono);font-size:.66rem;
}
.specimen .sp-meta .m{
display:inline-flex;align-items:center;gap:.4rem;
border:1px solid var(--border);background:var(--surface);
color:var(--muted);padding:.3em .6em;border-radius:7px;letter-spacing:.03em;
}
.specimen .sp-meta .m .mk{color:var(--faint);text-transform:uppercase;letter-spacing:.1em;font-size:.9em}
.specimen .sp-meta .m .mv{color:var(--ink-soft);font-weight:700}
.specimen .sp-meta .m.lang .mv{font-weight:600}
/* footer of the card: the Read affordance, mirrors .gobtn language */
.specimen .sp-foot{
margin-top:1.2rem;padding:.95rem 1.2rem;border-top:1px solid var(--border);
display:flex;align-items:center;justify-content:space-between;gap:.8rem;
}
.specimen .sp-stamp{
font-family:var(--mono);font-size:.6rem;letter-spacing:.1em;text-transform:uppercase;color:var(--faint);
}
.specimen .sp-read{
display:inline-flex;align-items:center;gap:.5rem;
font-family:var(--mono);font-size:.74rem;font-weight:700;letter-spacing:.04em;
color:#fff;background:var(--accent);border:1px solid var(--accent);
padding:.5em 1em;border-radius:99px;line-height:1;
box-shadow:0 1px 8px -3px rgba(109,74,255,.6);
transition:background-color .16s ease, border-color .16s ease, gap .18s ease;
}
:root[data-theme="dark"] .specimen .sp-read{color:#fff}
@media (prefers-color-scheme: dark){
:root:not([data-theme="light"]) .specimen .sp-read{color:#fff}
}
.specimen:hover .sp-read{background:var(--accent-ink);border-color:var(--accent-ink);gap:.7rem}
.specimen .sp-read svg{width:13px;height:13px;flex:none}
/* =========================================================================
FOOTER
========================================================================= */
footer{border-top:1px solid var(--border-strong);padding:2.4rem 0 4rem;margin-top:1rem}
footer .fnote{font-family:var(--mono);font-size:var(--step--1);color:var(--muted);line-height:1.7;max-width:80ch}
footer .fnote b{color:var(--ink-soft)}
footer .fnote .prims{color:var(--accent-ink)}
footer .sig{
margin-top:1.4rem;display:flex;flex-wrap:wrap;gap:.5rem 1.2rem;align-items:center;
font-family:var(--mono);font-size:var(--step--1);color:var(--faint);
}
footer .sig .dot{width:6px;height:6px;border-radius:50%;background:var(--accent)}
/* =========================================================================
MOTION — single calm reveal, reduced-motion safe
========================================================================= */
@media (prefers-reduced-motion: no-preference){
.reveal{opacity:0;transform:translateY(12px);transition:opacity .6s ease, transform .6s cubic-bezier(.2,.7,.2,1)}
.reveal.in{opacity:1;transform:none}
}
/* =========================================================================
DARK-MODE: keep the section-number tag legible (accent-tinted slab).
========================================================================= */
:root[data-theme="dark"] .sec-head .tag{background:var(--accent-wash);color:var(--accent-ink)}
@media (prefers-color-scheme: dark){
:root:not([data-theme="light"]) .sec-head .tag{background:var(--accent-wash);color:var(--accent-ink)}
}
/* =========================================================================
PRINT
========================================================================= */
@media print{
:root{--bg:#fff;--surface:#fff;--surface-2:#f4f4f4;--ink:#000;--ink-soft:#222;--muted:#555;--border:#bbb;--rule:#ddd}
body{background:#fff}
body::before{display:none}
section{page-break-inside:avoid;border-top:1px solid #ccc}
.featured,.specimen{box-shadow:none}
.specimen{break-inside:avoid}
.specimen .sp-read{background:#fff;color:#000;border-color:#555;box-shadow:none;-webkit-print-color-adjust:exact;print-color-adjust:exact}
.reveal{opacity:1!important;transform:none!important}
.themebar{display:none}
.featured{break-inside:avoid}
}
</style>
</head>
<body>
<a class="skip" href="#main">Skip to content</a>
<!-- ============================ MASTHEAD ============================ -->
<header class="masthead wrap">
<div class="themebar" role="group" aria-label="Colour theme">
<div class="tgctl" role="group" aria-label="Colour theme">
<span class="tglabel">Theme</span>
<div class="themeseg">
<button type="button" data-theme-set="light" aria-pressed="false" aria-label="Light theme">
<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" aria-hidden="true"><circle cx="12" cy="12" r="4.5"/><path d="M12 2v2M12 20v2M2 12h2M20 12h2M5 5l1.5 1.5M17.5 17.5L19 19M19 5l-1.5 1.5M6.5 17.5L5 19"/></svg><span>LIGHT</span></button>
<button type="button" data-theme-set="dark" aria-pressed="false" aria-label="Dark theme">
<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M20 14.5A8 8 0 1 1 9.5 4a6.5 6.5 0 0 0 10.5 10.5z"/></svg><span>DARK</span></button>
</div>
</div>
</div>
<div class="topline">
<span><strong>POUYA'S FIELD GUIDES</strong></span>
<span class="sep">/</span>
<span>Plain-English tutorials for normal humans</span>
<span class="doc-id num">INDEX / 00</span>
</div>
<p class="kicker" style="margin:0 0 .9rem">The shelf</p>
<h1>The missing manuals for the tech that <span class="accent">won't explain itself</span></h1>
<p class="sub">Plain-English field guides — no fearmongering, no affiliate links, no "it depends."</p>
<p class="lede">Each one takes a single intimidating topic and explains it properly — once, in
plain English, with <b>zero shame and zero scare tactics</b>. Pick one off the shelf.</p>
</header>
<main id="main" class="wrap">
<!-- ============================ FEATURED ============================ -->
<section aria-labelledby="featured-h" style="border-top:none">
<div class="sec-head">
<span class="tag">FEATURED</span>
<h2 id="featured-h">The flagship guide</h2>
<p class="note">Start here. It's the one almost everyone needs first.</p>
</div>
<a class="featured reveal" href="bitwarden-switch/password-manager-overview.html"
aria-label="Read the field guide: Your Passwords Are the Keys to Your Whole Life">
<div class="ft-body">
<div class="ft-stamp">
<span class="ft-tag">Featured</span>
<span class="ft-no num">01</span>
<span class="ft-avail num"><span class="lc">EN</span> <span class="sep">&middot;</span> <span class="lc">DE</span> <span class="sep">&middot;</span> <span class="lc">FA</span></span>
</div>
<h3>Your Passwords Are the Keys to Your Whole Life</h3>
<p class="ft-premise">A plain-English guide for people who don't (and shouldn't have
to) think about hackers all day. <b>From "I reuse the same password" to "I don't have
to worry about this anymore."</b></p>
<div class="ft-meta">
<span class="chip">Password managers</span>
<span class="chip">The Bitwarden switch</span>
<span class="chip">Start here</span>
</div>
<span class="ft-cta">
<span class="gobtn">
Read the guide
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M5 12h14M13 6l6 6-6 6"/></svg>
</span>
</span>
</div>
<!-- the centerpiece: one master key, fanning out to the many locks it opens.
Composition is balanced on a single centerline (y=130): the key bow sits
in a soft concentric "secured" halo at left; the blade runs to a shoulder
node at x=196; three symmetric bezier strands fan to three identical
padlocks stacked and vertically centred at right (top 70 · mid 130 · bot 190),
each held clear of the frame edge. -->
<div class="ft-art" aria-hidden="true">
<svg viewBox="0 0 340 260" fill="none" stroke="currentColor" stroke-width="3.6" stroke-linecap="round" stroke-linejoin="round">
<!-- soft concentric "secured" halo behind the key bow -->
<g stroke="currentColor" fill="none">
<circle cx="58" cy="130" r="46" stroke-width="1.2" opacity=".18"/>
<circle cx="58" cy="130" r="38" stroke-width="1.2" opacity=".30"/>
</g>
<!-- the single master key, on the centreline -->
<g>
<circle cx="58" cy="130" r="27"/>
<circle cx="58" cy="130" r="9" stroke-width="2.6"/>
<!-- blade -->
<path d="M85 130 H196"/>
<!-- evenly-spaced teeth, mirrored about the blade for a key-like silhouette -->
<path d="M150 130 v15 M168 130 v20 M186 130 v13"/>
</g>
<!-- shoulder node where the three strands depart -->
<circle cx="196" cy="130" r="4.6" fill="currentColor" stroke="none"/>
<!-- three symmetric strands fanning to the three locks -->
<g stroke-width="2.4" opacity=".8">
<path d="M199 127 C232 104 244 84 262 72"/>
<path d="M201 130 H258"/>
<path d="M199 133 C232 156 244 176 262 188"/>
</g>
<!-- three identical padlocks the one key opens (centres x=283, kept off the edge) -->
<g stroke-width="2.8">
<!-- top lock, centred at y=70 -->
<rect x="266" y="62" width="34" height="30" rx="5"/>
<path d="M272 62 v-7 a11 11 0 0 1 22 0 v7" stroke-width="2.6"/>
<circle cx="283" cy="74" r="3.4" stroke-width="2.2"/>
<path d="M283 77 v5.5" stroke-width="2.2"/>
<!-- middle lock, centred at y=130 -->
<rect x="266" y="122" width="34" height="30" rx="5"/>
<path d="M272 122 v-7 a11 11 0 0 1 22 0 v7" stroke-width="2.6"/>
<circle cx="283" cy="134" r="3.4" stroke-width="2.2"/>
<path d="M283 137 v5.5" stroke-width="2.2"/>
<!-- bottom lock, centred at y=190 -->
<rect x="266" y="182" width="34" height="30" rx="5"/>
<path d="M272 182 v-7 a11 11 0 0 1 22 0 v7" stroke-width="2.6"/>
<circle cx="283" cy="194" r="3.4" stroke-width="2.2"/>
<path d="M283 197 v5.5" stroke-width="2.2"/>
</g>
</svg>
</div>
</a>
</section>
<!-- ============================ THE SHELF ============================ -->
<section aria-labelledby="shelf-h">
<div class="sec-head">
<span class="tag">SHELF</span>
<h2 id="shelf-h">The shelf</h2>
<p class="note">One card per guide. Numbered like specimens — the shelf grows as guides are added.</p>
</div>
<div class="specimens">
<!-- ========================================================================
SPECIMEN SEC-01 — Password security field guide (also the featured one)
======================================================================== -->
<a class="specimen reveal" href="bitwarden-switch/password-manager-overview.html"
aria-label="Specimen 01, SEC-01, Security: Your Passwords Are the Keys to Your Whole Life. Read the guide.">
<div class="sp-rail">
<span class="sp-index num" aria-hidden="true">01</span>
<span class="sp-codes">
<span class="sp-docid num">SEC-01</span>
<span class="sp-topic">Security</span>
</span>
<span class="sp-rail-glyph" aria-hidden="true">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="11" width="18" height="11" rx="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/></svg>
</span>
</div>
<div class="sp-art" aria-hidden="true">
<!-- key + padlock motif, accent stroke -->
<svg viewBox="0 0 200 120" fill="none" role="img" aria-hidden="true">
<!-- faint baseline rule -->
<line x1="10" y1="104" x2="190" y2="104" stroke="currentColor" stroke-width="1" opacity=".22" stroke-dasharray="3 5"/>
<!-- padlock body -->
<rect x="96" y="48" width="74" height="56" rx="9" stroke="currentColor" stroke-width="3.5"/>
<!-- padlock shackle -->
<path d="M110 48V36a23 23 0 0 1 46 0v12" stroke="currentColor" stroke-width="3.5" stroke-linecap="round"/>
<!-- keyhole -->
<circle cx="133" cy="72" r="7.5" stroke="currentColor" stroke-width="3.2"/>
<path d="M133 79v11" stroke="currentColor" stroke-width="3.2" stroke-linecap="round"/>
<!-- key, pointing toward the lock -->
<circle cx="40" cy="70" r="17" stroke="currentColor" stroke-width="3.5"/>
<circle cx="40" cy="70" r="6" stroke="currentColor" stroke-width="3"/>
<path d="M57 70h34" stroke="currentColor" stroke-width="3.5" stroke-linecap="round"/>
<path d="M78 70v11M88 70v8" stroke="currentColor" stroke-width="3.5" stroke-linecap="round"/>
</svg>
</div>
<div class="sp-body">
<h3 class="sp-title">Your Passwords Are the Keys to Your Whole Life</h3>
<p class="sp-premise">A plain-English guide for people who don't (and shouldn't have to)
think about hackers all day.</p>
</div>
<div class="sp-meta" aria-label="Guide details">
<span class="m lang"><span class="mk">Lang</span><span class="mv">EN · DE · FA</span></span>
<span class="m"><span class="mk">Level</span><span class="mv">Starter</span></span>
<span class="m"><span class="mk">Format</span><span class="mv">Walkthrough</span></span>
</div>
<div class="sp-foot">
<span class="sp-stamp num">SAFE·01</span>
<span class="sp-read">Read
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M5 12h14M13 6l6 6-6 6"/></svg>
</span>
</div>
</a>
<!-- ========================================================================
SPECIMEN AGT-01 — Agentic environment field guide
======================================================================== -->
<a class="specimen reveal" href="agentic-setup/agentic-setup-overview.html"
aria-label="Specimen 02, AGT-01, Agentic dev: Your Agentic Environment, a field guide. Read the guide.">
<div class="sp-rail">
<span class="sp-index num" aria-hidden="true">02</span>
<span class="sp-codes">
<span class="sp-docid num">AGT-01</span>
<span class="sp-topic">Agentic Dev</span>
</span>
<span class="sp-rail-glyph" aria-hidden="true">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="5" r="2.4"/><circle cx="5" cy="18" r="2.4"/><circle cx="19" cy="18" r="2.4"/><path d="M10.6 6.9 6.4 16M13.4 6.9 17.6 16M7.4 18h9.2"/></svg>
</span>
</div>
<div class="sp-art" aria-hidden="true">
<!-- "team of agents" motif: a coordinating hub linked to specialist nodes -->
<svg viewBox="0 0 200 120" fill="none" role="img" aria-hidden="true">
<!-- faint baseline rule -->
<line x1="10" y1="104" x2="190" y2="104" stroke="currentColor" stroke-width="1" opacity=".22" stroke-dasharray="3 5"/>
<!-- connection strands from the hub to each specialist (drawn first, under the nodes) -->
<g stroke="currentColor" stroke-width="2.4" opacity=".55" stroke-linecap="round">
<path d="M100 60 L48 30"/>
<path d="M100 60 L152 30"/>
<path d="M100 60 L40 84"/>
<path d="M100 60 L160 84"/>
<path d="M100 60 L100 22"/>
</g>
<!-- the five specialist agent nodes -->
<g stroke="currentColor" stroke-width="3" fill="none">
<circle cx="100" cy="22" r="8.5"/>
<circle cx="48" cy="30" r="8.5"/>
<circle cx="152" cy="30" r="8.5"/>
<circle cx="40" cy="84" r="8.5"/>
<circle cx="160" cy="84" r="8.5"/>
</g>
<!-- the coordinating hub: filled core inside a ring -->
<circle cx="100" cy="60" r="15" stroke="currentColor" stroke-width="3.5" fill="none"/>
<circle cx="100" cy="60" r="5.5" fill="currentColor" stroke="none"/>
</svg>
</div>
<div class="sp-body">
<h3 class="sp-title">Your Agentic Environment — A Field Guide</h3>
<p class="sp-premise">A personal team of AI experts for your homelab, code, and ideas —
what it is, why it's built this way, and how the pieces fit.</p>
</div>
<div class="sp-meta" aria-label="Guide details">
<span class="m lang"><span class="mk">Lang</span><span class="mv">EN · DE</span></span>
<span class="m"><span class="mk">Level</span><span class="mv">Intermediate</span></span>
<span class="m"><span class="mk">Format</span><span class="mv">Field guide</span></span>
</div>
<div class="sp-foot">
<span class="sp-stamp num">ORIENT·01</span>
<span class="sp-read">Read
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M5 12h14M13 6l6 6-6 6"/></svg>
</span>
</div>
</a>
<!-- ========================================================================
NEXT SPECIMENS GO HERE.
Copy an <a class="specimen"> block above, then update:
- href → the guide's relative path
- .sp-index → 03, 04, … (tabular, two digits)
- .sp-docid / .sp-topic → e.g. NET-01 / NETWORKING
- .sp-rail-glyph + .sp-art svg → a motif in the accent colour
- .sp-title / .sp-premise / .sp-meta (Lang = ISO codes only) / .sp-stamp
The auto-fill grid reflows on its own — no layout changes needed,
and it left-aligns so a short shelf never looks padded out.
==================================================================== -->
</div>
</section>
</main>
<!-- ============================ FOOTER ============================ -->
<footer class="wrap">
<p class="fnote">
A small, slow-growing library of plain-English field guides —
<span class="prims">written to be read once, calmly, and then forgotten about</span>.
<br><br>
<b>Served as a static site.</b> The source of truth lives in the
<a href="https://git.pouya.duckdns.org/public/tutorials" target="_blank" rel="noopener"><code>public/tutorials</code></a> Gitea repository; this page and every guide are plain
self-contained HTML, built from there.
<br>
<a class="srclink" href="https://git.pouya.duckdns.org/public/tutorials" target="_blank" rel="noopener">View the source repository &rarr;</a>
</p>
<div class="sig">
<span class="dot" aria-hidden="true"></span>
<span>Pouya's Field Guides</span>
<span class="num">INDEX&middot;00</span>
<span>Plain-English tutorials for normal humans</span>
</div>
</footer>
<script>
/* =========================================================================
THEME TOGGLE — explicit light/dark override on :root[data-theme].
Default: localStorage choice -> else follow the OS (prefers-color-scheme,
handled in CSS). With JS off, the CSS media query still themes the page,
so nothing breaks. Uses the SAME store key as the guide pages so the
visitor's choice is consistent across the whole site.
(Reused verbatim from the password-guide design system.)
========================================================================= */
(function(){
var STORE = 'pwguide-theme';
var root = document.documentElement;
var buttons = document.querySelectorAll('.themeseg button[data-theme-set]');
function systemPref(){
return matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
}
function current(){
return root.getAttribute('data-theme') || systemPref();
}
function paint(theme){
buttons.forEach(function(b){
b.setAttribute('aria-pressed', b.getAttribute('data-theme-set') === theme ? 'true' : 'false');
});
}
function apply(theme, persist){
if(theme !== 'light' && theme !== 'dark') theme = systemPref();
root.setAttribute('data-theme', theme);
paint(theme);
if(persist){ try{ localStorage.setItem(STORE, theme); }catch(e){} }
}
var saved = null;
try{ saved = localStorage.getItem(STORE); }catch(e){}
if(saved === 'light' || saved === 'dark'){ apply(saved, false); }
else { paint(systemPref()); } /* leave data-theme unset -> CSS media query drives it */
buttons.forEach(function(b){
b.addEventListener('click', function(){ apply(b.getAttribute('data-theme-set'), true); });
});
})();
/* =========================================================================
CALM SINGLE REVEAL — fade the featured card + index in on first view.
Honors reduced-motion and degrades gracefully without IntersectionObserver.
(Reused from the password-guide design system.)
========================================================================= */
(function(){
var els = document.querySelectorAll('.reveal');
if(!('IntersectionObserver' in window) || matchMedia('(prefers-reduced-motion: reduce)').matches){
els.forEach(function(el){ el.classList.add('in'); });
return;
}
var io = new IntersectionObserver(function(entries){
entries.forEach(function(en){
if(en.isIntersecting){ en.target.classList.add('in'); io.unobserve(en.target); }
});
}, { rootMargin: '0px 0px -8% 0px', threshold: 0.08 });
els.forEach(function(el){ io.observe(el); });
})();
</script>
</body>
</html>