/* ───────────────────────────────────────────────────────────────
   Local Test, site stylesheet

   Warm paper, serif headings, system sans body. Same family as
   graysonanderson.com, with a software inflection carried by
   monospace details and framed screenshots rather than decoration.

   Everything is themed through the tokens in section 1. Light is the
   default; dark is the same design with the paper turned down, so no
   rule below this section may hardcode a colour.

    1. Tokens        2. Base          3. Header       4. Hero
    5. Sections      6. Buttons       7. Frames       8. Compare
    9. FAQ          10. Terminal     11. Live status 12. Demo host
   13. Dialog       14. Footer       15. Utilities   16. Motion
   17. Pocket       18. Two audiences (routes, spec sheet, pricing)
   ─────────────────────────────────────────────────────────────── */

/* ─── 1. Tokens ─────────────────────────────────────────────── */

:root {
  color-scheme: light;

  --paper:      #fcfbf9;
  --paper-2:    #f5f2ec;
  --card:       #ffffff;
  --rule:       #e6e1d9;
  --rule-2:     #d8d1c6;

  --ink:        #2c2a2f;
  --ink-2:      #56525c;
  --ink-3:      #6f6a78;   /* 5.1:1 on paper, carries most small text */

  --accent:     #a55f4c;   /* 4.7:1 on paper */
  --accent-ink: #ffffff;
  --accent-sub: #b98071;

  --sky:        #dce5f1;
  --sage:       #dde8da;
  --blush:      #f6e0da;
  --sky-ink:    #3f5877;
  --sage-ink:   #446341;
  --blush-ink:  #8a5344;

  --code-bg:    #f1ede6;
  --term-bg:    #2e2b33;
  --term-ink:   #efeaf2;
  --term-dim:   #a8a1b2;   /* 4.6:1 on term-bg */

  /* VIP. The only gold on the site, defined once so it stays identical
     wherever the crown appears, and dark enough to read as text. */
  --crown:      #8a6410;   /* 5.4:1 on paper */
  --crown-mark: #c8a13a;   /* the crown glyph itself, never text */
  --crown-bg:   #f8f1de;
  --crown-rule: #e0cd9a;

  --shadow:     0 18px 44px -22px rgba(44, 42, 47, .28);
  --shadow-sm:  0 8px 22px -12px rgba(44, 42, 47, .3);

  --wash-1: rgba(220, 229, 241, .80);
  --wash-2: rgba(221, 232, 218, .55);
  --wash-3: rgba(246, 224, 218, .40);

  --serif: "Iowan Old Style", "Palatino Linotype", Palatino, "Book Antiqua",
           Georgia, "Times New Roman", serif;
  --sans:  -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
           "Helvetica Neue", Arial, sans-serif;
  --mono:  ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas, monospace;

  --col:   660px;
  --wide:  980px;
  --pad:   clamp(1.4rem, 6vw, 2.5rem);
  --nav-h: 3.9rem;
  --ease:  cubic-bezier(.4, 0, .2, 1);
}

/* Dark is the same paper with the lights down: still warm, never grey. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;

    --paper:      #17151a;
    --paper-2:    #1e1b22;
    --card:       #201d25;
    --rule:       #322d3a;
    --rule-2:     #423b4c;

    --ink:        #f2eef3;
    --ink-2:      #cac4d0;
    --ink-3:      #9a93a3;   /* 6.2:1 on dark paper */

    --accent:     #e2937c;   /* 7.7:1 on dark paper */
    --accent-ink: #241a17;
    --accent-sub: #a86e5d;

    --sky:        #253044;
    --sage:       #24301f;
    --blush:      #3b2722;
    --sky-ink:    #b7c9e3;
    --sage-ink:   #b9d3b4;
    --blush-ink:  #f0bfae;

    --code-bg:    #2a2531;
    --term-bg:    #100e13;
    --term-ink:   #ece7ef;
    --term-dim:   #9b93a5;

    --crown:      #e0bb55;   /* 8.9:1 on dark paper */
    --crown-mark: #e0bb55;
    --crown-bg:   #2b2418;
    --crown-rule: #4d4028;

    --shadow:     0 18px 44px -22px rgba(0, 0, 0, .75);
    --shadow-sm:  0 8px 22px -12px rgba(0, 0, 0, .7);

    --wash-1: rgba(58, 78, 110, .30);
    --wash-2: rgba(56, 76, 52, .22);
    --wash-3: rgba(110, 62, 50, .22);
  }
}

:root[data-theme="dark"] {
  color-scheme: dark;

  --paper:      #17151a;
  --paper-2:    #1e1b22;
  --card:       #201d25;
  --rule:       #322d3a;
  --rule-2:     #423b4c;

  --ink:        #f2eef3;
  --ink-2:      #cac4d0;
  --ink-3:      #9a93a3;

  --accent:     #e2937c;
  --accent-ink: #241a17;
  --accent-sub: #a86e5d;

  --sky:        #253044;
  --sage:       #24301f;
  --blush:      #3b2722;
  --sky-ink:    #b7c9e3;
  --sage-ink:   #b9d3b4;
  --blush-ink:  #f0bfae;

  --code-bg:    #2a2531;
  --term-bg:    #100e13;
  --term-ink:   #ece7ef;
  --term-dim:   #9b93a5;

  --crown:      #e0bb55;
  --crown-mark: #e0bb55;
  --crown-bg:   #2b2418;
  --crown-rule: #4d4028;

  --shadow:     0 18px 44px -22px rgba(0, 0, 0, .75);
  --shadow-sm:  0 8px 22px -12px rgba(0, 0, 0, .7);

  --wash-1: rgba(58, 78, 110, .30);
  --wash-2: rgba(56, 76, 52, .22);
  --wash-3: rgba(110, 62, 50, .22);
}

/* ─── 2. Base ───────────────────────────────────────────────── */

