/* =========================================================
   Nodebug — dev hub, adapted from the Recto template
   Dark terminal aesthetic. Type does the work.
   ========================================================= */

:root {
  /* palette — terminal dark */
  --paper:        #0a0a0a;
  --paper-soft:   #161616;
  --ink:          #f2f2f2;
  --ink-soft:     #a8a8a8;
  --ink-mute:     #707070;
  --line:         rgba(255, 255, 255, 0.12);
  --line-strong:  rgba(255, 255, 255, 0.24);
  --line-soft:    rgba(255, 255, 255, 0.08);

  /* radii — sharp */
  --r-sm: 0;
  --r:    0;
  --r-lg: 0;

  /* motion */
  --ease:      cubic-bezier(0.2, 0.8, 0.2, 1);
  --ease-out:  cubic-bezier(0.16, 1, 0.3, 1);

  /* layout */
  --container: 1320px;
  --container-narrow: 760px;
  --pad-x: clamp(20px, 4vw, 64px);
  --pad-section: clamp(56px, 6.5vw, 100px);

  /* type */
  --display: 'JetBrains Mono', 'IBM Plex Mono', ui-monospace, 'SF Mono', Menlo, monospace;
  --sans:    'Inter Tight', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  --mono:    'IBM Plex Mono', ui-monospace, 'SF Mono', Menlo, monospace;

  --t-poster:  clamp(2.6rem, 2rem + 4.4vw, 7.2rem);
  --t-display: clamp(2.4rem, 1.4rem + 3.6vw, 4.6rem);
  --t-h2:      clamp(1.8rem, 1.2rem + 2.2vw, 3.2rem);
  --t-h3:      clamp(1.2rem, 1rem + 0.6vw, 1.5rem);
  --t-body:    clamp(1rem, 0.96rem + 0.16vw, 1.06rem);
  --t-small:   0.84rem;
  --t-mono:    0.74rem;
}

*, *::before, *::after { box-sizing: border-box; }
html { scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  margin: 0;
  font-family: var(--sans);
  font-size: var(--t-body);
  line-height: 1.6;
  color: var(--ink);
  background: var(--paper);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
}

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

h1, h2, h3, h4 {
  font-family: var(--display);
  font-weight: 400;
  margin: 0;
  letter-spacing: normal;
  line-height: 1;
  color: var(--ink);
}
h1 { font-size: var(--t-display); }
h2 { font-size: var(--t-h2); }
h3 { font-size: var(--t-h3); line-height: 1.2; letter-spacing: normal; }

p { margin: 0 0 1em; color: var(--ink-soft); }
a { color: inherit; text-decoration: none; transition: color 0.2s var(--ease), border-color 0.2s var(--ease); }

/* ───── label (replaces eyebrow-dot pattern) ───── */
/* a vertical rule + uppercase mono. NOT a dot. */
.label {
  display: inline-flex; align-items: center; gap: 14px;
  font-family: var(--mono);
  font-size: var(--t-mono);
  text-transform: uppercase;
  letter-spacing: 0.18em;
  color: var(--ink-mute);
  margin: 0 0 24px;
}
.label::before {
  content: '';
  display: inline-block;
  width: 1px;
  height: 16px;
  background: var(--ink);
}
.label.solid { color: var(--ink); }
.label.solid::before { background: var(--ink); }

.num {
  font-family: var(--mono);
  font-size: var(--t-mono);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-mute);
}

/* ───── utilities ───── */
.container { width: min(100% - var(--pad-x) * 2, var(--container)); margin-inline: auto; }
.container-narrow { width: min(100% - var(--pad-x) * 2, var(--container-narrow)); margin-inline: auto; }

/* ───── buttons ───── */
.btn {
  display: inline-flex; align-items: center; gap: 12px;
  padding: 0;
  margin: 0;
  appearance: none;
  -webkit-appearance: none;
  line-height: 1;
  vertical-align: middle;
  font-family: var(--mono);
  font-size: var(--t-small);
  font-weight: 400;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  cursor: pointer;
  background: transparent;
  border: 0;
  color: var(--ink);
  position: relative;
  padding-bottom: 6px;
}
.btn::after {
  content: '';
  position: absolute;
  left: 0; bottom: 0;
  width: 100%;
  height: 1px;
  background: var(--ink);
  transition: transform 0.4s var(--ease-out);
  transform-origin: left;
}
.btn:hover::after { transform: scaleX(0.5); }
.btn .arrow { display: inline-block; transition: transform 0.3s var(--ease-out); }
.btn:hover .arrow { transform: translateX(4px); }

.btn-solid {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  padding: 16px 28px;
  margin: 0;
  appearance: none;
  -webkit-appearance: none;
  font-family: var(--mono);
  font-size: var(--t-small);
  font-weight: 400;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  line-height: 1;
  background: var(--ink);
  color: var(--paper);
  border: 0;
  cursor: pointer;
}
.btn-solid::after { display: none; }
.btn-solid:hover { background: transparent; color: var(--ink); outline: 1px solid var(--ink); }

/* ───── header ───── */
.site-header {
  position: sticky; top: 0; z-index: 60;
  display: flex; justify-content: space-between;
  align-items: center;
  gap: 32px;
  padding: 22px var(--pad-x);
  background: color-mix(in oklab, var(--paper) 92%, transparent);
  backdrop-filter: saturate(140%) blur(14px);
  -webkit-backdrop-filter: saturate(140%) blur(14px);
  border-bottom: 1px solid var(--line-soft);
}
.brand {
  display: inline-flex; align-items: baseline; gap: 10px;
  color: var(--ink);
}
.brand-name {
  font-family: var(--display);
  font-size: 1.7rem;
  letter-spacing: normal;
  line-height: 1;
}
.brand-meta {
  font-family: var(--mono);
  font-size: 0.66rem;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--ink-mute);
}
.brand:hover .brand-name { font-style: italic; }

.site-nav {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  display: flex; gap: 32px;
}
.site-nav a {
  font-family: var(--mono);
  font-size: 0.78rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-soft);
  position: relative;
  padding: 6px 0;
}
.site-nav a:hover, .site-nav a.is-active { color: var(--ink); }
.site-nav a.is-active::after {
  content: ''; position: absolute;
  left: 0; right: 0; bottom: -2px;
  height: 1px; background: var(--ink);
}

.header-cta { display: flex; align-items: center; gap: 18px; }
.header-cta .meta {
  font-family: var(--mono);
  font-size: 0.7rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-mute);
}
.header-cta .meta strong { color: var(--ink); font-weight: 500; }

