/* ==========================================================================
   Public site
   ========================================================================== */

:root {
  --ground:      #05070C;
  --ground-2:    #080B12;
  --panel:       #0D121B;
  --panel-hi:    #121926;
  --rule:        #1A2231;
  --rule-strong: #27334A;
  --text:        #BFCBDA;
  --text-hi:     #F0F5FB;
  --muted:       #6C7B90;

  --violet:      #7C5CFF;
  --cyan:        #35E0F0;
  --accent:      #35E0F0;
  --hot:         #FF4D8D;
  --ok:          #3DDC97;
  --warn:        #E8A33D;
  --danger:      #E0645C;

  --font-display: "Space Grotesk", ui-sans-serif, system-ui, sans-serif;
  --font-mono: "Chivo Mono", ui-monospace, Menlo, Consolas, monospace;
  --font-body: "Inter Tight", ui-sans-serif, system-ui, -apple-system, sans-serif;

  --nav-h: 64px;

  /* The logo, in one place.
     Every mark on the site is --logo-h tall and every wordmark beside one is
     --logo-word of that, so the two keep the proportions of the original
     lockup wherever they appear. Setting each spot by hand is how the header,
     the footer and the repository ended up three different sizes. */
  --logo-h: 40px;
  --logo-word: .55;
  --measure: 68ch;
  --maxw: 1120px;
}

:root[data-theme="light"] {
  --ground: #F6F7FB; --ground-2: #FFFFFF; --panel: #FFFFFF; --panel-hi: #F2F4FA;
  --rule: #E1E5EF; --rule-strong: #C7CEDE;
  --text: #3A4354; --text-hi: #0B0F18; --muted: #6B7488;
  --violet: #5B3AE0; --cyan: #0A8FA0; --accent: #0A8FA0; --hot: #D62B68;
  --ok: #147A50; --warn: #9A6410; --danger: #B23F37;
}

@media (prefers-color-scheme: light) {
  :root:not([data-theme="dark"]) {
    --ground: #F6F7FB; --ground-2: #FFFFFF; --panel: #FFFFFF; --panel-hi: #F2F4FA;
    --rule: #E1E5EF; --rule-strong: #C7CEDE;
    --text: #3A4354; --text-hi: #0B0F18; --muted: #6B7488;
    --violet: #5B3AE0; --cyan: #0A8FA0; --accent: #0A8FA0; --hot: #D62B68;
    --ok: #147A50; --warn: #9A6410; --danger: #B23F37;
  }
}

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

html { scroll-behavior: smooth; scroll-padding-top: var(--nav-h); -webkit-text-size-adjust: 100%; }

/* The ground colour lives on html, not body, so the backdrop canvas can sit
   between them at z-index -1. An opaque body background would paint over it. */
html { background: var(--ground); }

body {
  margin: 0;
  background: transparent;
  color: var(--text);
  font-family: var(--font-body);
  font-size: 16px;
  line-height: 1.7;
  overflow-x: hidden;
  -webkit-font-smoothing: antialiased;
}

img { max-width: 100%; display: block; }
a { color: var(--accent); text-underline-offset: 3px; }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; border-radius: 3px; }

.skip {
  position: absolute; left: -9999px; top: 0; z-index: 200;
  background: var(--accent); color: var(--ground);
  padding: 12px 18px; font-family: var(--font-mono); font-size: 13px;
}
.skip:focus { left: 0; }

/* --- Nav ----------------------------------------------------------------- */

.nav {
  position: fixed; inset: 0 0 auto 0; height: var(--nav-h); z-index: 100;
  display: flex; align-items: center; gap: 24px;
  padding: 0 clamp(16px, 4vw, 40px);
  /* A fade from the ground colour down to nothing, never a panel with an
     edge. The backdrop runs the full height of the page behind this, and a
     bar with a border across the top of it reads as a slab laid over the
     page rather than part of it. The fade keeps the links legible over
     whatever scrolls underneath without drawing a line anywhere. */
  background: linear-gradient(
    to bottom,
    color-mix(in srgb, var(--ground) 88%, transparent) 0%,
    color-mix(in srgb, var(--ground) 55%, transparent) 55%,
    transparent 100%
  );
  border-bottom: 0;
}
/* Scrolled, the bar stays transparent. A blurred panel with a rule under it
   reads as a slab laid over the page rather than part of it, and the ground
   is dark enough that the links hold up against the content behind them
   without one. The class is still toggled; it just no longer paints. */

.brand {
  display: flex; align-items: center; flex: none;
  text-decoration: none; color: var(--text-hi);
}
.brand { gap: 9px; }

/* Both from the tokens, so the header, the footer and the repository cannot
   drift apart again. */
.brand-mark {
  height: var(--logo-h);
  width: auto; object-fit: contain; display: block; flex: none;
}
.brand-word {
  height: calc(var(--logo-h) * var(--logo-word));
  width: auto; object-fit: contain; display: block; flex: none;
}

/* Below this the menu needs the room more than the words do, and the mark
   alone is still unmistakably the site. */
@media (max-width: 640px) {
  .brand-word { display: none; }
}

.nav-links { display: flex; gap: 4px; margin-left: auto; align-items: center; }

.nav-links a {
  font-family: var(--font-mono); font-size: 12.5px; letter-spacing: .02em;
  color: var(--muted); text-decoration: none; padding: 7px 13px;
  border-radius: 100px; transition: color .2s, background .2s; white-space: nowrap;
}
.nav-links a:hover { color: var(--text-hi); background: var(--panel); }
.nav-links a.active { color: var(--text-hi); background: var(--panel-hi); }