*, *::before, *::after { box-sizing: border-box; }

html {
  scroll-behavior: smooth;
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink-2);
  font-family: var(--sans);
  font-size: 17px;
  line-height: 1.68;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  transition: background-color .25s var(--ease), color .25s var(--ease);
}

.wash {
  position: absolute;
  inset: 0 0 auto;
  height: 640px;
  pointer-events: none;
  z-index: 0;
  background:
    radial-gradient(60% 70% at 16% 0%,  var(--wash-1), transparent 62%),
    radial-gradient(55% 62% at 86% 4%,  var(--wash-2), transparent 60%),
    radial-gradient(70% 50% at 50% 24%, var(--wash-3), transparent 68%);
}

img { display: block; max-width: 100%; height: auto; }

a { color: inherit; }
a:hover { color: var(--accent); }

h1, h2, h3, h4 {
  font-family: var(--serif);
  font-weight: 400;
  color: var(--ink);
  margin: 0;
  letter-spacing: -.012em;
}

p { margin: 0 0 1.1em; }
p:last-child { margin-bottom: 0; }

code {
  font-family: var(--mono);
  font-size: .86em;
  background: var(--code-bg);
  border-radius: 5px;
  padding: .1em .38em;
}

.mono { font-family: var(--mono); font-size: .92em; }

::selection { background: var(--sky); color: var(--ink); }

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: 6px;
}

main { position: relative; z-index: 1; }

.skip {
  position: fixed;
  top: -100px;
  left: 1rem;
  z-index: 200;
  background: var(--ink);
  color: var(--paper);
  padding: .7rem 1.1rem;
  border-radius: 8px;
  font-size: .9rem;
  text-decoration: none;
  transition: top .2s var(--ease);
}
.skip:focus { top: 1rem; }

/* ─── 3. Header ─────────────────────────────────────────────── */

.nav {
  position: sticky;
  top: 0;
  z-index: 100;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  min-height: var(--nav-h);
  padding-block: .8rem;
  padding-inline: max(var(--pad), calc((100% - var(--wide)) / 2 + var(--pad)));
}

.nav::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: transparent;
  border-bottom: 1px solid transparent;
  transition: background-color .25s var(--ease), border-color .25s var(--ease);
}

.nav.scrolled::before {
  background: color-mix(in srgb, var(--paper) 82%, transparent);
  border-bottom-color: var(--rule);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
}

@supports not (backdrop-filter: blur(10px)) {
  .nav.scrolled::before { background: var(--paper); }
}

.nav-brand {
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  flex: none;
  white-space: nowrap;
  font-family: var(--serif);
  font-size: 1.12rem;
  color: var(--ink);
  text-decoration: none;
}
.mark { width: 13px; height: 13px; fill: var(--accent); flex: none; }
.nav-brand .mark { transition: transform .2s var(--ease); }
.nav-brand:hover .mark { transform: translateX(2px); }

.nav-links {
  display: flex;
  align-items: center;
  gap: 1.15rem;
  font-size: .92rem;
  min-width: 0;
}

.nav-links a {
  position: relative;
  padding-bottom: 3px;
  color: var(--ink-2);
  text-decoration: none;
  white-space: nowrap;
}

.nav-links a::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: -1px;
  height: 2px;
  background: var(--accent);
  border-radius: 2px;
  transform: scaleX(0);
  transform-origin: left;
  transition: transform .25s var(--ease);
}
.nav-links a.active::after,
.nav-links a[aria-current="page"]::after,
.nav-links a:hover::after { transform: scaleX(1); }

.theme-btn {
  display: grid;
  place-items: center;
  width: 30px;
  height: 30px;
  flex: none;
  padding: 0;
  border: 1px solid transparent;
  border-radius: 50%;
  background: transparent;
  color: var(--ink-3);
  cursor: pointer;
  transition: color .15s var(--ease), border-color .15s var(--ease);
}
.theme-btn:hover { color: var(--ink); border-color: var(--rule); }
.theme-btn svg { width: 16px; height: 16px; }

@media (max-width: 620px) {
  .nav { flex-wrap: wrap; gap: .35rem 1rem; }
  .nav-links { width: 100%; gap: .95rem; font-size: .86rem; overflow-x: auto; scrollbar-width: none; }
  .nav-links::-webkit-scrollbar { display: none; }
  .theme-btn { margin-left: auto; }
}

/* ─── 4. Hero ───────────────────────────────────────────────── */

.hero {
  position: relative;
  width: 100%;
  max-width: var(--wide);
  margin-inline: auto;
  padding: clamp(2.4rem, 7vw, 4rem) var(--pad) 0;
  text-align: center;
}

.hero h1 { font-size: clamp(2.5rem, 7vw, 3.6rem); }

.tagline {
  font-family: var(--serif);
  font-size: clamp(1.15rem, 3vw, 1.4rem);
  color: var(--ink);
  margin: .5rem 0 1rem;
}

.lede { max-width: 34rem; margin: 0 auto 1.6rem; }

.cta {
  display: flex;
  justify-content: center;
  flex-wrap: wrap;
  gap: .7rem;
  margin-bottom: .9rem;
}

.meta {
  font-family: var(--mono);
  font-size: .78rem;
  letter-spacing: .02em;
  color: var(--ink-3);
  margin-bottom: 2.2rem;
}

/* ─── 5. Sections ───────────────────────────────────────────── */

.block {
  width: 100%;
  max-width: var(--col);
  margin-inline: auto;
  padding: clamp(2.6rem, 7vw, 4.2rem) var(--pad) 0;
}
.block.wide { max-width: var(--wide); }

section[id] { scroll-margin-top: calc(var(--nav-h) + .6rem); }

h2 {
  font-size: clamp(1.5rem, 3.4vw, 1.85rem);
  margin-bottom: 1.1rem;
  padding-bottom: .55rem;
  border-bottom: 1px solid var(--rule);
}