.menu-toggle {
  display: none;
  background: transparent;
  border: 1px solid var(--ink);
  width: 44px; height: 44px;
  border-radius: 0;
  padding: 0; cursor: pointer;
  flex-direction: column; justify-content: center; align-items: center; gap: 4px;
}
.menu-toggle span { display: block; width: 18px; height: 1px; background: var(--ink); transition: all 0.3s var(--ease); }
.menu-toggle[aria-expanded="true"] span:nth-child(1) { transform: translateY(5px) rotate(45deg); }
.menu-toggle[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
.menu-toggle[aria-expanded="true"] span:nth-child(3) { transform: translateY(-5px) rotate(-45deg); }

.site-mobile-nav {
  display: none;
  position: fixed; inset: 76px 0 auto 0; z-index: 55;
  flex-direction: column; gap: 0;
  padding: 32px var(--pad-x);
  background: var(--paper);
  border-bottom: 1px solid var(--line);
}
.site-mobile-nav a {
  font-family: var(--display);
  font-size: 2rem;
  padding: 16px 0;
  color: var(--ink);
  border-bottom: 1px solid var(--line-soft);
}
.site-mobile-nav.is-open { display: flex; }

/* ───── hero (composition G — type-only poster) ───── */
.hero {
  display: grid;
  grid-template-columns: 1fr;
  padding: clamp(40px, 5vw, 80px) var(--pad-x) clamp(36px, 4vw, 64px);
  border-bottom: 1px solid var(--line);
}
.hero-grid {
  width: min(100%, var(--container));
  margin-inline: auto;
  display: grid;
  grid-template-columns: 1fr auto;
  gap: clamp(32px, 4vw, 80px);
  align-items: start;
  position: relative;
}

.hero-meta-top {
  grid-column: 1 / -1;
  display: flex; justify-content: space-between; gap: 24px; flex-wrap: wrap;
  margin-bottom: clamp(28px, 3vw, 48px);
  padding-bottom: 18px;
  border-bottom: 1px solid var(--line);
  font-family: var(--mono);
  font-size: var(--t-mono);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-mute);
}
.hero-meta-top .l, .hero-meta-top .r { display: flex; gap: 36px; }
.hero-meta-top strong { color: var(--ink); font-weight: 500; }

.hero-poster {
  font-family: var(--display);
  font-size: var(--t-poster);
  line-height: 0.92;
  letter-spacing: normal;
  color: var(--ink);
  margin: 0;
  font-weight: 700;
  position: relative;
}
.hero-poster .ink-thin { font-style: italic; font-weight: 300; color: var(--ink); }
.hero-poster .scramble-line { display: inline-block; }
.hero-poster .scramble-char { color: var(--ink-mute); font-weight: 400; }

.hero-snow {
  position: absolute;
  left: 0;
  width: 100%;
  pointer-events: none;
}

.hero-rail {
  position: relative;
  display: flex; flex-direction: column;
  gap: 18px;
  padding-left: 28px;
  border-left: 1px solid var(--ink);
  align-self: start;
  min-width: 280px;
  max-width: 320px;
  padding-block: 6px 16px;
}
.hero-rail .label { color: var(--ink); margin: 0; }
.hero-rail .label::before { background: var(--ink); }
.hero-rail h3 {
  font-family: var(--display);
  font-size: 1.7rem;
  letter-spacing: normal;
  line-height: 1.05;
  margin: 0;
}
.hero-rail h3 em { font-style: italic; color: var(--ink); }
.hero-rail p {
  font-size: 0.95rem;
  line-height: 1.55;
  color: var(--ink-soft);
  margin: 0;
}

.hero-foot {
  position: relative;
  grid-column: 1 / -1;
  margin-top: clamp(28px, 3vw, 48px);
  padding-top: 24px;
  border-top: 1px solid var(--line);
  display: grid;
  grid-template-columns: 1.4fr 0.8fr 0.8fr;
  gap: 32px;
  align-items: start;
}
.hero-foot .lede {
  font-size: 1.1rem;
  line-height: 1.65;
  color: var(--ink-soft);
  max-width: 50ch;
  margin: 0;
}
.hero-foot .field-block {
  font-family: var(--mono);
  font-size: var(--t-mono);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-mute);
}
.hero-foot .field-block strong { color: var(--ink); font-weight: 500; display: block; margin-bottom: 6px; }
.hero-foot .field-block .val {
  font-family: var(--display);
  font-size: 1.4rem;
  text-transform: none;
  letter-spacing: normal;
  color: var(--ink);
  line-height: 1.05;
  margin-top: 4px;
  display: block;
}

.hero-actions {
  grid-column: 1 / -1;
  margin-top: clamp(24px, 3vw, 40px);
  display: flex; gap: 36px; flex-wrap: wrap;
}

/* ───── statement ───── */
.statement {
  padding: var(--pad-section) var(--pad-x);
  border-bottom: 1px solid var(--line);
}
.statement .container-narrow {
  display: flex; flex-direction: column;
  gap: 28px;
}
.statement .label { margin-bottom: 8px; }
.statement-body {
  font-family: var(--display);
  font-size: clamp(1.6rem, 1rem + 1.6vw, 2.4rem);
  font-weight: 300;
  line-height: 1.32;
  color: var(--ink);
  letter-spacing: normal;
}
.statement-body em { font-style: italic; }
.statement-sign {
  font-family: var(--mono);
  font-size: var(--t-mono);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-mute);
  margin-top: 8px;
}
.statement-sign strong { color: var(--ink); font-weight: 500; }

/* ───── closing CTA ───── */
.cta {
  padding: var(--pad-section) var(--pad-x) 0;
}
.cta:has(+ .bottom-play) {
  border-bottom: 1px solid var(--line);
}
.cta-grid {
  width: min(100%, var(--container));
  margin: 0 auto;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(40px, 6vw, 96px);
  align-items: end;
  padding-bottom: 56px;
}
.cta-grid h2 {
  font-size: clamp(2rem, 1.2rem + 3vw, 4rem);
  font-weight: 400;
  letter-spacing: normal;
  line-height: 1;
  margin: 0;
}
.cta-grid h2 em { font-style: italic; font-weight: 300; }
.cta-meta {
  display: grid; gap: 16px;
}
.cta-meta .row {
  display: grid; grid-template-columns: 110px 1fr;
  gap: 18px;
  padding-bottom: 16px;
  border-bottom: 1px solid var(--line);
  font-family: var(--mono);
  font-size: var(--t-mono);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-mute);
}
.cta-meta .row strong { color: var(--ink); font-weight: 500; font-family: var(--display); font-size: 1.1rem; letter-spacing: normal; text-transform: none; line-height: 1.1; }
.cta-grid .btn-solid { justify-self: start; margin-top: 32px; }

/* ───── reveals ───── */
.reveal { opacity: 0; transform: translateY(14px); transition: opacity 0.9s var(--ease-out), transform 0.9s var(--ease-out); will-change: opacity, transform; }
.reveal.in { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) { .reveal { opacity: 1; transform: none; transition: none; } }

/* ───── inner page heads ───── */
.page-head {
  padding: clamp(56px, 7vw, 120px) var(--pad-x) clamp(40px, 5vw, 80px);
  border-bottom: 1px solid var(--line);
}
.page-head .container { display: flex; flex-direction: column; gap: 24px; }
.page-head h1 {
  font-size: clamp(3.5rem, 2rem + 6vw, 9rem);
  letter-spacing: normal;
  line-height: 0.92;
  font-weight: 400;
  font-style: italic;
}
.page-head .lede { font-size: 1.15rem; color: var(--ink-soft); max-width: 60ch; margin: 0; line-height: 1.55; }
.page-head .meta-row {
  margin-top: 18px;
  display: flex; gap: 36px; flex-wrap: wrap;
  font-family: var(--mono);
  font-size: var(--t-mono);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-mute);
  padding-top: 24px;
  border-top: 1px solid var(--line);
}
.page-head .meta-row strong { color: var(--ink); font-weight: 500; }

/* ───── status bar (live clock / route / connection) ───── */
/* ───── status bar (live clock / route / connection) ─────
   Matches the hero's meta-top treatment: real space below the sticky
   header, and a divider that's inset to the container width rather than
   running full-bleed edge to edge. */
