feat: add field-guide landing page and agentic-environment guide
This commit is contained in:
+860
@@ -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">·</span> <span class="lc">DE</span> <span class="sep">·</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 →</a>
|
||||
</p>
|
||||
<div class="sig">
|
||||
<span class="dot" aria-hidden="true"></span>
|
||||
<span>Pouya's Field Guides</span>
|
||||
<span class="num">INDEX·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>
|
||||
Reference in New Issue
Block a user