.section-hint { font-size: .9rem; color: var(--ink-3); }
.section-hint a, .muted a { color: var(--accent); }

/* Feature groups */
.features { display: grid; grid-template-columns: 1fr 1fr; gap: 1.5rem 2.4rem; }
.feature { border-top: 1px solid var(--rule); padding-top: 1rem; }
.features .feature:nth-child(-n+2) { border-top: 0; padding-top: .2rem; }
.feature h3 { font-size: 1.08rem; margin-bottom: .35rem; }
.feature p { font-size: .95rem; }

@media (max-width: 640px) {
  .features { grid-template-columns: 1fr; }
  .features .feature:nth-child(2) { border-top: 1px solid var(--rule); padding-top: 1rem; }
}

/* Numbered steps */
.steps { list-style: none; margin: 0; padding: 0; display: grid; gap: 1.4rem; }
.steps li { display: flex; gap: 1.1rem; align-items: flex-start; }
.steps .n {
  flex: none;
  width: 2rem;
  height: 2rem;
  display: grid;
  place-items: center;
  font-family: var(--mono);
  font-size: .85rem;
  color: var(--sky-ink);
  background: var(--sky);
  border-radius: 50%;
  margin-top: .15rem;
}
.steps li:nth-child(2) .n { background: var(--sage); color: var(--sage-ink); }
.steps li:nth-child(3) .n { background: var(--blush); color: var(--blush-ink); }
.steps h3 { font-size: 1.06rem; margin-bottom: .2rem; }
.steps p { font-size: .95rem; }

/* Plain honest list, used for non-goals */
.limits { list-style: none; margin: 0; padding: 0; display: grid; gap: .55rem; }
.limits li { display: flex; gap: .7rem; font-size: .95rem; padding-left: .1rem; }
.limits li::before {
  content: "";
  flex: none;
  width: 6px;
  height: 6px;
  margin-top: .62em;
  border-radius: 1px;
  background: var(--rule-2);
}

/* ─── 6. Buttons ────────────────────────────────────────────── */

.btn {
  display: inline-block;
  padding: .62rem 1.25rem;
  border: 1px solid var(--rule-2);
  border-radius: 9px;
  background: var(--card);
  color: var(--ink);
  font-family: inherit;
  font-size: .95rem;
  font-weight: 500;
  text-decoration: none;
  cursor: pointer;
  transition: transform .15s var(--ease), background-color .15s var(--ease),
              color .15s var(--ease), border-color .15s var(--ease);
}
.btn:hover { transform: translateY(-1px); border-color: var(--ink-3); color: var(--ink); }
.btn:active { transform: none; }

.btn-primary { background: var(--ink); border-color: var(--ink); color: var(--paper); }
.btn-primary:hover { background: var(--accent); border-color: var(--accent); color: var(--accent-ink); }

.btn-small { padding: .34rem .8rem; font-size: .85rem; }

/* ─── 7. Frames (screenshots) ───────────────────────────────── */

.frame {
  margin: 0;
  background: var(--card);
  border: 1px solid var(--rule);
  border-radius: 12px;
  overflow: hidden;
  box-shadow: var(--shadow);
}

.hero .frame { max-width: 880px; margin-inline: auto; }

.frame-bar {
  display: flex;
  gap: 6px;
  padding: 9px 12px;
  border-bottom: 1px solid var(--rule);
  background: var(--paper-2);
}
.frame-bar i { width: 10px; height: 10px; border-radius: 50%; background: var(--rule-2); }
.frame-bar i:nth-child(1) { background: #d99a8a; }
.frame-bar i:nth-child(2) { background: #d9c48a; }
.frame-bar i:nth-child(3) { background: #a7c4a0; }

.frame figcaption {
  padding: .7rem 1rem .8rem;
  font-size: .88rem;
  color: var(--ink-3);
  border-top: 1px solid var(--rule);
}

.gallery { display: grid; gap: 1.8rem; }

/* Theme gallery: the ten real app themes */
.theme-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(15rem, 100%), 1fr));
  gap: 1.2rem;
  margin-top: 1.2rem;
}
.theme-card {
  margin: 0;
  border: 1px solid var(--rule);
  border-radius: 10px;
  overflow: hidden;
  background: var(--card);
  box-shadow: var(--shadow-sm);
}
.theme-card .zoomable { cursor: zoom-in; }
.theme-card img { width: 100%; }
.theme-card figcaption {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: .6rem;
  padding: .55rem .75rem .65rem;
  border-top: 1px solid var(--rule);
  font-size: .86rem;
  color: var(--ink);
}
.theme-card .mood { color: var(--ink-3); font-size: .8rem; text-align: right; }

/* ─── 8. Comparison table ───────────────────────────────────── */

.compare-wrap {
  overflow-x: auto;
  border: 1px solid var(--rule);
  border-radius: 10px;
  background: var(--card);
}

.compare {
  width: 100%;
  /* Below this the cells wrap to two or three words each and the table stops
     being readable, so it scrolls inside .compare-wrap instead. */
  min-width: 34rem;
  border-collapse: collapse;
  font-size: .93rem;
}
.compare caption {
  text-align: left;
  padding: .7rem .9rem .1rem;
  font-size: .86rem;
  color: var(--ink-3);
}
.compare th, .compare td {
  padding: .65rem .9rem;
  text-align: left;
  border-bottom: 1px solid var(--rule);
}
.compare thead th {
  font-family: var(--mono);
  font-size: .72rem;
  letter-spacing: .05em;
  text-transform: uppercase;
  color: var(--ink-3);
  font-weight: 500;
  background: var(--paper-2);
}
.compare tbody th { font-weight: 500; color: var(--ink); width: 28%; }
.compare tbody tr:last-child th,
.compare tbody tr:last-child td { border-bottom: 0; }
.compare td { color: var(--ink-2); }
.compare td:nth-child(2) { color: var(--ink); font-weight: 500; background: var(--sage); }