.status-bar {
  padding: clamp(40px, 5vw, 80px) var(--pad-x) 0;
}
.status-bar .container, .notice-bar .container {
  display: flex; justify-content: space-between; gap: 24px; flex-wrap: wrap;
  padding-bottom: 18px;
  border-bottom: 1px solid var(--line);
  font-family: var(--mono);
  font-size: var(--t-mono);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-mute);
}
.status-bar .l, .status-bar .r, .notice-bar .l, .notice-bar .r { display: flex; gap: 36px; flex-wrap: wrap; }
.status-bar strong, .notice-bar strong { color: var(--ink); font-weight: 500; }
.notice-bar { padding: 18px var(--pad-x) 0; }

/* ───── contact/info blocks (about.html) + shared .form styles (login/register/forgot) ───── */
.contact {
  padding: var(--pad-section) var(--pad-x);
}
.contact-grid {
  width: min(100% - 0, var(--container));
  margin: 0 auto;
  display: grid;
  grid-template-columns: 1fr 1.2fr;
  gap: clamp(40px, 5vw, 96px);
  align-items: start;
}
.contact-info { display: flex; flex-direction: column; gap: 28px; }
.contact-info h2 {
  font-size: clamp(1.8rem, 1.2rem + 1.4vw, 2.6rem);
  font-style: italic;
  font-weight: 400;
  margin: 0;
}
.contact-info p { font-size: 1.04rem; line-height: 1.65; max-width: 50ch; margin: 0; }

.contact-blocks { display: grid; gap: 24px; margin-top: 16px; }
.contact-block {
  padding: 22px 0;
  border-top: 1px solid var(--line);
}
.contact-block:last-child { border-bottom: 1px solid var(--line); }
.contact-block .label { margin: 0 0 8px; }
.contact-block .val {
  font-family: var(--display);
  font-size: 1.4rem;
  font-style: italic;
  font-weight: 400;
  color: var(--ink);
  letter-spacing: normal;
  display: block;
}
.contact-block address { font-style: normal; line-height: 1.65; color: var(--ink-soft); margin-top: 6px; font-family: var(--sans); font-size: 0.95rem; }

.form { display: grid; gap: 20px; }
.form .label { margin: 0 0 12px; }
.form h2 {
  font-size: clamp(1.8rem, 1.2rem + 1.4vw, 2.6rem);
  font-style: italic;
  font-weight: 400;
  margin: 0 0 8px;
}
.field { display: grid; gap: 8px; }
.field label {
  font-family: var(--mono);
  font-size: 0.7rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-mute);
}
.field input,
.field select,
.field textarea {
  width: 100%;
  min-width: 0;
  box-sizing: border-box;
  font-family: var(--sans);
  font-size: 1rem;
  padding: 14px 0;
  border: 0;
  border-bottom: 1px solid var(--line);
  background: transparent;
  color: var(--ink);
  border-radius: 0;
  transition: border-color 0.25s var(--ease);
}
.field textarea { resize: none; min-height: 160px; padding-top: 12px; }
.field input:focus, .field select:focus, .field textarea:focus {
  outline: none;
  border-bottom-color: var(--ink);
}
.field input[type="file"] {
  padding: 10px 0;
  font-family: var(--mono);
  font-size: 0.82rem;
  color: var(--ink-mute);
}
.field input[type="file"]::file-selector-button {
  font-family: var(--mono);
  font-size: 0.7rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  padding: 10px 18px;
  margin-right: 16px;
  background: var(--ink);
  color: var(--paper);
  border: 0;
  cursor: pointer;
  transition: background 0.25s var(--ease), color 0.25s var(--ease);
}
.field input[type="file"]::file-selector-button:hover { background: transparent; color: var(--ink); outline: 1px solid var(--ink); }

.file-current {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 10px;
  font-family: var(--mono);
  font-size: 0.82rem;
}
.file-current a { color: var(--ink-soft); border-bottom: 1px solid var(--line); }
.file-current a:hover { color: var(--ink); }
.file-clear-x {
  position: relative;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 20px;
  color: var(--ink-mute);
  flex-shrink: 0;
}
.file-clear-x input { position: absolute; opacity: 0; width: 1px; height: 1px; }
.file-clear-x span { font-size: 1.1rem; line-height: 1; }
.file-clear-x:hover span { color: var(--ink); }
.file-current:has(.file-clear-x input:checked) a { text-decoration: line-through; opacity: 0.5; }
.file-current:has(.file-clear-x input:checked) .file-clear-x span { color: #ff6b6b; }
.form .btn-solid { justify-self: start; margin-top: 12px; }

/* ───── forum post detail ───── */
.post-body-block { margin: 40px 0 40px; }
.post-body-content {
  padding: 24px;
  border: 1px solid var(--line);
  white-space: pre-wrap;
  line-height: 1.7;
  color: var(--ink-soft);
  font-size: 0.98rem;
}
.post-reactions-block { margin: 0 0 8px; }
.entry-reactions { margin-left: auto; display: flex; gap: 20px; color: var(--ink-mute); flex-shrink: 0; }
.reaction-like, .reaction-dislike { white-space: nowrap; }

.post-comments-block { margin: 40px 0 0; }
.comment-item { padding: 20px 0; border-bottom: 1px solid var(--line-soft); }
.comment-meta { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; }
.comment-meta a { color: var(--ink); }
.comment-date { font-family: var(--mono); font-size: 0.72rem; color: var(--ink-mute); margin-left: auto; }
.comment-body { color: var(--ink-soft); line-height: 1.6; margin: 0 0 12px; white-space: pre-wrap; }
.comment-react-btn { font-size: 0.72rem; }
.comment-react-static { font-family: var(--mono); font-size: 0.72rem; color: var(--ink-mute); }

/* ───── profile page ───── */
.profile-banner {
  width: 100%;
  height: clamp(140px, 22vw, 240px);
  background: var(--paper-soft) center/cover no-repeat;
  border-bottom: 1px solid var(--line);
}
.profile-header {
  display: flex;
  align-items: flex-end;
  gap: 24px;
  flex-wrap: wrap;
  margin-top: -56px;
  padding-top: 24px;
}
.profile-avatar {
  width: 112px;
  height: 112px;
  border-radius: 50%;
  background: var(--paper-soft) center/cover no-repeat;
  border: 4px solid var(--paper);
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--mono);
  font-size: 2.4rem;
  color: var(--ink-mute);
  flex-shrink: 0;
}
.profile-identity { flex: 1; min-width: 200px; }
.profile-identity h1 {
  font-size: clamp(1.8rem, 1.3rem + 1.6vw, 2.6rem);
  font-style: italic;
  font-weight: 400;
  margin: 0;
}
.profile-username { font-family: var(--mono); color: var(--ink-mute); font-size: 0.85rem; margin: 4px 0 0; }
.profile-actions { padding-bottom: 8px; display: flex; gap: 16px; align-items: center; margin-left: auto; }
.profile-actions form { margin: 0; padding: 0; display: inline-flex; align-items: center; }
.profile-bio { margin: 20px 0 0; max-width: 60ch; }
.profile-stats {
  display: flex;
  gap: 28px;
  margin: 20px 0 32px;
  font-family: var(--mono);
  font-size: 0.8rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}