/* --- Account menu --------------------------------------------------------- */
/* One control for a signed-in person: profile, submit, admin (staff only)
   and sign out. Replaces the earlier pair of near-identical buttons. */

.account { position: relative; margin-left: 12px; }

.account-btn {
  display: flex; align-items: center; gap: 9px;
  background: none; border: 1px solid transparent; cursor: pointer;
  padding: 5px 11px 5px 5px; border-radius: 100px;
  font-family: var(--font-mono); font-size: 12.5px; color: var(--text);
  transition: background .2s, border-color .2s, color .2s;
}
.account-btn:hover,
.account-btn[aria-expanded="true"] {
  background: var(--panel); border-color: var(--rule-strong); color: var(--text-hi);
}

.account-initial {
  width: 26px; height: 26px; border-radius: 50%; flex: none;
  display: grid; place-items: center;
  background: linear-gradient(135deg, var(--violet), var(--cyan));
  color: #04070E; font-weight: 700; font-size: 12px;
  font-family: var(--font-display);
}

.account-name { max-width: 14ch; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.account-chev { opacity: .6; transition: transform .2s; flex: none; }
.account-btn[aria-expanded="true"] .account-chev { transform: rotate(180deg); }

.account-menu {
  position: absolute; right: 0; top: calc(100% + 10px); min-width: 210px;
  background: var(--panel); border: 1px solid var(--rule-strong);
  border-radius: 12px; padding: 6px; z-index: 120;
  box-shadow: 0 18px 44px rgba(0,0,0,.4);
  display: flex; flex-direction: column; gap: 1px;
  animation: menu-in .16s cubic-bezier(.22,.61,.36,1);
}
.account-menu[hidden] { display: none; }

@keyframes menu-in {
  from { opacity: 0; transform: translateY(-6px); }
  to   { opacity: 1; transform: none; }
}

.account-head { padding: 10px 12px 12px; border-bottom: 1px solid var(--rule); margin-bottom: 5px; }
.account-head-name { color: var(--text-hi); font-size: 13.5px; font-weight: 600; }
.account-head-role {
  font-family: var(--font-mono); font-size: 10px; letter-spacing: .12em;
  text-transform: uppercase; color: var(--muted); margin-top: 3px;
}

.account-menu a {
  padding: 9px 12px; border-radius: 8px; text-decoration: none;
  color: var(--text); font-size: 13.5px; font-family: var(--font-body);
  transition: background .12s, color .12s;
}
.account-menu a:hover { background: var(--panel-hi); color: var(--text-hi); }

.account-out {
  border-top: 1px solid var(--rule); margin-top: 5px; padding-top: 12px !important;
  border-radius: 0 0 8px 8px !important; color: var(--muted) !important;
}
.account-out:hover { color: var(--danger) !important; }

.nav-cta {
  font-family: var(--font-mono); font-size: 12.5px; text-decoration: none;
  padding: 8px 16px; border-radius: 100px; margin-left: 8px;
  background: linear-gradient(100deg, var(--violet), var(--cyan));
  color: #04070E; font-weight: 700; white-space: nowrap;
  transition: transform .2s, box-shadow .2s;
}
.nav-cta:hover { transform: translateY(-1px); box-shadow: 0 8px 24px color-mix(in srgb, var(--violet) 40%, transparent); color: #04070E; }
.nav-links a.nav-cta.active {
  background: linear-gradient(100deg, var(--violet), var(--cyan));
  color: #04070E; box-shadow: 0 6px 20px color-mix(in srgb, var(--violet) 38%, transparent);
}

.burger {
  display: none; margin-left: auto; background: none; border: 1px solid var(--rule-strong);
  border-radius: 8px; width: 40px; height: 36px; cursor: pointer; padding: 0;
  align-items: center; justify-content: center; flex-direction: column; gap: 4px;
}
.burger span { display: block; width: 16px; height: 1.5px; background: var(--text-hi); transition: transform .25s, opacity .25s; }
.burger[aria-expanded="true"] span:nth-child(1) { transform: translateY(5.5px) rotate(45deg); }
.burger[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
.burger[aria-expanded="true"] span:nth-child(3) { transform: translateY(-5.5px) rotate(-45deg); }

/* --- Hero ---------------------------------------------------------------- */

/* The animated backdrop, fixed behind the entire document.
   A negative z-index puts it behind everything without a blanket rule on
   body's children — an earlier attempt used
   `body > *:not(#backdrop) { position: relative }`, which outranks `.nav`
   on specificity and quietly stripped `position: fixed` from the header. */
#backdrop {
  position: fixed; inset: 0; width: 100%; height: 100%;
  display: block; z-index: -1; pointer-events: none;
}

.hero {
  position: relative; min-height: 100vh; min-height: 100svh;
  display: grid; place-items: center;
  padding: calc(var(--nav-h) + 40px) 24px 80px;
  /* Nothing is clipped here. overflow:hidden cut the blurred glow off dead
     along the hero's top edge, which read as a lighter band across the page
     under the header — exactly what blurring it is meant to avoid. The grid
     is what needed clipping, and it clips itself instead. */
}

.hero-glow {
  position: absolute; left: 50%; top: 42%; transform: translate(-50%,-50%);
  width: min(1100px, 130vw); aspect-ratio: 1; pointer-events: none;
  /* Sits over the canvas, so it has to stay faint — at 26% it drowned the
     starfield in exactly the area the hero occupies. */
  background:
    radial-gradient(circle at 42% 45%, color-mix(in srgb, var(--violet) 11%, transparent) 0%, transparent 58%),
    radial-gradient(circle at 62% 58%, color-mix(in srgb, var(--cyan) 8%, transparent) 0%, transparent 55%);
  filter: blur(56px);
  animation: drift 22s ease-in-out infinite alternate;
}
@keyframes drift {
  from { transform: translate(-52%,-50%) scale(1); }
  to   { transform: translate(-46%,-46%) scale(1.16); }
}

/* A faint perspective grid, drifting toward the horizon. Gives the hero a
   floor without needing an image. */
.hero-grid {
  position: absolute; inset: auto 0 0 0; height: 45%;
  pointer-events: none; opacity: .5;
  /* The perspective tilt throws the far edges of the grid well outside the
     hero, so it clips itself. The hero used to do this for it, but that
     also clipped the glow and left a hard line under the header. */
  clip-path: inset(0);
  background-image:
    linear-gradient(to right, color-mix(in srgb, var(--accent) 8%, transparent) 1px, transparent 1px),
    linear-gradient(to bottom, color-mix(in srgb, var(--accent) 8%, transparent) 1px, transparent 1px);
  background-size: 64px 64px;
  transform: perspective(340px) rotateX(58deg);
  transform-origin: bottom center;
  mask-image: linear-gradient(to bottom, transparent, #000 55%, transparent);
  -webkit-mask-image: linear-gradient(to bottom, transparent, #000 55%, transparent);
  animation: grid-drift 9s linear infinite;
}
@keyframes grid-drift {
  from { background-position: 0 0; }
  to   { background-position: 0 64px; }
}

.hero-inner { position: relative; z-index: 2; text-align: center; max-width: 900px; }


.hero-tag {
  display: inline-flex; align-items: center; gap: 9px;
  font-family: var(--font-mono); font-size: 11.5px; letter-spacing: .16em;
  text-transform: uppercase; color: var(--text);
  border: 1px solid var(--rule-strong); border-radius: 100px;
  padding: 7px 16px; margin-bottom: 30px;
  background: color-mix(in srgb, var(--panel) 70%, transparent);
  backdrop-filter: blur(8px);
}
.hero-tag i {
  width: 6px; height: 6px; border-radius: 50%; background: var(--cyan);
  box-shadow: 0 0 8px var(--cyan); animation: pulse 2.4s ease-in-out infinite;
}

h1 {
  font-family: var(--font-display); font-weight: 700;
  font-size: clamp(2.4rem, 1rem + 6vw, 5.2rem); line-height: 1.02;
  letter-spacing: -.035em; color: var(--text-hi);
  margin: 0 0 26px; text-wrap: balance;
}
h1 .grad {
  background: linear-gradient(100deg, var(--violet) 10%, var(--cyan) 60%, var(--hot) 115%);
  -webkit-background-clip: text; background-clip: text; color: transparent;
}

.hero p {
  font-size: clamp(1rem, .92rem + .38vw, 1.2rem); color: var(--text);
  max-width: 60ch; margin: 0 auto 36px; line-height: 1.65;
}

.hero-actions { display: flex; gap: 12px; justify-content: center; flex-wrap: wrap; }

.btn {
  font-family: var(--font-mono); font-size: .875rem; text-decoration: none;
  padding: 13px 26px; border-radius: 100px; border: 1px solid var(--rule-strong);
  color: var(--text-hi); background: color-mix(in srgb, var(--panel) 80%, transparent);
  display: inline-flex; align-items: center; gap: 9px; cursor: pointer;
  transition: transform .2s, border-color .2s, color .2s, box-shadow .2s;
  backdrop-filter: blur(8px);
}
.btn:hover { transform: translateY(-2px); border-color: var(--accent); color: var(--accent); }

.btn-primary {
  background: linear-gradient(100deg, var(--violet), var(--cyan));
  border-color: transparent; color: #04070E; font-weight: 700;
}
.btn-primary:hover { color: #04070E; box-shadow: 0 12px 34px color-mix(in srgb, var(--violet) 45%, transparent); }

/* --- Sections ------------------------------------------------------------ */

/* Sections are translucent so the animated backdrop shows through the whole
   page. A solid fill here is what made everything below the hero flat. */
.sec {
  padding: clamp(72px, 11vh, 128px) clamp(16px, 4vw, 40px);
  position: relative; z-index: 1;
}

.sec-alt {
  background: color-mix(in srgb, var(--ground-2) 78%, transparent);
  border-block: 1px solid var(--rule);
  backdrop-filter: blur(2px);
  -webkit-backdrop-filter: blur(2px);
}

/* An aurora that fades in as the section arrives, so scrolling reveals
   depth instead of cutting to a flat panel. Alternating sides keep it from
   reading as a repeated motif. */
.sec::before {
  content: ""; position: absolute; inset: 0; pointer-events: none; z-index: -1;
  opacity: 0; transition: opacity 1.4s ease;
  background:
    radial-gradient(60% 55% at 18% 0%, color-mix(in srgb, var(--violet) 7%, transparent), transparent 70%),
    radial-gradient(50% 50% at 88% 100%, color-mix(in srgb, var(--accent) 5%, transparent), transparent 72%);
}
.sec:nth-of-type(even)::before {
  background:
    radial-gradient(58% 52% at 82% 4%, color-mix(in srgb, var(--accent) 6%, transparent), transparent 70%),
    radial-gradient(52% 50% at 12% 96%, color-mix(in srgb, var(--hot) 5%, transparent), transparent 72%);
}
.sec.lit::before { opacity: 1; }

.inner { max-width: var(--maxw); margin: 0 auto; position: relative; z-index: 1; }

.sec-head { margin-bottom: 52px; }

.eyebrow {
  font-family: var(--font-mono); font-size: 11px; letter-spacing: .2em;
  text-transform: uppercase; color: var(--accent); margin: 0 0 14px;
  display: flex; align-items: center; gap: 12px;
}
/* The rule draws itself out when the section arrives. */
.eyebrow::after {
  content: ""; height: 1px; flex: 1;
  background: linear-gradient(90deg, var(--accent), var(--rule-strong) 22%, transparent);
  transform-origin: left;
  transform: scaleX(0);
  transition: transform 1.1s cubic-bezier(.22,.61,.36,1) .15s;
}
.rv.in .eyebrow::after,
.sec.lit .eyebrow::after { transform: scaleX(1); }

h2 {
  font-family: var(--font-display); font-weight: 700;
  font-size: clamp(1.7rem, 1.1rem + 2.2vw, 2.7rem); line-height: 1.12;
  letter-spacing: -.025em; color: var(--text-hi); margin: 0 0 16px; text-wrap: balance;
}

.sec-head p { font-size: 1.05rem; color: var(--muted); max-width: var(--measure); margin: 0; }

h3 { font-family: var(--font-display); font-size: 1.15rem; font-weight: 700; color: var(--text-hi); margin: 0 0 10px; letter-spacing: -.01em; }

/* --- Reveal -------------------------------------------------------------- */

.rv { opacity: 0; transform: translateY(26px); transition: opacity .7s cubic-bezier(.22,.61,.36,1), transform .7s cubic-bezier(.22,.61,.36,1); }
.rv.in { opacity: 1; transform: none; }

/* --- Cards --------------------------------------------------------------- */

.cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 20px; }

.card {
  position: relative; background: var(--panel); border: 1px solid var(--rule);
  border-radius: 16px; padding: 28px; overflow: hidden;
  text-decoration: none; color: inherit; display: flex; flex-direction: column; gap: 14px;
  transition: transform .3s cubic-bezier(.22,.61,.36,1), border-color .3s, box-shadow .3s;
}
.card::before {
  content: ""; position: absolute; inset: 0; opacity: 0; transition: opacity .35s;
  background: radial-gradient(520px circle at var(--mx,50%) var(--my,0%), color-mix(in srgb, var(--violet) 13%, transparent), transparent 62%);
  pointer-events: none;
}
.card:hover {
  transform: translateY(-5px) perspective(900px) rotateX(var(--rx, 0deg)) rotateY(var(--ry, 0deg));
  border-color: var(--rule-strong);
  box-shadow: 0 18px 44px rgba(0,0,0,.34);
}
.card:hover::before { opacity: 1; }
.card > * { position: relative; z-index: 1; }

/* A light sweep along the top edge on hover, following the accent. */
.card::after {
  content: ""; position: absolute; inset: 0 0 auto 0; height: 1px;
  background: linear-gradient(90deg, transparent, var(--accent), transparent);
  opacity: 0; transform: translateX(-100%);
  transition: opacity .3s;
  pointer-events: none;
}
.card:hover::after { opacity: .7; animation: sweep 1.1s cubic-bezier(.22,.61,.36,1); }
@keyframes sweep {
  from { transform: translateX(-100%); }
  to   { transform: translateX(100%); }
}

.card-top { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.card h3 { margin: 0; }
.card p { margin: 0; color: var(--muted); font-size: .94rem; }

.card-media {
  margin: -28px -28px 0; aspect-ratio: 16/9; overflow: hidden;
  background: var(--panel-hi); border-bottom: 1px solid var(--rule);
}
.card-media img { width: 100%; height: 100%; object-fit: cover; transition: transform .5s cubic-bezier(.22,.61,.36,1); }
.card:hover .card-media img { transform: scale(1.04); }

.tags { display: flex; flex-wrap: wrap; gap: 7px; margin-top: auto; padding-top: 6px; }
.tag { font-family: var(--font-mono); font-size: 10.5px; color: var(--muted); border: 1px solid var(--rule); border-radius: 5px; padding: 3px 9px; }

.card-go { font-family: var(--font-mono); font-size: 12px; color: var(--accent); display: inline-flex; align-items: center; gap: 7px; }
.card-go span { transition: transform .25s; }
.card:hover .card-go span { transform: translateX(4px); }

.byline { font-family: var(--font-mono); font-size: 11px; color: var(--muted); }

/* --- Pills --------------------------------------------------------------- */

.pill {
  font-family: var(--font-mono); font-size: 9.5px; letter-spacing: .13em; text-transform: uppercase;
  padding: 5px 11px; border-radius: 100px; border: 1px solid currentColor;
  display: inline-flex; align-items: center; gap: 6px; line-height: 1.4; white-space: nowrap;
}
.pill::before { content: ""; width: 5px; height: 5px; border-radius: 50%; background: currentColor; }
.pill-live { color: var(--cyan); }
.pill-progress { color: var(--warn); }
.pill-soon, .pill-archived { color: var(--muted); }
.pill-soon::before { background: transparent; box-shadow: inset 0 0 0 1px currentColor; }
.pill-community { color: var(--violet); }

/* --- Empty state --------------------------------------------------------- */

.empty {
  border: 1px dashed var(--rule-strong); border-radius: 14px;
  padding: clamp(32px, 6vw, 56px) 28px; text-align: center;
  color: var(--muted); font-size: .95rem;
}
.empty strong { display: block; color: var(--text-hi); font-family: var(--font-display); font-size: 1.1rem; margin-bottom: 8px; }
.empty .btn { margin-top: 20px; }

/* --- Split --------------------------------------------------------------- */

.split { display: grid; grid-template-columns: 1.05fr .95fr; gap: clamp(28px, 5vw, 64px); align-items: center; }

.feat { list-style: none; padding: 0; margin: 22px 0 0; display: grid; gap: 11px; }
.feat li { padding-left: 26px; position: relative; font-size: .96rem; }
.feat li::before { content: "→"; position: absolute; left: 0; color: var(--accent); font-family: var(--font-mono); }

/* --- Code ---------------------------------------------------------------- */

.code {
  background: var(--panel); border: 1px solid var(--rule); border-radius: 12px;
  padding: 20px 22px; overflow-x: auto; font-family: var(--font-mono);
  font-size: .84rem; line-height: 1.75; color: var(--text); margin: 0;
}
.code .c { color: var(--muted); }
.code .p { color: var(--cyan); }
code:not(.code code) { font-family: var(--font-mono); font-size: .88em; background: var(--panel); border: 1px solid var(--rule); border-radius: 4px; padding: .12em .4em; color: var(--text-hi); }

.note { border-left: 2px solid var(--rule-strong); padding: 8px 0 8px 20px; color: var(--muted); font-size: .92rem; max-width: var(--measure); margin: 22px 0 0; }
.note strong { color: var(--text); font-weight: 600; }

/* --- Forms --------------------------------------------------------------- */

.form { display: grid; gap: 18px; max-width: 640px; }
.form-row { display: grid; gap: 7px; }
.form-row.two { grid-template-columns: 1fr 1fr; gap: 18px; }
@media (max-width: 620px) { .form-row.two { grid-template-columns: 1fr; } }

label {
  font-family: var(--font-mono); font-size: 11px; letter-spacing: .1em;
  text-transform: uppercase; color: var(--muted);
}
label .req { color: var(--hot); }

input[type=text], input[type=email], input[type=url], input[type=password],
input[type=number], textarea, select {
  width: 100%; padding: 12px 15px; border-radius: 10px;
  border: 1px solid var(--rule-strong); background: var(--panel);
  color: var(--text-hi); font-family: var(--font-body); font-size: .96rem;
  transition: border-color .2s, box-shadow .2s;
}
input:focus, textarea:focus, select:focus {
  outline: none; border-color: var(--accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 18%, transparent);
}
textarea { resize: vertical; min-height: 130px; line-height: 1.6; }
.hint { font-size: .82rem; color: var(--muted); }

input[type=file] {
  width: 100%; padding: 14px; border-radius: 10px; color: var(--muted);
  border: 1px dashed var(--rule-strong); background: var(--panel);
  font-family: var(--font-mono); font-size: .82rem; cursor: pointer;
}
input[type=file]::file-selector-button {
  font-family: var(--font-mono); font-size: .8rem; margin-right: 12px;
  padding: 7px 14px; border-radius: 100px; cursor: pointer;
  border: 1px solid var(--rule-strong); background: var(--panel-hi); color: var(--text-hi);
}

/* Honeypot — hidden from people, visible to naive bots. */
.hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

/* --- Alerts -------------------------------------------------------------- */

.alert {
  border-radius: 10px; padding: 14px 18px; font-size: .93rem;
  border: 1px solid; display: flex; gap: 11px; align-items: flex-start;
}
.alert-success { color: var(--ok);     border-color: color-mix(in srgb, var(--ok) 40%, transparent);     background: color-mix(in srgb, var(--ok) 8%, transparent); }
.alert-error   { color: var(--danger); border-color: color-mix(in srgb, var(--danger) 40%, transparent); background: color-mix(in srgb, var(--danger) 8%, transparent); }
.alert-info    { color: var(--text);   border-color: var(--rule-strong);                                 background: var(--panel); }
.alert-warning { color: var(--warn);   border-color: color-mix(in srgb, var(--warn) 40%, transparent);   background: color-mix(in srgb, var(--warn) 8%, transparent); }

/* --- Gallery ------------------------------------------------------------- */

.gallery { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 12px; margin-top: 20px; }
.gallery a { display: block; border-radius: 10px; overflow: hidden; border: 1px solid var(--rule); aspect-ratio: 4/3; background: var(--panel-hi); }
.gallery img { width: 100%; height: 100%; object-fit: cover; transition: transform .4s; }
.gallery a:hover img { transform: scale(1.05); }

/* --- Areas ---------------------------------------------------------------- */
/* Each part of the site gets a full section that explains it: a lead
   paragraph, three concrete points, and one way in. Sides alternate so four
   explanations do not read as one repeated row. */

.area-split {
  display: grid; grid-template-columns: 1.05fr .95fr;
  gap: clamp(32px, 6vw, 72px); align-items: center;
}
.area-split.flip .area-text   { order: 2; }
.area-split.flip .area-visual { order: 1; }

.area-lead {
  font-size: 1.06rem; line-height: 1.65; color: var(--text);
  max-width: var(--measure); margin: 0;
}

.area-text .feat { margin-top: 24px; }
.area-text h2 { margin-bottom: 16px; }

/* --- Area illustrations --------------------------------------------------- */
/* Abstract rather than literal: they suggest the shape of each thing without
   pretending to be a screenshot of software that may not exist yet. */

.area-visual { min-width: 0; }

/* The stack itself, named. More use to another homelabber than an
   illustration would be. */
.stack-grid {
  display: flex; flex-wrap: wrap; gap: 10px;
  background: var(--panel); border: 1px solid var(--rule);
  border-radius: 14px; padding: 24px;
}
.stack-item {
  font-family: var(--font-mono); font-size: .82rem;
  color: var(--text-hi); background: var(--ground);
  border: 1px solid var(--rule-strong); border-radius: 100px;
  padding: 8px 15px; white-space: nowrap;
  transition: border-color .2s, color .2s;
}
.stack-item:hover { border-color: var(--accent); color: var(--accent); }

/* Showcase: the shape of a gallery, suggested with the kind of thing
   members put up rather than with blank tiles. */
.showcase-preview {
  display: grid; grid-template-columns: 1fr 1fr; gap: 12px;
}
/* Built like a testimonial card: who posted it at the top, what they made
   underneath. The avatar matches the one in the account menu, so a sample
   card looks like a real member's post. */
.showcase-card {
  display: grid; gap: 12px; align-content: start;
  padding: 18px;
  background: var(--panel); border: 1px solid var(--rule);
  border-radius: 12px;
  transition: border-color .2s, transform .25s cubic-bezier(.22,.61,.36,1);
}
.showcase-card:hover { border-color: var(--rule-strong); transform: translateY(-3px); }

.showcase-head { display: flex; align-items: center; gap: 9px; }

.showcase-avatar {
  width: 26px; height: 26px; border-radius: 50%; flex: none;
  display: grid; place-items: center;
  font-family: var(--font-display); font-size: 12px; font-weight: 700;
  color: #04070E; text-transform: uppercase;
  background: linear-gradient(135deg, var(--violet), var(--cyan));
}
.showcase-avatar.tint-1 { background: linear-gradient(135deg, var(--cyan), var(--ok)); }
.showcase-avatar.tint-2 { background: linear-gradient(135deg, var(--hot), var(--violet)); }
.showcase-avatar.tint-3 { background: linear-gradient(135deg, var(--warn), var(--hot)); }

.showcase-name {
  font-family: var(--font-mono); font-size: 12px; color: var(--text);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

.showcase-what {
  margin: 0; font-size: .9rem; color: var(--muted); line-height: 1.5;
}

@media (max-width: 520px) {
  .showcase-preview { grid-template-columns: 1fr; }
}

/* Still used by the Repository section. */
.entry-anatomy {
  background: var(--panel); border: 1px solid var(--rule);
  border-radius: 14px; padding: 26px 28px;
}
.entry-anatomy-head {
  font-family: var(--font-mono); font-size: 10.5px; letter-spacing: .14em;
  text-transform: uppercase; color: var(--muted); margin: 0 0 16px;
}
.entry-anatomy ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 12px; }
.entry-anatomy li {
  font-size: .93rem; color: var(--muted); padding-left: 20px; position: relative;
}
.entry-anatomy li::before {
  content: ""; position: absolute; left: 0; top: .55em;
  width: 6px; height: 6px; border-radius: 50%; background: var(--accent); opacity: .7;
}
.entry-anatomy strong { color: var(--text-hi); font-weight: 600; }

/* Forum: the kind of question the board is for, in words. */
.thread-hint {
  background: var(--panel); border: 1px solid var(--rule);
  border-radius: 14px; padding: 10px; display: grid; gap: 2px;
}
.thread-item {
  display: grid; gap: 5px; padding: 14px 16px; border-radius: 9px;
  transition: background .2s;
}
.thread-item:hover { background: var(--panel-hi); }
.thread-q { font-size: .93rem; color: var(--text-hi); line-height: 1.4; }
.thread-meta { font-family: var(--font-mono); font-size: 10.5px; color: var(--muted); }

@media (max-width: 860px) {
  .area-split { grid-template-columns: 1fr; }
  /* On one column the text always comes first, whatever the desktop order. */
  .area-split.flip .area-text   { order: 1; }
  .area-split.flip .area-visual { order: 2; }
}

/* --- Showcase submission CTA --------------------------------------------- */
/* Sits under the showcase grid and explains what submitting actually does,
   so the button is never a bare instruction with no context. */

.submit-cta {
  margin-top: 36px; padding: 26px 30px;
  background: var(--panel); border: 1px solid var(--rule); border-radius: 16px;
  display: flex; align-items: center; gap: 28px; flex-wrap: wrap;
}
.submit-cta h3 { margin: 0 0 6px; font-size: 1.05rem; }
.submit-cta p { margin: 0; color: var(--muted); font-size: .93rem; max-width: 54ch; }
.submit-cta .btn { margin-left: auto; flex: none; }

@media (max-width: 700px) {
  .submit-cta { flex-direction: column; align-items: flex-start; gap: 18px; }
  .submit-cta .btn { margin-left: 0; }
}

/* --- CTA ----------------------------------------------------------------- */

.cta-box { text-align: center; border: 1px solid var(--rule); border-radius: 20px; padding: clamp(40px, 7vw, 72px) 28px; background: var(--panel); position: relative; overflow: hidden; }
.cta-box::before {
  content: ""; position: absolute; inset: -50% -10% auto; height: 320px;
  background: radial-gradient(ellipse at 50% 0%, color-mix(in srgb, var(--violet) 20%, transparent), transparent 68%);
  filter: blur(38px); pointer-events: none;
}
.cta-box > * { position: relative; }
.cta-box h2 { margin-bottom: 14px; }
.cta-box p { color: var(--muted); max-width: 52ch; margin: 0 auto 30px; }

/* --- Sign in / register -------------------------------------------------- */

.auth-body { display: grid; place-items: center; min-height: 100vh; padding: 40px 20px; }
.auth-wrap { width: 100%; }
.auth-box { width: 100%; max-width: 420px; margin: 0 auto; }

.auth-brand {
  display: flex; align-items: center; justify-content: center;
  color: var(--text-hi); text-decoration: none; margin-bottom: 24px;
}
/* A composed lockup rather than the two images side by side, so its height
   covers the mark and the wordmark together. 1.35 of the mark height puts
   the mark inside it at about the size it is everywhere else. */
.auth-logo {
  height: calc(var(--logo-h) * 1.35);
  width: auto; max-width: min(78vw, 300px);
  object-fit: contain; display: block;
}

.auth-card {
  background: var(--panel); border: 1px solid var(--rule);
  border-radius: 18px; padding: 34px;
}
.auth-card h1 {
  font-size: 1.5rem; margin: 0 0 8px; letter-spacing: -.02em; line-height: 1.2;
}
.auth-sub { color: var(--muted); font-size: .93rem; margin: 0 0 24px; }
.auth-card .form { max-width: none; }
.auth-card .alert { margin-bottom: 20px; }

.btn-full { width: 100%; justify-content: center; }

.auth-alt {
  text-align: center; margin: 22px 0 0; font-size: .9rem; color: var(--muted);
}
.auth-back {
  text-align: center; margin: 20px 0 0;
  font-family: var(--font-mono); font-size: 12px;
}
.auth-back a { color: var(--muted); text-decoration: none; }
.auth-back a:hover { color: var(--accent); }

/* --- Two-factor ---------------------------------------------------------- */

/* A one-time code is read digit by digit, so give it monospace and spacing. */
.code-input {
  font-family: var(--font-mono) !important;
  font-size: 1.5rem !important;
  letter-spacing: .4em;
  text-align: center;
  padding: 14px !important;
}
.code-input::placeholder { letter-spacing: .4em; opacity: .3; }

.totp-setup {
  display: flex; gap: 32px; flex-wrap: wrap; align-items: flex-start;
  background: var(--panel); border: 1px solid var(--rule);
  border-radius: 16px; padding: 28px; max-width: 720px;
}
.totp-qr {
  flex: none; background: #fff; padding: 12px; border-radius: 12px;
  line-height: 0;
}
.totp-manual { flex: 1; min-width: 260px; }

.totp-secret {
  display: block; font-family: var(--font-mono); font-size: .95rem;
  letter-spacing: .08em; word-break: break-all;
  background: var(--ground); border: 1px solid var(--rule-strong);
  border-radius: 8px; padding: 12px 14px; color: var(--text-hi);
}

.recovery-codes {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  gap: 10px; max-width: 640px; margin-top: 16px;
  background: var(--panel); border: 1px solid var(--rule-strong);
  border-radius: 12px; padding: 20px;
}
.recovery-codes span {
  font-family: var(--font-mono); font-size: .95rem; letter-spacing: .05em;
  color: var(--text-hi); text-align: center; padding: 7px 4px;
  background: var(--ground); border-radius: 6px;
}

.two-col {
  display: grid; grid-template-columns: 1fr 1fr; gap: 28px;
  max-width: 760px; margin-top: 8px;
}
.two-col > form {
  background: var(--panel); border: 1px solid var(--rule);
  border-radius: 14px; padding: 22px;
}
@media (max-width: 700px) { .two-col { grid-template-columns: 1fr; } }

.auth-details {
  margin-top: 20px; font-size: .9rem; color: var(--muted);
  border-top: 1px solid var(--rule); padding-top: 16px;
}
.auth-details summary { cursor: pointer; color: var(--text); }
.auth-details p { margin: 10px 0 0; line-height: 1.6; }

.btn-danger {
  color: var(--danger); border-color: color-mix(in srgb, var(--danger) 45%, transparent);
}
.btn-danger:hover {
  background: color-mix(in srgb, var(--danger) 12%, transparent);
  color: var(--danger); border-color: var(--danger);
}

/* Folded away, and tinted so that opening it feels like a different kind of
   action from changing a display name. */
.danger {
  border: 1px solid color-mix(in srgb, var(--danger) 30%, transparent);
  border-radius: 12px;
  background: color-mix(in srgb, var(--danger) 5%, transparent);
  max-width: 640px;
}
.danger > summary {
  cursor: pointer; padding: 14px 18px;
  font-family: var(--font-mono); font-size: 12.5px;
  letter-spacing: .04em; color: var(--danger);
}
.danger > summary:hover { color: var(--danger); text-decoration: underline; }
.danger[open] > summary {
  border-bottom: 1px solid color-mix(in srgb, var(--danger) 22%, transparent);
}
.danger-body { padding: 18px; }
.danger-body p { margin: 0 0 12px; font-size: 13.5px; line-height: 1.7; color: var(--muted); }
.danger-body strong { color: var(--text-hi); }
.danger-body .form { margin-top: 18px; }

/* --- Footer -------------------------------------------------------------- */

/* The rule is faint on purpose: the footer should read as the end of the
   page rather than a box bolted to the bottom of it. */
.foot {
  border-top: 1px solid var(--rule);
  padding: 54px clamp(16px, 4vw, 40px) 34px;
  background: color-mix(in srgb, var(--ground) 55%, transparent);
}
.foot-in {
  max-width: var(--maxw); margin: 0 auto;
  display: grid; gap: 40px;
  grid-template-columns: minmax(220px, 1fr) 2fr;
}
.foot-in a { color: var(--muted); text-decoration: none; transition: color .15s; }
.foot-in a:hover { color: var(--accent); }

/* The same lockup as the bar, one size up: the footer has room, and the
   tagline set into the wordmark is legible here where it is not at 22px. */
.foot-brand { display: flex; }
.foot-logo { display: flex; align-items: center; gap: 11px; }
.foot-mark { height: calc(var(--logo-h) * 1.2); width: auto; flex: none; }
.foot-word { height: calc(var(--logo-h) * 1.2 * var(--logo-word)); width: auto; flex: none; }

.foot-nav {
  display: grid; gap: 28px;
  grid-template-columns: repeat(auto-fit, minmax(130px, 1fr));
}
.foot-col { display: flex; flex-direction: column; gap: 9px; }
.foot-col h2 {
  margin: 0 0 3px; font-family: var(--font-mono); font-size: 10.5px;
  letter-spacing: .12em; text-transform: uppercase; color: var(--text-hi);
  font-weight: 700;
}
.foot-col a { font-size: 13px; }

/* Sits under both columns, so it spans the whole grid. */
.foot-base {
  grid-column: 1 / -1;
  display: flex; flex-wrap: wrap; gap: 14px;
  align-items: center; justify-content: space-between;
  margin-top: 8px; padding-top: 22px;
  border-top: 1px solid var(--rule);
}
.foot-copy {
  margin: 0; font-family: var(--font-mono); font-size: 11.5px;
  color: var(--muted);
}

@media (max-width: 720px) {
  .foot-in { grid-template-columns: 1fr; gap: 32px; }
}

/* Shows the theme you would switch TO, which is the convention people
   expect: a moon while you are in light, a sun while you are in dark. */
.theme-toggle {
  display: inline-flex; align-items: center; justify-content: center;
  width: 30px; height: 30px; padding: 0; cursor: pointer;
  background: none; border: 1px solid var(--rule-strong); border-radius: 8px;
  color: var(--muted); transition: color .15s, border-color .15s, background .15s;
}
.theme-toggle:hover { color: var(--accent); border-color: var(--accent); background: var(--panel); }

.theme-toggle .icon-sun { display: none; }
.theme-toggle .icon-moon { display: block; }

:root[data-theme="dark"] .theme-toggle .icon-sun { display: block; }
:root[data-theme="dark"] .theme-toggle .icon-moon { display: none; }

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .theme-toggle .icon-sun { display: block; }
  :root:not([data-theme="light"]) .theme-toggle .icon-moon { display: none; }
}

/* --- Detail pages -------------------------------------------------------- */

.page { padding: calc(var(--nav-h) + clamp(48px, 8vh, 88px)) clamp(16px,4vw,40px) clamp(60px, 9vh, 100px); }
.back { font-family: var(--font-mono); font-size: 12px; color: var(--muted); text-decoration: none; display: inline-flex; gap: 8px; margin-bottom: 24px; }
.back:hover { color: var(--accent); }
.prose { max-width: var(--measure); }
.prose p { margin: 0 0 1.1em; }
.prose p:last-child { margin-bottom: 0; }

/* Long-form pages — the privacy policy and the terms. Nobody reads a wall
   of undifferentiated text, and terms nobody reads protect nobody, so the
   headings and lists are given room to be scanned. */
.prose h1 { font-size: clamp(2rem, 1.4rem + 2.2vw, 2.7rem); margin: 0 0 14px; }
.prose h2 {
  font-size: 1.25rem; margin: 2.2em 0 .7em; color: var(--text-hi);
  letter-spacing: -.01em;
}
.prose h3 {
  font-size: 1rem; margin: 1.6em 0 .5em; color: var(--text-hi);
  font-weight: 600;
}
.prose .lede {
  font-size: 1.05rem; color: var(--text); margin-bottom: 2em;
  line-height: 1.75;
}
.prose ul { margin: 0 0 1.2em; padding-left: 1.3em; }
.prose li { margin-bottom: .55em; line-height: 1.7; }
.prose li:last-child { margin-bottom: 0; }
.prose strong { color: var(--text-hi); font-weight: 600; }
.prose a { color: var(--accent); text-decoration: underline; text-underline-offset: 3px; }
.prose a:hover { color: var(--accent-hi, var(--accent)); }
.prose code {
  font-family: var(--font-mono); font-size: .88em;
  background: var(--panel); padding: 2px 6px; border-radius: 5px;
}

.meta-row { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; margin: 18px 0 30px; }

/* --- Responsive ---------------------------------------------------------- */

@media (max-width: 860px) {
  .split { grid-template-columns: 1fr; }

  .burger { display: flex; }
  .nav-links {
    position: fixed; inset: var(--nav-h) 0 auto 0; flex-direction: column;
    align-items: stretch; gap: 0; margin: 0; padding: 10px 16px 20px;
    background: color-mix(in srgb, var(--ground) 97%, transparent);
    backdrop-filter: blur(16px); border-bottom: 1px solid var(--rule);
    transform: translateY(-8px); opacity: 0; pointer-events: none;
    transition: opacity .22s, transform .22s;
  }
  .nav-links.open { opacity: 1; transform: none; pointer-events: auto; }

  /* The bar is transparent at the top of the page, which is right until the
     menu is open beneath it: the panel would otherwise hang off a bar you
     can see straight through. */
  .nav:has(.nav-links.open) {
    background: color-mix(in srgb, var(--ground) 97%, transparent);
    backdrop-filter: blur(16px);
    -webkit-backdrop-filter: blur(16px);
  }

  .nav-links a { padding: 13px 14px; border-radius: 8px; font-size: 14px; }
  .nav-cta { margin: 8px 0 0; text-align: center; }

  /* Stacked menu: the account control becomes a normal block, and its
     dropdown sits inline rather than floating over the page. */
  .account { margin: 8px 0 0; border-top: 1px solid var(--rule); padding-top: 10px; }
  .account-btn { width: 100%; justify-content: flex-start; padding: 10px; }
  .account-name { max-width: none; }
  .account-chev { margin-left: auto; }
  .account-menu {
    position: static; min-width: 0; margin-top: 6px;
    box-shadow: none; animation: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: .01ms !important; animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
  }
  .rv { opacity: 1; transform: none; }

  /* Everything added for atmosphere still needs to end up in its final,
     readable state rather than stuck mid-animation. */
  .sec::before { opacity: 1; }
  .eyebrow::after { transform: scaleX(1); }
  .hero-grid { animation: none; }
  .card:hover { transform: translateY(-2px); }
  .card:hover::after { animation: none; opacity: 0; }
}