/* ─── 9. FAQ ────────────────────────────────────────────────── */

.faq details { border-top: 1px solid var(--rule); }
.faq details:last-child { border-bottom: 1px solid var(--rule); }
.faq summary {
  list-style: none;
  cursor: pointer;
  padding: .9rem 2rem .9rem 0;
  font-family: var(--serif);
  font-size: 1.06rem;
  color: var(--ink);
  position: relative;
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after {
  content: "+";
  position: absolute;
  right: .2rem;
  top: 50%;
  transform: translateY(-50%);
  font-family: var(--mono);
  color: var(--ink-3);
  transition: transform .2s var(--ease), color .2s var(--ease);
}
.faq details[open] summary::after { transform: translateY(-50%) rotate(45deg); color: var(--accent); }
.faq summary:hover::after { color: var(--accent); }
.faq-a { padding: 0 0 1rem; font-size: .95rem; }

/* ─── 10. Terminal ──────────────────────────────────────────── */

.terminal {
  margin-top: 1.6rem;
  background: var(--term-bg);
  border: 1px solid var(--rule);
  border-radius: 10px;
  overflow: hidden;
}
.terminal-title {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  margin: 0;
  padding: .55rem .7rem .55rem 1rem;
  font-family: var(--mono);
  font-size: .74rem;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--term-dim);
  border-bottom: 1px solid rgba(255, 255, 255, .09);
}
.terminal pre { margin: 0; padding: .9rem 1rem 1rem; overflow-x: auto; }
.terminal code {
  background: none;
  padding: 0;
  font-size: .84rem;
  line-height: 1.8;
  color: var(--term-ink);
}
.terminal .dim { color: var(--term-dim); }
.terminal pre:focus-visible { outline-offset: -3px; }

.copy-btn {
  flex: none;
  border: 1px solid rgba(255, 255, 255, .22);
  background: transparent;
  color: var(--term-dim);
  font-family: var(--mono);
  font-size: .7rem;
  letter-spacing: .04em;
  text-transform: uppercase;
  border-radius: 6px;
  padding: .25rem .6rem;
  cursor: pointer;
  transition: color .15s var(--ease), border-color .15s var(--ease);
}
.copy-btn:hover { color: #fff; border-color: rgba(255, 255, 255, .5); }

/* ─── 11. Live status card ──────────────────────────────────── */

.status-card {
  margin-top: 1.6rem;
  background: var(--card);
  border: 1px solid var(--rule);
  border-radius: 10px;
  padding: 1rem 1.2rem 1.1rem;
}
.status-card[hidden] { display: none; }

.status-head { display: flex; align-items: center; gap: .55rem; margin-bottom: .9rem; }
.status-head h3 { font-size: 1.02rem; flex: 1; }
.status-link {
  font-family: var(--mono);
  font-size: .72rem;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--ink-3);
  text-decoration: none;
}
.status-link:hover { color: var(--accent); }

.live-dot {
  width: 7px;
  height: 7px;
  flex: none;
  border-radius: 50%;
  background: var(--sage-ink);
  animation: live-pulse 2.4s var(--ease) infinite;
}
@keyframes live-pulse {
  0%   { box-shadow: 0 0 0 0 color-mix(in srgb, var(--sage-ink) 45%, transparent); }
  70%  { box-shadow: 0 0 0 7px transparent; }
  100% { box-shadow: 0 0 0 0 transparent; }
}

.status-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(7.5rem, 100%), 1fr));
  gap: .9rem 1.2rem;
  margin: 0;
}
.stat[hidden] { display: none; }
.status-grid dt {
  font-family: var(--mono);
  font-size: .68rem;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin-bottom: .15rem;
}
.status-grid dd { margin: 0; font-size: 1.02rem; color: var(--ink); font-weight: 500; }

.status-note { margin-top: .9rem; font-size: .88rem; color: var(--ink-3); }

/* ─── 12. Demo host ─────────────────────────────────────────── */
/* The replica's own styling lives in demo.css; this is just its slot. */

.demo-host { margin-top: 1.4rem; }
.demo-hint { margin-top: .75rem; font-size: .88rem; color: var(--ink-3); text-align: center; }

/* ─── 13. Dialog (screenshot viewer) ────────────────────────── */

dialog.lightbox {
  width: min(1200px, 92vw);
  max-height: 92vh;
  padding: 0;
  border: 0;
  border-radius: 12px;
  background: transparent;
  color: var(--ink-2);
  overflow: visible;
}
dialog.lightbox::backdrop {
  background: rgba(20, 18, 23, .82);
  backdrop-filter: blur(2px);
  -webkit-backdrop-filter: blur(2px);
}
dialog.lightbox figure { margin: 0; }
dialog.lightbox img {
  width: 100%;
  max-height: 78vh;
  object-fit: contain;
  border-radius: 10px;
  background: var(--card);
  box-shadow: 0 30px 80px -20px rgba(0, 0, 0, .6);
}
dialog.lightbox figcaption {
  padding-top: .75rem;
  text-align: center;
  font-size: .9rem;
  color: #d6d0dc;
}
.lightbox-bar {
  position: absolute;
  top: -3rem;
  right: 0;
  display: flex;
  align-items: center;
  gap: .4rem;
}
.lightbox-count {
  font-family: var(--mono);
  font-size: .75rem;
  color: #d6d0dc;
  margin-right: .4rem;
}
.lightbox-btn {
  display: grid;
  place-items: center;
  width: 36px;
  height: 36px;
  border: 0;
  border-radius: 50%;
  background: rgba(255, 255, 255, .14);
  color: #fff;
  font-size: 18px;
  line-height: 1;
  cursor: pointer;
  transition: background-color .15s var(--ease);
}
.lightbox-btn:hover { background: rgba(255, 255, 255, .28); }
.lightbox-btn svg { width: 16px; height: 16px; }