.profile-stats a { color: var(--ink-mute); border-bottom: 1px solid transparent; padding-bottom: 2px; }
.profile-stats a:hover { color: var(--ink); border-bottom-color: var(--ink-mute); }

/* ───── auth pages (login.html / register.html / forgot-password.html) ───── */
.auth {
  padding: clamp(48px, 6vw, 96px) var(--pad-x) var(--pad-section);
}
.auth-shell {
  width: min(100%, 400px);
  margin: 0 auto;
  padding: clamp(28px, 4vw, 36px) clamp(24px, 4vw, 34px);
  background: rgba(10, 10, 10, 0.35);
  backdrop-filter: blur(14px) brightness(1.4);
  -webkit-backdrop-filter: blur(14px) brightness(1.4);
  border: 1px solid var(--line);
  position: relative;
  z-index: 1;
}
.auth-shell .label { margin: 0 0 12px; }
.auth-shell h1 {
  font-size: clamp(1.8rem, 1.3rem + 1.6vw, 2.4rem);
  font-style: italic;
  font-weight: 400;
  margin: 0 0 12px;
}
.auth-shell .lede {
  font-size: 0.98rem;
  color: var(--ink-soft);
  margin: 0 0 32px;
  line-height: 1.55;
}
.auth-shell .form { gap: 20px; }
.auth-shell .field-note {
  margin-top: -8px;
  text-align: right;
}
.auth-shell .field-note a,
.auth-foot a {
  font-family: var(--mono);
  font-size: 0.72rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-mute);
  border-bottom: 1px solid var(--ink-mute);
  padding-bottom: 2px;
}
.auth-shell .field-note a:hover,
.auth-foot a:hover { color: var(--ink); border-bottom-color: var(--ink); }
.auth-shell .btn-solid { width: 100%; justify-content: center; margin-top: 8px; }
.auth-foot {
  margin-top: 28px;
  padding-top: 20px;
  border-top: 1px solid var(--line);
  text-align: center;
  font-family: var(--mono);
  font-size: 0.76rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-mute);
}
.page-snow {
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 0;
}

/* ───── focus visibility ───── */
:focus-visible { outline: 1px solid var(--ink); outline-offset: 4px; }

/* ───── responsive ───── */
@media (max-width: 1024px) {
  .hero-grid { grid-template-columns: 1fr; }
  .hero-rail { padding-left: 0; border-left: 0; padding-top: 28px; border-top: 1px solid var(--line); max-width: none; }
  .hero-foot { grid-template-columns: 1fr; }
  .cta-grid { grid-template-columns: 1fr; align-items: start; }
  .contact-grid { grid-template-columns: 1fr; }
}

@media (max-width: 768px) {
  .site-nav, .header-cta { display: none; }
  .menu-toggle { display: inline-flex; }
  .hero-meta-top { flex-direction: column; gap: 12px; }
  .hero-meta-top .l, .hero-meta-top .r { gap: 18px; flex-wrap: wrap; }
}

/* ───── bottom play (interactive cloth, replaces old footer slot).
   No border-top here — the .cta-grid directly above already ends in
   its own line, so this section just continues straight into the canvas. ───── */
.bottom-play {
  padding-bottom: clamp(32px, 4vw, 56px);
}
.cloth-wrap {
  position: relative;
  width: min(100% - var(--pad-x) * 2, var(--container));
  margin: 0 auto;
  height: clamp(180px, 22vw, 300px);
}
.cloth-canvas {
  display: block;
  width: 100%;
  height: 100%;
  cursor: crosshair;
  touch-action: none;
}
.cloth-caption {
  text-align: center;
  justify-content: center;
  width: 100%;
  margin: 20px 0 0;
  pointer-events: none;
  opacity: 0.7;
}

/* ───── full-height page (404): pins the footer to the bottom of the
   viewport on short pages instead of it trailing right after the content,
   without forcing a scrollbar. ───── */
.page-full-height {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}
.page-full-height main {
  flex: 1;
  display: flex;
  flex-direction: column;
}
.page-full-height main .auth {
  flex: 1;
  display: flex;
  align-items: center;
}

/* ───── site footer (copyright + build tags, terminal-styled) ───── */
.site-footer {
  padding: 22px var(--pad-x);
  border-top: 1px solid var(--line);
}
.footer-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 16px;
}
.footer-prompt { margin: 0; }
.footer-tags {
  display: flex;
  align-items: center;
  gap: 16px;
  flex-wrap: wrap;
  font-family: var(--mono);
  font-size: 0.7rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-mute);
}
.footer-tags .footer-link {
  color: var(--ink-soft);
  text-decoration: none;
  border-bottom: 1px solid var(--ink-mute);
  padding-bottom: 1px;
  transition: color 0.2s var(--ease), border-color 0.2s var(--ease);
}
.footer-tags .footer-link:hover { color: var(--ink); border-color: var(--ink); }
@media (max-width: 560px) { .footer-inner { flex-direction: column; align-items: flex-start; } }

@media (max-width: 768px) {
  .bottom-play { display: none; }
}

/* ───── site-wide cursor ───── */
*, *::before, *::after {
  cursor: crosshair !important;
}

/* =========================================================
   Project hub extensions — directory listing + project detail
   Additive only. Reuses tokens/vars from the base theme above.
   ========================================================= */