.zoomable { display: block; width: 100%; padding: 0; border: 0; background: none; cursor: zoom-in; }

/* ─── 14. Footer ────────────────────────────────────────────── */

.footer {
  position: relative;
  z-index: 1;
  max-width: var(--col);
  margin: clamp(3rem, 8vw, 4.6rem) auto 0;
  padding: 1.6rem var(--pad) 2.4rem;
  border-top: 1px solid var(--rule);
  text-align: center;
  font-size: .9rem;
  color: var(--ink-3);
}
.footer a { color: var(--ink-2); }
.footer a:hover { color: var(--accent); }

/* Footer links sit on their own rather than inside a sentence, so they need a
   real touch target. Inline padding would collide with the neighbouring link,
   so the height comes from the block axis only. */
.foot-links a {
  display: inline-block;
  padding-block: .35rem;
  min-height: 24px;
}
.dogfood { margin-top: .5rem; font-size: .85rem; font-style: italic; }
.made-by { margin-top: .4rem; }

/* ─── 15. Utilities ─────────────────────────────────────────── */

.to-top {
  position: fixed;
  right: 1.2rem;
  bottom: 1.2rem;
  z-index: 90;
  width: 42px;
  height: 42px;
  display: grid;
  place-items: center;
  border: 1px solid var(--rule-2);
  border-radius: 50%;
  background: var(--card);
  color: var(--ink-2);
  cursor: pointer;
  box-shadow: var(--shadow-sm);
  opacity: 0;
  visibility: hidden;
  transform: translateY(8px);
  transition: opacity .25s var(--ease), transform .25s var(--ease),
              visibility .25s var(--ease), color .15s var(--ease), border-color .15s var(--ease);
}
.to-top.show { opacity: 1; visibility: visible; transform: none; }
.to-top:hover { color: var(--accent); border-color: var(--accent); }

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* ─── 16. Motion ────────────────────────────────────────────── */

/* Content is visible by default. The hide-then-fade is opted into only
   once site.js confirms it is running, and it force-reveals after 1.5s. */
/* Published checksums for the installers (filled in by status.js). */
#verify[hidden], #verify-hint[hidden] { display: none; }
.verify-sums {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: .4rem 1rem;
  align-items: baseline;
  margin: 0;
  padding: .8rem 1rem 1rem;
  border-top: 1px solid rgba(255, 255, 255, .09);
}
.verify-sums dt {
  font-family: var(--mono);
  font-size: .71rem;
  letter-spacing: .05em;
  text-transform: uppercase;
  color: var(--term-dim);
}
.verify-sums dd { margin: 0; min-width: 0; }
.verify-file {
  display: block;
  font-size: .78rem;
  color: var(--term-ink);
}
.verify-sums code {
  display: block;
  font-family: var(--mono);
  font-size: .69rem;
  line-height: 1.55;
  color: var(--term-dim);
  overflow-wrap: anywhere;
}
@media (max-width: 34rem) {
  .verify-sums { grid-template-columns: minmax(0, 1fr); gap: .1rem; }
  .verify-sums dt { margin-top: .6rem; }
}

.js-reveal [data-reveal] {
  opacity: 0;
  transform: translateY(14px);
  transition: opacity .55s var(--ease), transform .55s var(--ease);
}
.js-reveal [data-reveal].in { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .js-reveal [data-reveal] { opacity: 1; transform: none; transition: none; }
  .live-dot { animation: none; }
  .nav::before, .to-top, .btn, .theme-btn, body { transition: none; }
  .nav-links a::after, .nav-brand .mark { transition: none; }
}

@media print {
  .nav, .to-top, .theme-btn, .wash, dialog.lightbox, .skip { display: none !important; }
  body { background: #fff; color: #000; }
  .frame { box-shadow: none; }
}

/* ───────────────────────────────────────────────────────────────
   17. Pocket-console layer

   The app took a retro-handheld turn in 1.3.0: moulded-plastic
   shading on the controls, a power-LED that breathes, and two
   pocket-console themes. The site borrows the same vocabulary
   (the same easing, the same press, the same shading), so the two
   read as one product. It is an inflection of the warm paper,
   not a costume over it.
   ─────────────────────────────────────────────────────────────── */

:root { --ease-pop: cubic-bezier(.2, .7, .3, 1); }

/* Pocket: the DMG screen, as a full site theme. */
:root[data-theme="pocket"] {
  color-scheme: light;

  --paper:      #c6d29c;
  --paper-2:    #b7c48c;
  --card:       #d5dfb1;
  --rule:       #9aa96f;
  --rule-2:     #8c9c62;

  --ink:        #16240c;
  --ink-2:      #2d3f16;
  --ink-3:      #46551f;

  --accent:     #2c5a2e;
  --accent-ink: #e7f0c8;
  --accent-sub: #4a7a44;

  --sky:        #b9c9a4;
  --sage:       #b4c188;
  --blush:      #cbc79a;
  --sky-ink:    #24361a;
  --sage-ink:   #2a601c;
  --blush-ink:  #5a4a12;

  --code-bg:    #b9c690;
  --term-bg:    #16240c;
  --term-ink:   #c6d29c;
  --term-dim:   #8ba065;

  /* The console's screen has no gold in it, so VIP borrows the amber the
     handheld does have rather than importing a colour from another theme. */
  --crown:      #5a4a12;   /* 6.3:1 on the pocket paper */
  --crown-mark: #7a6410;
  --crown-bg:   #cbc79a;
  --crown-rule: #a39558;

  --shadow:     0 14px 34px -20px rgba(22, 36, 12, .5);
  --shadow-sm:  0 7px 18px -10px rgba(22, 36, 12, .45);

  --wash-1: rgba(154, 169, 111, .45);
  --wash-2: rgba(120, 140, 80, .35);
  --wash-3: rgba(180, 193, 136, .35);

  --sans: var(--mono);
}

/* Moulded-plastic shading, applied to every theme so the retro
   flavour blends with the original design rather than replacing it.
   Same values the app uses. */
.btn, .theme-btn, .to-top, .copy-btn, .lightbox-btn {
  box-shadow: inset 0 -1.5px 0 rgba(0, 0, 0, .10), inset 0 1px 0 rgba(255, 255, 255, .16);
}
.btn-primary {
  box-shadow: inset 0 -2px 0 rgba(0, 0, 0, .20), inset 0 1px 0 rgba(255, 255, 255, .22);
}
.to-top { box-shadow: var(--shadow-sm), inset 0 -1.5px 0 rgba(0, 0, 0, .10), inset 0 1px 0 rgba(255, 255, 255, .16); }
.steps .n { box-shadow: inset 0 -2px 0 rgba(0, 0, 0, .07), inset 0 1px 0 rgba(255, 255, 255, .3); }

/* The frame chrome reads as a screen bezel rather than a browser bar. */
.frame-bar { box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .06); }