/* ───── terminal prompt strip (top of projects.html / project.html) ───── */
.term-prompt {
  padding: 14px var(--pad-x);
  border-bottom: 1px solid var(--line);
  background: var(--paper-soft);
}
.term-prompt .container { display: flex; align-items: center; }
.prompt-line {
  margin: 0;
  font-family: var(--mono);
  font-size: var(--t-mono);
  letter-spacing: 0.05em;
  color: var(--ink-soft);
  white-space: pre-wrap;
  word-break: break-word;
}
.prompt-user { color: #7ee787; }
.prompt-colon { color: var(--ink-mute); margin: 0 2px; }
.prompt-path { color: #79c0ff; }
.prompt-dollar { color: var(--ink-mute); margin-left: 8px; margin-right: 8px; }
.prompt-cmd { color: var(--ink); }
.prompt-cursor {
  display: inline-block;
  width: 8px; height: 1em;
  background: var(--ink);
  margin-left: 2px;
  vertical-align: text-bottom;
  animation: term-blink 1.1s steps(1) infinite;
}
@keyframes term-blink { 0%, 49% { opacity: 1; } 50%, 100% { opacity: 0; } }

/* ───── gallery: hero + thumbnail strip + lightbox ───── */
.gallery {
  width: min(100% - var(--pad-x) * 2, var(--container));
  margin: 0 auto clamp(48px, 6vw, 80px);
}
.gallery-hero {
  aspect-ratio: 16 / 9;
  background: var(--paper-soft);
  overflow: hidden;
  margin-bottom: 12px;
  border: 1px solid var(--line);
}
.gallery-hero img { width: 100%; height: 100%; object-fit: cover; cursor: zoom-in; }
.gallery-strip {
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  gap: 10px;
}
.gallery-thumb {
  aspect-ratio: 4 / 3;
  overflow: hidden;
  border: 1px solid var(--line);
  cursor: pointer;
  opacity: 0.55;
  transition: opacity 0.2s var(--ease), border-color 0.2s var(--ease);
}
.gallery-thumb img { width: 100%; height: 100%; object-fit: cover; }
.gallery-thumb:hover { opacity: 0.9; }
.gallery-thumb.is-active { opacity: 1; border-color: var(--ink); }
@media (max-width: 860px) { .gallery-strip { grid-template-columns: repeat(3, 1fr); } }

.lightbox {
  position: fixed; inset: 0; z-index: 200;
  background: rgba(6,6,6,0.92);
  display: none;
  align-items: center; justify-content: center;
  padding: 40px;
}
.lightbox.is-open { display: flex; }
.lightbox img { max-width: 100%; max-height: 100%; object-fit: contain; }
.lightbox-close {
  position: absolute; top: 24px; right: 32px;
  font-family: var(--mono);
  font-size: 0.8rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-soft);
  background: none; border: 1px solid var(--line-strong);
  padding: 8px 14px; cursor: pointer;
}
.lightbox-close:hover { color: var(--ink); }

/* ───── live demo embed ───── */
.demo-embed {
  width: min(100% - var(--pad-x) * 2, var(--container));
  margin: 18vh auto;
  /* Generous top/bottom room (not just a bottom margin) is what makes
     it possible to scroll to a point where the game is the only thing
     between the header and footer, instead of it just trailing right
     under the details block. */
}
/* .is-inline-embed: a direct template include (e.g. the vault) rather
   than an iframe/game embed. The included partial brings its own
   sensible spacing (see .vault-app) — the 18vh above is specifically
   tuned to make a game feel like the sole focus of the page, and would
   just be excessive empty space around ordinary in-page content. */
.demo-embed.is-inline-embed { margin: 0 auto; }
.demo-embed .term-window iframe {
  display: block;
  width: 100%;
  border: 0;
  background: var(--paper);
  /* Matches the game's native 1100x600 viewport so Godot's canvas fills
     the frame edge-to-edge with no letterboxing at any width. */
  aspect-ratio: 1100 / 600;
  /* Scales up to fill most of the screen on load, capped so it never
     forces scrolling on a normal-height display. */
  max-height: 82vh;
}
/* .is-app-embed: a live Django page (e.g. the vault) instead of a fixed-
   resolution game canvas. Its content height varies with what's typed
   into it, so a locked aspect-ratio would either crop it or leave dead
   space — a generous fixed height with the iframe's own internal scroll
   works better here than trying to match an aspect ratio that has no
   natural value for this kind of content. */
.demo-embed .term-window.is-app-embed iframe {
  aspect-ratio: auto;
  height: 760px;
  max-height: 82vh;
}
.demo-embed .fallback {
  padding: 14px 16px;
  font-family: var(--mono);
  font-size: 0.76rem;
  color: var(--ink-mute);
  border-top: 1px solid var(--line);
}
.demo-embed .fallback a { color: var(--ink); border-bottom: 1px solid var(--ink-mute); }
/* The login-prompt link reuses .btn-solid (light pill, dark text) inside
   .fallback — the plain-text-link rule above was winning on specificity
   and forcing it back to light-on-light. This wins back for that case
   specifically without touching the plain "check back soon" style link. */
.demo-embed .fallback a.btn-solid { color: var(--paper); border-bottom: none; }

/* ───── devlog (collapsible changelog) ───── */
.devlog {
  width: min(100% - var(--pad-x) * 2, var(--container-narrow));
  margin: 0 auto clamp(48px, 6vw, 80px);
}
.devlog summary {
  cursor: pointer;
  list-style: none;
  display: flex; align-items: center; gap: 12px;
  padding-bottom: 18px;
  border-bottom: 1px solid var(--line);
  font-family: var(--mono);
  font-size: 0.8rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-soft);
}
.devlog summary::-webkit-details-marker { display: none; }
.devlog summary::before { content: '▸'; color: var(--ink-mute); transition: transform 0.2s var(--ease); }
.devlog[open] summary::before { transform: rotate(90deg); }
.devlog-body { padding-top: 24px; }
.devlog-entry { display: grid; grid-template-columns: 130px 1fr; gap: 20px; padding: 22px 0; border-bottom: 1px solid var(--line-soft); }
.devlog-entry .date { font-family: var(--mono); font-size: 0.72rem; color: var(--ink-mute); letter-spacing: 0.08em; padding-top: 2px; }
.devlog-entry .entry { font-size: 0.94rem; color: var(--ink-soft); line-height: 1.6; display: flex; align-items: center; flex-wrap: wrap; gap: 12px; }
.devlog-entry .entry strong { color: var(--ink); font-weight: 500; }
.entry-main { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.entry-avatar {
  width: 30px; height: 30px; border-radius: 50%;
  background: var(--paper-soft) center/cover no-repeat;
  display: inline-flex; align-items: center; justify-content: center;
  font-family: var(--mono); font-size: 0.75rem; color: var(--ink-mute);
  flex-shrink: 0;
}
@media (max-width: 640px) { .devlog-entry { grid-template-columns: 1fr; gap: 4px; } }

/* ───── image crop modal ───── */
.crop-modal {
  position: fixed;
  inset: 0;
  z-index: 200;
  background: rgba(0, 0, 0, 0.82);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
}
.crop-modal[hidden] { display: none; }
.crop-modal-box {
  background: var(--paper);
  border: 1px solid var(--line);
  padding: 32px;
  width: min(100%, 480px);
}
.crop-modal-stage { max-height: 55vh; overflow: hidden; background: #000; }
.crop-modal-stage img { display: block; max-width: 100%; }
.crop-modal-actions { display: flex; justify-content: flex-end; gap: 16px; margin-top: 24px; }
.crop-modal.is-circle .cropper-view-box,
.crop-modal.is-circle .cropper-face { border-radius: 50%; }

/* =========================================================
   Radial hex menu + glossary (projects.html)
   ========================================================= */

/* ───── merged hero: status bar + title + hex menu share one wrapper,
   mirroring .hero-grid on index.html, so the snow canvas can start right
   below the status bar and flow down through everything below it. ───── */
.projects-hero {
  position: relative;
  overflow: hidden;
  border-bottom: 1px solid var(--line);
}
.projects-hero .page-head.no-border {
  border-bottom: 0;
  position: relative;
  padding-top: clamp(24px, 3vw, 44px);
  padding-bottom: clamp(20px, 3vw, 40px);
}
.projects-hero .hex-menu { position: relative; }

.glossary-section {
  padding: clamp(20px, 3vw, 40px) var(--pad-x) clamp(60px, 7vw, 100px);
  border-bottom: 1px solid var(--line);
}

/* ───── snow layer (canvas, driven by effects.js — same falling '*'
   system, and the same top/height-via-JS approach, as the hero snow) ─────
   Width must be set explicitly: a canvas is a replaced element, and
   `left:0; right:0` alone (no `width`) doesn't reliably stretch a replaced
   element to fill its container in every browser — it was quietly staying
   at the canvas's intrinsic size, which is why the snow only ever
   appeared in a strip on the left before. */
.hex-snow {
  position: absolute;
  left: 0;
  width: 100%;
  pointer-events: none;
  z-index: 0;
}

/* ───── hub + ring wrapper ─────
   Hexagons here are drawn "flat-top" (flat horizontal edges top/bottom,
   pointy vertices left/right). Placed at 60°-step angles starting at -90°,
   each hex's flat edge faces the hub directly — that's what makes them
   read as parallel neighbors rather than corner-first. This only works
   if the box itself has true hexagon proportions (width : height =
   2 : √3 ≈ 1.15 : 1) rather than a square — a square box forces either
   a squished/tall look or a corner pointing at the hub. --tx/--ty below
   are precomputed for radius R = 195, just beyond the "touching"
   distance (which equals hex height, 165px) for a tight-but-clear gap.
*/
.hex-menu {
  position: relative;
  z-index: 1;
  width: min(100%, 580px);
  height: clamp(430px, 50vw, 560px);
  margin: 0 auto clamp(24px, 3vw, 48px);
  display: flex;
  align-items: center;
  justify-content: center;
}

.hex-hub {
  position: relative;
  z-index: 5;
  width: 225px; height: 195px;
  border: 0;
  cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  flex-direction: column;
  gap: 2px;
  font-family: var(--mono);
  font-size: 0.62rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink);
  background: transparent;
  transition: width 0.35s var(--ease-out), height 0.35s var(--ease-out), transform 0.3s var(--ease-out);
}
.hex-menu.is-open .hex-hub { width: 190px; height: 165px; }
.hex-hub:hover { transform: scale(1.05); }
.hub-glass {
  position: absolute;
  inset: 0;
  clip-path: polygon(25% 1.5%, 75% 1.5%, 99% 50%, 75% 98.5%, 25% 98.5%, 1% 50%);
  background: rgba(10, 10, 10, 0.28);
  backdrop-filter: blur(14px) brightness(1.4);
  -webkit-backdrop-filter: blur(14px) brightness(1.4);
  transition: background 0.2s var(--ease);
}
.hub-svg {
  position: absolute;
  inset: 0;
  width: 100%; height: 100%;
  overflow: visible;
  pointer-events: none;
}
.hub-outline {
  fill: none;
  stroke: var(--ink);
  stroke-width: 2;
  vector-effect: non-scaling-stroke;
}
.hex-hub .hub-icon, .hex-hub .hub-label { position: relative; z-index: 2; }
.hex-hub .hub-icon { font-size: 1.3rem; line-height: 1; margin-bottom: 2px; }
.hex-menu.is-open .hex-hub .hub-label { display: none; }
.hex-menu.is-open .hex-hub .hub-icon::after { content: '✕'; }
.hex-menu:not(.is-open) .hex-hub .hub-icon::after { content: '▸'; }
.hex-hub .hub-icon::before { content: ''; }

/* ───── "click to explore" hint, fades out once the ring is open ───── */
.hex-hint {
  position: absolute;
  left: 50%;
  top: calc(50% + 113px);
  transform: translateX(-50%);
  margin: 0;
  font-family: var(--mono);
  font-size: 0.68rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-mute);
  white-space: nowrap;
  opacity: 0.6;
  transition: opacity 0.25s var(--ease);
  pointer-events: none;
  z-index: 3;
  animation: hex-hint-pulse 2.6s ease-in-out infinite;
}
.hex-menu.is-open .hex-hint { opacity: 0; }
@keyframes hex-hint-pulse {
  0%, 100% { opacity: 0.4; }
  50% { opacity: 0.85; }
}
@media (prefers-reduced-motion: reduce) {
  .hex-hint { animation: none; opacity: 0.65; }
}

/* ───── individual hexagons (ring items) ─────
   Two layers: a clip-path'd glass panel (fill + blur, no border — borders
   on clip-path elements cause seam artifacts) and an SVG overlay that draws
   just the outline stroke + icon (crisp at any size, no artifacts).
*/
.hex {
  position: absolute;
  top: 50%; left: 50%;
  width: 190px; height: 165px;
  margin: -82px 0 0 -95px;
  display: block;
  text-decoration: none;
  cursor: pointer;
  opacity: 0;
  transform: translate(0, 0);
  transition: transform 0.5s var(--ease-out), opacity 0.4s var(--ease-out);
  transition-delay: 0s;
  z-index: 4;
}
.hex-glass {
  position: absolute;
  inset: 0;
  clip-path: polygon(25% 1.5%, 75% 1.5%, 99% 50%, 75% 98.5%, 25% 98.5%, 1% 50%);
  background: rgba(10, 10, 10, 0.28);
  backdrop-filter: blur(14px) brightness(1.4);
  -webkit-backdrop-filter: blur(14px) brightness(1.4);
  transition: background 0.2s var(--ease);
}
.hex-svg {
  position: absolute;
  inset: 0;
  width: 100%; height: 100%;
  overflow: visible;
  pointer-events: none;
}
.hex-outline {
  fill: none;
  stroke: var(--line-strong);
  stroke-width: 1.5;
  vector-effect: non-scaling-stroke;
  transition: stroke 0.2s var(--ease);
}
.hex-icon {
  stroke: var(--ink-soft);
  fill: none;
  stroke-width: 1.4;
  transition: stroke 0.2s var(--ease);
}
.hex-menu.is-open .hex {
  opacity: 1;
  transform: translate(var(--tx), var(--ty));
}
.hex:hover .hex-glass, .hex.is-active .hex-glass { background: rgba(10, 10, 10, 0.42); }
.hex:hover .hex-outline, .hex.is-active .hex-outline { stroke: var(--ink); }
.hex:hover .hex-icon, .hex.is-active .hex-icon { stroke: var(--ink); }
.hex-menu.is-open .hex:nth-of-type(1) { transition-delay: 0.03s; }
.hex-menu.is-open .hex:nth-of-type(2) { transition-delay: 0.07s; }
.hex-menu.is-open .hex:nth-of-type(3) { transition-delay: 0.11s; }
.hex-menu.is-open .hex:nth-of-type(4) { transition-delay: 0.15s; }
.hex-menu.is-open .hex:nth-of-type(5) { transition-delay: 0.19s; }
.hex-menu.is-open .hex:nth-of-type(6) { transition-delay: 0.23s; }

@media (max-width: 720px) {
  /* radial math gets cramped on narrow screens — settle into a static grid */
  .hex-menu { height: auto; }
  .hex-hub { display: none; }
  .hex-menu, .hex-menu.is-open { display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px; width: min(100%, 380px); justify-items: center; }
  .hex, .hex-menu.is-open .hex {
    position: static; margin: 0; opacity: 1; transform: none; transition: none;
    width: 104px; height: 90px;
  }
}

/* ───── glossary (image + short description, replaces the old catalog) ───── */
.glossary {
  width: min(100% - var(--pad-x) * 2, var(--container-narrow));
  margin: 0 auto;
}
.glossary-entry {
  display: grid;
  grid-template-columns: 180px 1fr;
  gap: 22px;
  align-items: center;
  padding: 22px 14px;
  border-top: 1px solid var(--line);
  text-decoration: none;
  scroll-margin-top: 120px;
  transition: background 0.3s var(--ease), padding 0.3s var(--ease);
}
.glossary-entry:first-child { border-top: 0; }
.glossary-entry .thumb {
  width: 180px; height: 135px;
  overflow: hidden;
  background: var(--paper-soft);
  border: 1px solid var(--line);
  flex: none;
}
.glossary-entry .thumb img { width: 100%; height: 100%; object-fit: cover; }
.glossary-entry .title {
  display: block;
  font-family: var(--display);
  font-style: italic;
  font-size: 1.15rem;
  color: var(--ink);
  margin-bottom: 4px;
}
.glossary-entry .desc { font-size: 0.92rem; color: var(--ink-soft); max-width: 52ch; }
.glossary-entry.is-active {
  background: var(--paper-soft);
  padding-left: 22px; padding-right: 22px;
}
.glossary-entry.is-active .thumb { border-color: var(--ink); }
@media (max-width: 560px) {
  .glossary-entry { grid-template-columns: 120px 1fr; gap: 14px; }
  .glossary-entry .thumb { width: 120px; height: 90px; }
}