@media (prefers-reduced-motion: no-preference) {
  /* One press, everywhere something is pressable. */
  .btn:active, .theme-btn:active, .to-top:active,
  .copy-btn:active, .lightbox-btn:active, .zoomable:active {
    transform: translateY(1px) scale(.985);
  }
  .btn { transition: transform .12s var(--ease-pop), background-color .15s var(--ease),
                     color .15s var(--ease), border-color .15s var(--ease), box-shadow .15s var(--ease); }
  .theme-btn, .to-top, .copy-btn, .lightbox-btn, .zoomable {
    transition: transform .12s var(--ease-pop), color .15s var(--ease),
                border-color .15s var(--ease), background-color .15s var(--ease);
  }

  /* Rows lean toward the pointer, the way the app's project list does. */
  .theme-card { transition: transform .16s var(--ease-pop), box-shadow .16s var(--ease); }
  .theme-card:hover { transform: translateY(-2px); box-shadow: var(--shadow); }
  .faq summary { transition: color .15s var(--ease); }
  .faq details[open] .faq-a { animation: rise .22s var(--ease-pop); }

  /* The reveal uses the app's rise, so scrolling feels like the app. */
  .js-reveal [data-reveal] { transition: opacity .5s var(--ease-pop), transform .5s var(--ease-pop); }

  /* Status dot breathes like a power LED instead of pinging. */
  .live-dot { animation: breathe 2.6s ease-in-out infinite; }
}

@keyframes rise {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: none; }
}
@keyframes breathe {
  0%, 100% { box-shadow: 0 0 4px var(--sage-ink); opacity: 1; }
  50%      { box-shadow: 0 0 9px var(--sage-ink); opacity: .82; }
}

@media (prefers-reduced-motion: reduce) {
  .theme-card, .faq details[open] .faq-a { transition: none; animation: none; }
}

/* A download that has not been built yet: visible, clearly inert, never a
   link that goes nowhere. */
.btn-unavailable {
  opacity: .5;
  cursor: not-allowed;
  box-shadow: none;
}
.btn-unavailable:hover { transform: none; border-color: var(--rule-2); color: var(--ink); }

/* 404 */
.not-found { text-align: center; padding-top: clamp(3rem, 12vh, 6rem); }
.not-found h1 { font-size: clamp(3rem, 10vw, 4.5rem); margin-bottom: .4rem; }
.not-found .section-hint { margin-bottom: 1.6rem; }

.themes-note { margin-top: 1rem; }

/* ─── Download verification ─────────────────────────────────── */

.verify {
  margin-top: 1.2rem;
  border: 1px solid var(--rule);
  border-radius: 10px;
  background: var(--card);
}
.verify summary {
  list-style: none;
  cursor: pointer;
  padding: .7rem 1rem;
  font-size: .93rem;
  color: var(--ink);
  position: relative;
}
.verify summary::-webkit-details-marker { display: none; }
.verify summary::after {
  content: "+";
  position: absolute; right: 1rem; top: 50%;
  transform: translateY(-50%);
  font-family: var(--mono);
  color: var(--ink-3);
}
.verify[open] summary::after { content: "\2212"; }
.verify-body { padding: 0 1rem 1rem; font-size: .93rem; }
.verify-cmd { display: flex; align-items: baseline; gap: .7rem; margin: .4rem 0; }
.verify-os {
  flex: none; width: 4.5rem;
  font-family: var(--mono); font-size: .72rem;
  letter-spacing: .05em; text-transform: uppercase; color: var(--ink-3);
}
.verify-sums { margin: .9rem 0; display: grid; gap: .6rem; }
.verify-sums dt {
  font-family: var(--mono); font-size: .68rem;
  letter-spacing: .06em; text-transform: uppercase; color: var(--ink-3);
  margin-bottom: .1rem;
}
.verify-sums dd {
  margin: 0;
  font-family: var(--mono); font-size: .74rem;
  color: var(--ink);
  overflow-wrap: anywhere;
  user-select: all;
}

/* ─── Coming soon: one quiet line, never a banner ───────────── */

.soon {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  gap: .55rem .9rem;
  margin: -1.4rem 0 2.2rem;
  font-size: .82rem;
  color: var(--ink-3);
}
.soon-item { display: inline-flex; align-items: center; gap: .38rem; }
.soon-icon { width: 13px; height: 13px; fill: var(--ink-3); flex: none; }
/* The crown is the one gold thing on the page, so it stays small. It reads
   from the same token the pricing page uses, so VIP looks identical in both. */