/* ───── Django auth additions: logout form needs to behave like the .btn-solid link it replaces ───── */
.header-cta-form { margin: 0; display: contents; }
.field-optional { opacity: 0.5; font-weight: 400; text-transform: none; letter-spacing: 0; }

/* ───── Django auth additions: small "?" info tooltip (e.g. optional-email note) ───── */
.info-tip {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 15px;
  height: 15px;
  margin-left: 6px;
  border: 1px solid var(--line-strong);
  border-radius: 50%;
  font-family: var(--mono);
  font-size: 0.62rem;
  line-height: 1;
  color: var(--ink-soft);
  cursor: help;
  vertical-align: middle;
}
.info-tip:hover, .info-tip:focus-visible {
  color: var(--ink);
  border-color: var(--ink-soft);
  outline: none;
}
.info-tip-bubble {
  position: absolute;
  bottom: calc(100% + 8px);
  left: 50%;
  transform: translateX(-50%);
  width: max-content;
  max-width: 240px;
  padding: 8px 10px;
  background: var(--paper-soft);
  border: 1px solid var(--line-strong);
  color: var(--ink-soft);
  font-family: var(--sans);
  font-size: 0.76rem;
  line-height: 1.4;
  text-transform: none;
  letter-spacing: 0;
  font-weight: 400;
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.15s var(--ease), visibility 0.15s var(--ease);
  z-index: 5;
  pointer-events: none;
}
.info-tip:hover .info-tip-bubble,
.info-tip:focus-visible .info-tip-bubble {
  opacity: 1;
  visibility: visible;
}

/* ───── Django additions: glossary now shows the same hex-menu icon glyph instead of a photo thumbnail, so it's obvious which glossary row matches which hex ───── */
.glossary-entry .thumb.thumb-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  background: none;
  border: none;
}
.thumb-icon-svg {
  width: 96%;
  height: 96%;
  overflow: visible;
}
.thumb-icon-svg .hex-icon { stroke: var(--ink-soft); }
.glossary-entry:hover .thumb-icon-svg .hex-icon,
.glossary-entry.is-active .thumb-icon-svg .hex-icon { stroke: var(--ink); }

/* =========================================================
   Vault page — offline password manager
   ========================================================= */
.vault-app {
  width: min(100% - var(--pad-x) * 2, var(--container-narrow));
  margin: clamp(40px, 5vw, 72px) auto clamp(80px, 8vw, 140px);
}

/* ── shared field styling ── */
.vault-field { display: flex; flex-direction: column; gap: 8px; }
.vault-field-label {
  font-family: var(--mono);
  font-size: 0.68rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-mute);
}
.vault-field input[type="text"],
.vault-field input[type="password"],
.vault-field textarea {
  font-family: var(--sans);
  font-size: 0.95rem;
  color: var(--ink);
  background: var(--paper-soft);
  border: 1px solid var(--line);
  padding: 12px 14px;
  width: 100%;
}
.vault-field input[type="file"] {
  font-family: var(--sans);
  font-size: 0.88rem;
  color: var(--ink-soft);
}
/* The native file-picker button (labelled "Browse", "Choose File", etc.
   depending on the browser) is a real <button> living inside the input,
   exposed via this pseudo-element — restyle it to match .btn-ghost
   instead of leaving it as the unstyled OS-default button. Needs both
   the standard property and the older WebKit-prefixed one; Firefox and
   Chromium-based browsers both support the unprefixed version today,
   but Safari has historically needed the prefix. */
.vault-field input[type="file"]::file-selector-button,
.vault-field input[type="file"]::-webkit-file-upload-button {
  margin-right: 14px;
  padding: 10px 18px;
  font-family: var(--mono);
  font-size: 0.72rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  background: transparent;
  color: var(--ink-soft);
  border: 1px solid var(--line-strong);
  cursor: pointer;
}
.vault-field input[type="file"]::file-selector-button:hover,
.vault-field input[type="file"]::-webkit-file-upload-button:hover {
  color: var(--ink);
  border-color: var(--ink);
}
.vault-field input:focus, .vault-field textarea:focus {
  outline: none;
  border-color: var(--ink-soft);
}
.vault-field-row { display: flex; gap: 20px; margin-bottom: 18px; }
.vault-field-row .vault-field { flex: 1; }
.vault-hint { font-size: 0.86rem; color: var(--ink-mute); line-height: 1.5; max-width: 52ch; }

/* ── ghost/secondary button (outline, no fill) ── */
.btn-ghost {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 14px 24px;
  font-family: var(--mono);
  font-size: var(--t-small);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  background: transparent;
  color: var(--ink-soft);
  border: 1px solid var(--line-strong);
  cursor: pointer;
}
.btn-ghost:hover { color: var(--ink); border-color: var(--ink); }
.btn-small { padding: 8px 16px; font-size: 0.7rem; }

/* ── locked panel: tabs + create/unlock forms ── */
.vault-panel { padding-top: clamp(24px, 3vw, 40px); }
.vault-tabs {
  display: flex;
  gap: 8px;
  border-bottom: 1px solid var(--line);
  margin-bottom: 32px;
}
.vault-tab {
  padding: 12px 4px;
  margin-right: 28px;
  font-family: var(--mono);
  font-size: 0.78rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  background: none;
  border: 0;
  border-bottom: 2px solid transparent;
  color: var(--ink-mute);
  cursor: pointer;
  transform: translateY(1px);
}
.vault-tab:hover { color: var(--ink-soft); }
.vault-tab.is-active { color: var(--ink); border-bottom-color: var(--ink); }
.vault-tab-panel { display: flex; flex-direction: column; gap: 20px; max-width: 440px; }
.vault-tab-panel[hidden] { display: none; }
.vault-tab-panel .btn-solid { align-self: flex-start; }

.vault-msg { font-size: 0.88rem; color: var(--ink-soft); min-height: 1.4em; }
.vault-msg.is-error { color: #d98077; }

/* ── unlocked panel: toolbar + entry list ── */
.vault-toolbar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
  gap: 16px;
  padding-bottom: 24px;
  border-bottom: 1px solid var(--line);
  margin-bottom: 24px;
}
.vault-status {
  font-family: var(--mono);
  font-size: 0.78rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-mute);
  display: inline-flex;
  align-items: center;
  gap: 8px;
}
.vault-status .term-dot {
  width: 7px; height: 7px; border-radius: 50%;
  background: #7fbf8f;
  display: inline-block;
}
.vault-toolbar-actions { display: flex; gap: 12px; flex-wrap: wrap; }

.vault-textarea {
  width: 100%;
  min-height: 480px;
  resize: vertical;
  font-family: var(--mono);
  font-size: 0.92rem;
  line-height: 1.6;
  color: var(--ink);
  background: var(--paper-soft);
  border: 1px solid var(--line);
  padding: 20px;
  overflow-y: auto;
}
.vault-textarea:focus { outline: none; border-color: var(--ink-soft); }
.vault-textarea::placeholder { color: var(--ink-mute); }

@media (max-width: 640px) {
  .vault-field-row { flex-direction: column; gap: 18px; }
  .vault-textarea { min-height: 340px; }
}

/* =========================================================
   Mobile block — site isn't ready for small screens yet.
   Pure CSS, no JS: included in every page (base.html + the
   standalone vault.html, which doesn't extend base.html), hidden by
   default, only shown below the same breakpoint the site already uses
   to switch to the mobile nav. Covers the whole viewport so nothing
   underneath is reachable or scrollable.
   ========================================================= */
.mobile-block { display: none; }

@media (max-width: 768px) {
  body { overflow: hidden; }
  .mobile-block {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 18px;
    position: fixed;
    inset: 0;
    z-index: 9999;
    padding: 40px;
    text-align: center;
    background: var(--paper);
    color: var(--ink);
  }
  .mobile-block .label { justify-content: center; }
  .mobile-block h2 {
    font-family: var(--display);
    font-style: italic;
    font-weight: 400;
    font-size: 2.2rem;
    margin: 0;
  }
  .mobile-block p:not(.label) {
    max-width: 38ch;
    color: var(--ink-soft);
    font-size: 0.95rem;
    line-height: 1.55;
    margin: 0;
  }
}

/* ───── deals: plain list (deliberately not the devlog/cat-log treatment —
   a straight scannable list reads better for a "browse the deals" page
   than the terminal-log framing used elsewhere) ───── */
.deal-list-section { padding: 8px 0 var(--pad-section); }
.deal-list-section .label { margin-bottom: 18px; }
.deal-list { list-style: none; margin: 0; padding: 0; }
.deal-row {
  display: grid;
  grid-template-columns: 56px 1fr auto;
  align-items: baseline;
  gap: 16px;
  padding: 16px 0;
  border-bottom: 1px solid var(--line-soft);
}
.deal-cut { font-family: var(--mono); font-size: 0.8rem; color: var(--ink-soft); }
.deal-title {
  font-family: var(--display);
  font-size: 1rem;
  color: var(--ink);
  text-decoration: none;
}
.deal-title:hover { text-decoration: underline; }
.deal-store {
  font-family: var(--mono);
  font-size: 0.66rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-mute);
  margin-left: 6px;
}
.deal-reviews {
  font-family: var(--mono);
  font-size: 0.78rem;
  color: var(--ink-soft);
  margin-left: 12px;
}
.deal-reviews-meta { color: var(--ink-mute); font-size: 0.7rem; }
.deal-price { font-family: var(--mono); font-size: 0.85rem; color: var(--ink-soft); text-align: right; white-space: nowrap; }
.deal-price s { opacity: 0.5; margin-left: 6px; text-decoration-color: var(--ink-mute); }
.deal-low {
  display: inline-block;
  font-family: var(--mono);
  font-size: 0.62rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink);
  border: 1px solid var(--line-strong);
  padding: 2px 6px;
  margin-left: 8px;
}
.deal-row-empty { padding: 16px 0; color: var(--ink-mute); font-size: 0.9rem; }
@media (max-width: 640px) {
  .deal-row { grid-template-columns: 40px 1fr; }
  .deal-price { grid-column: 1 / -1; text-align: left; padding-left: 56px; }
  .deal-store { display: block; margin-left: 0; margin-top: 2px; }
}

/* ───── deals: filter/sort controls + pager ───── */
.deal-controls {
  display: flex;
  gap: 28px;
  align-items: flex-end;
  margin-bottom: 24px;
  padding-bottom: 20px;
  border-bottom: 1px solid var(--line);
}
.deal-controls label { display: flex; flex-direction: column; gap: 6px; }
.deal-controls-label {
  font-family: var(--mono);
  font-size: 0.66rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-mute);
}
.deal-controls select {
  font-family: var(--sans);
  font-size: 0.9rem;
  color: var(--ink);
  background: var(--paper-soft);
  border: 1px solid var(--line);
  padding: 9px 12px;
  min-width: 140px;
}
.deal-pager {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  align-items: center;
  padding-top: 8px;
  margin-top: 24px;
  font-family: var(--mono);
  font-size: 0.82rem;
}
.deal-pager a, .deal-pager-current {
  padding: 6px 11px;
  color: var(--ink-soft);
  text-decoration: none;
  border: 1px solid transparent;
}
.deal-pager a:hover { color: var(--ink); border-color: var(--line); }
.deal-pager-current { color: var(--ink); border-color: var(--line-strong); }

/* ───── shared glass modal (rules popups, and anything similar) ─────
   Generic on purpose — any page can use this by adding the markup below
   plus data-modal-open/data-modal-close attributes (wired up in
   main.js), no per-page CSS or JS needed. The board games' own win/
   aborted popups predate this and keep their own per-game-prefixed
   styles rather than being migrated onto it. */
.glass-modal-backdrop {
  display: none; position: fixed; inset: 0;
  background: rgba(5, 6, 9, 0.55);
  backdrop-filter: blur(3px); -webkit-backdrop-filter: blur(3px);
  z-index: 70; align-items: center; justify-content: center; padding: 24px;
}
.glass-modal-backdrop.is-visible { display: flex; }
.glass-modal {
  position: relative; width: 100%; max-width: 480px; max-height: 80vh;
  padding: 40px 32px 32px; overflow-y: auto;
  background: rgba(255, 255, 255, 0.06); border: 1px solid rgba(255, 255, 255, 0.18);
  backdrop-filter: blur(18px) saturate(140%); -webkit-backdrop-filter: blur(18px) saturate(140%);
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.45), inset 0 1px 0 rgba(255, 255, 255, 0.08);
  animation: glass-modal-in 0.2s ease both;
}
@keyframes glass-modal-in { from { opacity: 0; transform: translateY(8px) scale(0.98); } to { opacity: 1; transform: translateY(0) scale(1); } }
.glass-modal-title { font-family: var(--mono); font-size: 1.3rem; margin: 0 0 16px; }
.glass-modal-body { font-family: var(--mono); font-size: var(--t-small, 0.9rem); color: var(--ink-soft); line-height: 1.6; }
.glass-modal-body p { margin: 0 0 12px; }
.glass-modal-body p:last-child { margin-bottom: 0; }
.glass-modal-body ul { margin: 0 0 12px; padding-left: 20px; }
.glass-modal-body li { margin-bottom: 4px; }
.glass-modal-body strong { color: var(--ink); }
.glass-modal-close { position: absolute; top: 8px; right: 12px; background: none; border: 0; color: var(--ink-mute); font-size: 1.5rem; line-height: 1; cursor: pointer; padding: 8px; }
.glass-modal-close:hover { color: var(--ink); }

.rules-btn {
  font-family: var(--mono); font-size: var(--t-mono, 0.75rem); text-transform: uppercase; letter-spacing: 0.04em;
  color: var(--ink-soft); background: none; border: 1px solid var(--line); padding: 8px 14px; cursor: pointer;
}
.rules-btn:hover { color: var(--ink); border-color: var(--line-strong); }

.turn-timer {
  font-family: var(--mono);
  font-size: var(--t-mono, 0.75rem);
  color: var(--ink-mute);
  text-align: center;
}
.turn-timer.is-urgent { color: #d9534f; }