.soon-crown { fill: var(--crown-mark); }
.soon-tag {
  font-family: var(--mono);
  font-size: .64rem;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--ink-3);
  background: var(--paper-2);
  border: 1px solid var(--rule);
  border-radius: 999px;
  padding: .1rem .45rem;
}
.soon-sep { width: 1px; height: .85rem; background: var(--rule); }
@media (max-width: 480px) { .soon-sep { display: none; } }

/* ─── Ambient background ────────────────────────────────────── */
/* Sits behind everything, ignores the pointer, and never affects layout. */
.ambient {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 0;
  pointer-events: none;
  user-select: none;
}
@media (prefers-reduced-motion: reduce) { .ambient { display: none; } }
@media print { .ambient { display: none; } }

/* ─── First-launch warning dialog ───────────────────────────── */

dialog.gk {
  width: min(640px, 92vw);
  max-height: 88vh;
  padding: 0;
  border: 1px solid var(--rule);
  border-radius: 14px;
  background: var(--card);
  color: var(--ink-2);
  box-shadow: var(--shadow);
  overflow: auto;
}
dialog.gk::backdrop {
  background: rgba(20, 18, 23, .62);
  backdrop-filter: blur(3px);
  -webkit-backdrop-filter: blur(3px);
}
.gk-inner { position: relative; padding: 1.6rem clamp(1.2rem, 4vw, 2rem) 1.5rem; }

.gk-close {
  position: absolute;
  top: .7rem;
  right: .8rem;
  width: 30px;
  height: 30px;
  display: grid;
  place-items: center;
  border: 0;
  border-radius: 50%;
  background: transparent;
  color: var(--ink-3);
  font-size: 20px;
  line-height: 1;
  cursor: pointer;
}
.gk-close:hover { background: var(--paper-2); color: var(--ink); }

.gk-eyebrow {
  font-family: var(--mono);
  font-size: .7rem;
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--sage-ink);
  margin: 0 0 .3rem;
}
dialog.gk h2 { font-size: 1.35rem; margin-bottom: .7rem; }
.gk-lead { font-size: .95rem; }

.gk-quote {
  margin: .9rem 0 1.1rem;
  padding: .7rem .9rem;
  border-left: 3px solid var(--rule-2);
  background: var(--paper-2);
  border-radius: 0 8px 8px 0;
  font-size: .92rem;
  color: var(--ink);
  font-style: italic;
}

.gk-steps section + section { margin-top: 1.1rem; }
.gk-steps h3 { font-size: 1rem; margin-bottom: .35rem; }
.gk-steps ol { margin: .3rem 0 0; padding-left: 1.3rem; font-size: .93rem; }
.gk-steps li { margin-bottom: .35rem; }
.gk-note { font-size: .86rem; color: var(--ink-3); margin: .2rem 0 .4rem; }

.gk-once {
  margin: 1.1rem 0 0;
  padding: .65rem .85rem;
  border-radius: 8px;
  background: var(--sage);
  color: var(--sage-ink);
  font-size: .9rem;
}

.gk-more { margin-top: .8rem; border-top: 1px solid var(--rule); }
.gk-more summary {
  list-style: none;
  cursor: pointer;
  padding: .6rem 0 .5rem;
  font-size: .9rem;
  color: var(--ink);
  position: relative;
}
.gk-more summary::-webkit-details-marker { display: none; }
.gk-more summary::after {
  content: "+";
  position: absolute; right: .1rem; top: 50%;
  transform: translateY(-50%);
  font-family: var(--mono);
  color: var(--ink-3);
}
.gk-more[open] summary::after { content: "\2212"; }
.gk-more > div { padding-bottom: .7rem; font-size: .9rem; }
.gk-cmd { margin: .45rem 0; }
.gk-cmd code {
  display: block;
  padding: .5rem .7rem;
  background: var(--code-bg);
  border-radius: 7px;
  font-size: .8rem;
  overflow-x: auto;
  user-select: all;
}

.gk-actions {
  display: flex;
  flex-wrap: wrap;
  gap: .6rem;
  margin-top: 1.3rem;
  padding-top: 1rem;
  border-top: 1px solid var(--rule);
}

@media (prefers-reduced-motion: no-preference) {
  dialog.gk[open] { animation: rise .22s var(--ease-pop); }
}

/* ───────────────────────────────────────────────────────────────
   18. Two audiences

   The landing page has to serve someone who has never run a
   server and someone who wants to read the security posture
   before downloading. Rather than averaging them into one bland
   voice, the page forks: a pair of route cards near the top, and
   a spec sheet further down that the second reader is sent
   straight to. Both use the same paper; only the density changes.
   ─────────────────────────────────────────────────────────────── */

/* A small mono label above a heading, for sections that need one. */
.eyebrow {
  font-family: var(--mono);
  font-size: .7rem;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin: 0 0 .4rem;
}

/* ─── Route cards ───────────────────────────────────────────── */

.routes { padding-top: clamp(1.6rem, 4vw, 2.4rem); }

.route-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(19rem, 100%), 1fr));
  gap: 1rem;
}

.route {
  border: 1px solid var(--rule);
  border-radius: 12px;
  background: var(--card);
  padding: 1.15rem 1.3rem 1.25rem;
  box-shadow: var(--shadow-sm);
}

.route-kicker {
  font-family: var(--mono);
  font-size: .72rem;
  letter-spacing: .04em;
  color: var(--ink-3);
  margin: 0 0 .45rem;
}
.route-kicker code { font-size: .95em; background: none; padding: 0; }

.route h3 { font-size: 1.14rem; margin-bottom: .45rem; }
.route p { font-size: .94rem; }

.route-links {
  display: flex;
  flex-wrap: wrap;
  gap: .3rem .55rem;
  margin: .9rem 0 0;
  font-size: .88rem;
}
.route-links a { color: var(--accent); text-decoration: none; }
.route-links a:hover { text-decoration: underline; }
.route-links span { color: var(--rule-2); }

/* ─── Demo section ──────────────────────────────────────────── */

.demo-section h2 { margin-bottom: .8rem; }
.demo-lede { max-width: 46rem; }

/* ─── Spec sheet (internals) ────────────────────────────────── */

.spec-lede { max-width: 46rem; margin-bottom: 1.6rem; }

.spec-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(21rem, 100%), 1fr));
  gap: 1.4rem 2.4rem;
}

.spec { min-width: 0; }
.spec h3 {
  font-size: 1.02rem;
  padding-bottom: .4rem;
  margin-bottom: .8rem;
  border-bottom: 1px solid var(--rule);
}

/* Term on its own line in mono, definition beneath: a reference layout,
   which is the register this section is written in. */
.spec-list { margin: 0; display: grid; gap: .85rem; }
.spec-list > div { min-width: 0; }
.spec-list dt {
  font-family: var(--mono);
  font-size: .71rem;
  letter-spacing: .05em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin-bottom: .18rem;
}
.spec-list dd {
  margin: 0;
  font-size: .91rem;
  line-height: 1.6;
  color: var(--ink-2);
}
.spec-list dd code { font-size: .84em; }

.spec-foot { margin-top: 1.6rem; }

/* ─── Comparison: grouped, including the losing group ───────── */

.compare-lede { max-width: 46rem; margin-bottom: 1rem; }

/* Specificity has to beat `.compare tbody th`, which sets the full ink
   colour every other row header wants. */
.compare tbody th.compare-group {
  font-family: var(--mono);
  font-size: .68rem;
  letter-spacing: .07em;
  text-transform: uppercase;
  font-weight: 500;
  /* ink-2, not ink-3: at this size ink-3 on paper-2 falls to 4.4:1 in the
     pocket theme, just under AA. */
  color: var(--ink-2);
  background: var(--paper-2);
}

/* The win highlight belongs only to rows Local Test actually wins, so the
   second group drops it rather than colouring a loss green. */
.compare-losses td:nth-child(2) {
  background: none;
  font-weight: 400;
  color: var(--ink-2);
}

/* ─── Pricing ───────────────────────────────────────────────── */

.plan-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(19rem, 100%), 1fr));
  gap: 1.2rem;
  margin-top: 1.6rem;
  align-items: start;
}

.plan {
  display: flex;
  flex-direction: column;
  border: 1px solid var(--rule);
  border-radius: 14px;
  background: var(--card);
  padding: 1.4rem 1.4rem 1.5rem;
  box-shadow: var(--shadow-sm);
}

.plan-vip { border-color: var(--crown-rule); }

.plan-head { display: flex; align-items: center; gap: .5rem; margin-bottom: .2rem; }
.plan-head h3 {
  font-size: 1.3rem;
  margin: 0;
  padding: 0;
  border: 0;
}
.plan-crown { width: 17px; height: 17px; fill: var(--crown-mark); flex: none; }

.plan-for { font-size: .9rem; color: var(--ink-3); margin: 0 0 1rem; }

.plan-price {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: .5rem;
  margin: 0 0 .3rem;
  font-family: var(--serif);
  font-size: 2.1rem;
  color: var(--ink);
  line-height: 1.15;
}
.plan-price .unit {
  font-family: var(--sans);
  font-size: .88rem;
  color: var(--ink-3);
}

/* A price that is not decided yet says so in the price slot. Putting a
   number here that later changes would be the one unrecoverable lie on
   the page, so the placeholder is deliberately not number-shaped. */
.price-tbd {
  font-family: var(--sans);
  font-size: 1.5rem;
  color: var(--ink-2);
}
.plan-price-note {
  font-size: .82rem;
  color: var(--ink-3);
  margin: 0 0 1.1rem;
  min-height: 1.2em;
}

.plan-cta { margin: 0 0 1.2rem; }
.plan-cta .btn { width: 100%; text-align: center; }

.btn-crown {
  background: var(--crown-bg);
  border-color: var(--crown-rule);
  color: var(--crown);
}
.btn-crown:hover { border-color: var(--crown); color: var(--crown); }

/* Not wired to a checkout yet: visibly a button, audibly disabled, and
   never a link that goes nowhere. */
.btn[aria-disabled="true"] { cursor: not-allowed; }

.plan-list { list-style: none; margin: 0; padding: 0; display: grid; gap: .5rem; }
.plan-list li {
  display: flex;
  gap: .6rem;
  align-items: flex-start;
  font-size: .92rem;
}
.plan-list svg {
  flex: none;
  width: 15px;
  height: 15px;
  margin-top: .3em;
  stroke: var(--sage-ink);
  fill: none;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.plan-list .plan-no svg { stroke: var(--ink-3); }
.plan-list .plan-no { color: var(--ink-3); }

.plan-foot {
  margin-top: 1.1rem;
  padding-top: .9rem;
  border-top: 1px solid var(--rule);
  font-size: .86rem;
  color: var(--ink-3);
}

/* Everything both tiers share, stated once so neither column has to
   repeat it and neither looks artificially thin. */
.plan-shared {
  margin-top: 1.4rem;
  border: 1px solid var(--rule);
  border-radius: 12px;
  background: var(--paper-2);
  padding: 1.1rem 1.3rem 1.2rem;
}
.plan-shared h3 { font-size: 1.02rem; margin-bottom: .5rem; }
.plan-shared ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(13rem, 100%), 1fr));
  gap: .35rem 1.4rem;
  font-size: .91rem;
}
.plan-shared li { display: flex; gap: .5rem; }
.plan-shared li::before {
  content: "";
  flex: none;
  width: 5px;
  height: 5px;
  margin-top: .66em;
  border-radius: 50%;
  background: var(--rule-2);
}

.pricing-head { text-align: center; }
.pricing-head .lede { margin-inline: auto; }

/* A CTA row inside a left-aligned section, rather than the centred hero. */
.cta-start { justify-content: flex-start; }
