/* =========================================================================
   Hard Times — shared stylesheet.
   Loaded by index.html AND by every Worker-rendered wiki page (see
   src/render.js), so the dashboard and the wiki stay one design system.
   ========================================================================= */

:root{
  --void:#05060a; --void-2:#0b0d14; --void-blue:#060815; --panel:#12151f;
  --steel:#232733; --steel-lt:#4a5568;
  --amber:#ffb020; --amber-dim:#b9791a; --rust:#8a4a2a;
  --text:#d8dbe2; --text-dim:#8890a0;
}
*{ box-sizing:border-box; }
html{ scroll-behavior:smooth; }
html,body{ margin:0; padding:0; }
body{
  background:var(--void); color:var(--text);
  font-family:'Barlow',sans-serif; line-height:1.65;
  overflow-x:hidden;
}
a{ color:var(--amber); }
::selection{ background:var(--amber); color:#1a1305; }

/* ---- ambient: HUD/tablet background (matches the Hard Times tome's 'digital'
   page treatment on 919gaming's bookshelf) + scanline/static overlay ---- */
.hud-bg{ position:fixed; inset:0; z-index:0; pointer-events:none;
  background:
    repeating-linear-gradient(180deg, rgba(255,255,255,0.035) 0 1px, transparent 1px 3px),
    repeating-linear-gradient(90deg, rgba(255,176,32,0.05) 0 1px, transparent 1px 46px),
    repeating-linear-gradient(0deg, rgba(255,176,32,0.05) 0 1px, transparent 1px 46px),
    radial-gradient(ellipse at 50% 0%, rgba(255,176,32,0.08), transparent 55%),
    linear-gradient(165deg,#1c2026 0%,#111418 55%,#05070a 100%); }
.static{ position:fixed; inset:0; z-index:0; pointer-events:none; opacity:0.05; mix-blend-mode:overlay;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E"); }
.vignette{ position:fixed; inset:0; z-index:0; pointer-events:none;
  background:radial-gradient(ellipse at 50% 40%, transparent 45%, rgba(0,0,0,0.55) 100%); }

section{ position:relative; z-index:1; max-width:960px; margin:0 auto; padding:90px 28px; }

/* ---- hero ---- */
.hero{ min-height:auto; display:flex; flex-direction:column; align-items:center; justify-content:center;
  text-align:center; padding:64px 28px 48px; }
.hero .badge{ width:132px; height:auto; margin:0 0 22px;
  filter:drop-shadow(0 0 26px rgba(255,176,32,0.35)) drop-shadow(0 8px 18px rgba(0,0,0,0.6)); }
.hero .kicker{ font-family:'Share Tech Mono',monospace; font-size:14.5px; letter-spacing:0.32em;
  text-transform:uppercase; color:var(--amber); opacity:0.85; margin:0 0 14px; }
.hero h1{ font-family:'Big Shoulders Stencil',sans-serif; font-weight:800; font-size:clamp(56px,13vw,132px);
  letter-spacing:0.02em; line-height:0.9; margin:0; color:var(--text);
  text-shadow:0 0 40px rgba(255,176,32,0.25), 0 6px 0 rgba(0,0,0,0.5); }
.hero .tagline{ font-family:'Oswald',sans-serif; font-weight:400; font-size:clamp(16.5px,2.1vw,20px);
  letter-spacing:0.06em; color:var(--text-dim); margin:16px 0 0; max-width:38ch; }
.hero .scroll-cue{ margin-top:32px; font-family:'Share Tech Mono',monospace; font-size:12.5px;
  letter-spacing:0.2em; text-transform:uppercase; color:var(--steel-lt); animation:pulse 2.4s ease infinite; }
.hero-nav{ display:flex; flex-wrap:wrap; justify-content:center; gap:26px; margin-top:26px; }
.hero-nav a{ font-family:'Share Tech Mono',monospace; font-size:13px; letter-spacing:0.16em;
  text-transform:uppercase; color:var(--text-dim); text-decoration:none;
  border-bottom:1px solid transparent; padding-bottom:3px; transition:color 0.2s ease, border-color 0.2s ease; }
.hero-nav a:hover{ color:var(--amber); border-bottom-color:rgba(255,176,32,0.5); }
.crew-more{ font-family:'Share Tech Mono',monospace; font-size:14px; color:var(--text-dim);
  margin:26px 0 0; padding-top:18px; border-top:1px solid rgba(74,85,104,0.28); }
@keyframes pulse{ 0%,100%{opacity:0.4;} 50%{opacity:1;} }

/* ---- section headers ---- */
.sec-head{ display:flex; align-items:baseline; gap:14px; margin:0 0 34px; }
.sec-head .tag{ font-family:'Share Tech Mono',monospace; font-size:13.5px; color:var(--amber-dim); opacity:0.9; }
.sec-head h2{ font-family:'Oswald',sans-serif; font-weight:600; font-size:clamp(24px,3.1vw,32px);
  letter-spacing:0.04em; text-transform:uppercase; color:var(--text); margin:0; }
.sec-head .rule{ flex:1; height:1px; background:linear-gradient(90deg, var(--steel-lt), transparent); }

/* ---- the campaign's front page: hero, briefing, crew ----
   It used to be three panels behind a hash, switched from the header. The log
   and the crew map live in A.N.C.O.R. now, where every campaign has them, so
   what is left is two sections down one page and the wrapper only has to keep
   the measure. */
/* Kept for .wiki-panel, which is the wiki's own tabs -- a different thing that
   happens to share the motion. */
@keyframes panelIn{ from{ opacity:0; transform:translateY(6px); } to{ opacity:1; transform:translateY(0); } }
.onepage{ position:relative; z-index:1; max-width:960px; margin:0 auto; padding:20px 28px 100px; }
.onepage > section + section{ margin-top:56px; padding-top:44px;
  border-top:1px solid rgba(74,85,104,0.28); }

/* ---- transmission log ("what's happening now") ---- */
.log{ background:var(--panel); border:1px solid rgba(255,176,32,0.15); border-radius:6px; padding:6px 0; }
.log-entry{ padding:20px 26px; border-bottom:1px solid rgba(74,85,104,0.28); }
.log-entry:last-child{ border-bottom:none; }
.log-entry.pending{ background:rgba(255,176,32,0.08); border-left:3px solid var(--amber); padding-left:23px; }
.log-entry .meta{ display:flex; align-items:center; gap:10px; margin:0 0 8px; }
.log-entry .date{ font-family:'Share Tech Mono',monospace; font-size:13.5px; color:var(--amber); }
.log-entry .status{ font-family:'Share Tech Mono',monospace; font-size:11.5px; letter-spacing:0.1em;
  text-transform:uppercase; color:var(--text-dim); padding:2px 8px; border:1px solid var(--steel-lt); border-radius:3px; }
.log-entry .pending-tag{ font-family:'Share Tech Mono',monospace; font-size:11.5px; letter-spacing:0.1em;
  text-transform:uppercase; color:var(--amber); }
.log-entry h3{ font-family:'Oswald',sans-serif; font-weight:500; font-size:19.5px; margin:0 0 6px; color:var(--text); }
.log-entry p{ margin:0; color:var(--text-dim); font-size:17px; }
.log-entry .author{ font-family:'Share Tech Mono',monospace; font-size:12.5px; color:var(--text-dim); opacity:0.7; margin-top:8px; }

/* ---- top-right nav: Warden login/logout (matches 919gaming.com's top-nav) ---- */
.top-nav{ position:fixed; top:20px; right:24px; z-index:10;
  display:flex; flex-direction:column; align-items:flex-end; gap:10px; }
.top-nav a, .top-nav .log-status{ display:inline-flex; align-items:center; gap:7px; white-space:nowrap;
  font-family:'Share Tech Mono',monospace; font-size:12.5px; letter-spacing:0.1em; text-transform:uppercase;
  color:var(--amber); opacity:0.85; text-decoration:none; transition:opacity 0.2s ease, color 0.2s ease; }
.top-nav a:hover{ opacity:1; text-decoration:underline; }
.top-nav svg{ flex-shrink:0; width:13px; height:13px; }
.top-nav .log-status{ color:var(--text-dim); opacity:0.8; }

/* ---- facility log controls: add-entry + per-entry admin actions ---- */
.sec-head-tight{ margin-bottom:14px; }
.log-controls{ display:flex; align-items:center; flex-wrap:wrap; gap:14px; margin:0 0 18px; }
.log-link, .log-admin-actions button, .acct-actions button{
  display:inline-flex; align-items:center; gap:6px;
  font-family:'Share Tech Mono',monospace; font-size:13.5px; letter-spacing:0.06em;
  text-transform:uppercase; color:var(--amber); background:none; border:none;
  padding:6px 2px; cursor:pointer; text-decoration:none; }
.log-link:hover, .log-admin-actions button:hover, .acct-actions button:hover{ text-decoration:underline; }
.log-link svg, .log-admin-actions button svg, .acct-actions button svg{ flex-shrink:0; width:13px; height:13px; }
.log-admin-actions{ display:flex; gap:14px; margin-top:12px; }
.log-admin-actions .btn-danger, .acct-actions .btn-danger{ color:#e08a8a; }

.entry-form{ background:var(--panel); border:1px solid rgba(255,176,32,0.25); border-radius:6px;
  padding:20px 24px; margin:0 0 18px; }
.entry-form label{ display:block; font-family:'Share Tech Mono',monospace; font-size:12.5px; letter-spacing:0.08em;
  text-transform:uppercase; color:var(--text-dim); margin:12px 0 6px; }
.entry-form label:first-child{ margin-top:0; }
.entry-form input[type=text], .entry-form textarea{ width:100%; background:var(--void);
  border:1px solid var(--steel-lt); border-radius:4px; color:var(--text); font-family:'Barlow',sans-serif;
  font-size:16.5px; padding:9px 11px; }
.entry-form textarea{ min-height:90px; resize:vertical; }
.entry-form input[type=text]:focus, .entry-form textarea:focus{ outline:none; border-color:var(--amber); }
.entry-form-actions{ display:flex; gap:10px; margin-top:16px; }
.entry-form-actions button{ display:inline-flex; align-items:center; gap:7px;
  font-family:'Oswald',sans-serif; font-weight:600; font-size:14.5px; letter-spacing:0.06em;
  text-transform:uppercase; padding:9px 16px; border-radius:4px; border:none; cursor:pointer;
  background:var(--amber); color:#1a1305; }
.entry-form-actions button svg{ flex-shrink:0; width:14px; height:14px; }
.entry-form-actions button:hover{ filter:brightness(1.08); }
.entry-form-actions .btn-ghost{ background:none; border:none; color:var(--text-dim); padding-left:2px; padding-right:2px; }
.entry-form-actions .btn-ghost:hover{ filter:none; text-decoration:underline; }
.entry-form-msg{ font-family:'Share Tech Mono',monospace; font-size:13.5px; color:#e08a8a; margin:12px 0 0; }

/* ---- accounts tab ---- */
.acct-row{ padding:16px 26px; border-bottom:1px solid rgba(74,85,104,0.28); display:flex;
  justify-content:space-between; align-items:flex-start; gap:14px; }
.acct-row:last-child{ border-bottom:none; }
.acct-row.blocked{ background:rgba(220,80,80,0.06); }
.acct-name{ font-family:'Oswald',sans-serif; font-size:16.5px; color:var(--text); margin:0 0 4px; }
.acct-meta{ font-family:'Share Tech Mono',monospace; font-size:12.5px; color:var(--text-dim); margin:0; }
.acct-actions{ display:flex; gap:14px; flex-shrink:0; flex-wrap:wrap; justify-content:flex-end; align-items:center; }
.acct-select{ background:var(--void); border:1px solid rgba(74,85,104,0.5); color:var(--text);
  font-family:'Share Tech Mono',monospace; font-size:13.5px; padding:6px 8px; border-radius:4px; }
.acct-select:focus{ outline:none; border-color:var(--amber); }
.audit-section{ margin-top:28px; padding-top:20px; border-top:1px solid rgba(74,85,104,0.28); }
.audit-section h3{ font-family:'Oswald',sans-serif; font-size:17.5px; color:var(--text); margin:0 0 10px; font-weight:600; }
.audit-row{ font-family:'Share Tech Mono',monospace; font-size:12.5px; color:var(--text-dim);
  padding:8px 26px; border-bottom:1px solid rgba(74,85,104,0.18); }
.audit-row.denied{ color:#e08a8a; }

/* ---- synopsis ---- */
.synopsis p{ font-size:18.5px; color:var(--text); margin:0 0 18px; }
.synopsis p:last-child{ margin-bottom:0; }
.synopsis p:first-of-type::first-letter{ font-family:'Big Shoulders Stencil',sans-serif; font-size:56px;
  font-weight:800; color:var(--amber); float:left; line-height:0.8; margin:6px 10px 0 0; }
.redacted{ background:#d8dbe2; color:#d8dbe2; border-radius:2px; padding:0 2px; user-select:none; }
.ooc-note{ font-family:'Share Tech Mono',monospace; font-size:14.5px; color:var(--steel-lt);
  border-left:2px solid var(--steel); padding-left:14px; margin-top:26px !important; }
.briefing{ background:var(--panel); border:1px solid rgba(255,176,32,0.18); border-radius:6px;
  padding:26px 30px; margin-top:34px; }
.briefing h3{ font-family:'Oswald',sans-serif; font-weight:600; font-size:16.5px; letter-spacing:0.14em;
  text-transform:uppercase; color:var(--amber); margin:0 0 14px; }
.briefing ol{ margin:0; padding-left:22px; }
.briefing li{ font-size:18px; color:var(--text); margin-bottom:10px; }
.briefing li:last-child{ margin-bottom:0; }

/* ---- crew: mugshot lineup — cards link through to the full case file ---- */
.crew-grid{ display:grid; grid-template-columns:repeat(auto-fill,minmax(210px,1fr)); gap:18px; }
.crew-card{ position:relative; aspect-ratio:4/5; border-radius:6px; overflow:hidden; cursor:pointer;
  display:block; text-decoration:none; color:inherit;
  background:var(--panel); border:1px solid rgba(74,85,104,0.35);
  transition:border-color 0.2s ease, transform 0.2s ease; }
.crew-card:hover{ border-color:rgba(255,176,32,0.55); transform:translateY(-3px); }
.crew-card:focus-visible{ outline:1px solid var(--amber); outline-offset:3px; }
.crew-card img{ width:100%; height:100%; object-fit:cover; object-position:center 15%;
  display:block; filter:grayscale(0.15) contrast(1.05); transition:transform 0.35s ease, filter 0.35s ease; }
.crew-card:hover img{ transform:scale(1.06); filter:grayscale(0) contrast(1.1); }
.crew-card .card-index{ position:absolute; top:10px; left:10px; z-index:1;
  font-family:'Share Tech Mono',monospace; font-size:12px; letter-spacing:0.08em; color:var(--amber);
  background:rgba(5,6,10,0.65); border:1px solid rgba(255,176,32,0.4); border-radius:3px; padding:2px 7px; }
.crew-card .card-caption{ position:absolute; left:0; right:0; bottom:0; z-index:1; padding:30px 14px 14px;
  background:linear-gradient(to top, rgba(5,6,10,0.95) 0%, rgba(5,6,10,0.78) 55%, transparent 100%); }
.crew-card .card-caption h3{ font-family:'Oswald',sans-serif; font-weight:600; font-size:18.5px;
  margin:0 0 3px; color:var(--text); }
.crew-card .card-caption .role{ font-family:'Share Tech Mono',monospace; font-size:11.5px; color:var(--amber-dim);
  text-transform:uppercase; letter-spacing:0.03em; margin:0; line-height:1.35; }

footer{ position:relative; z-index:1; text-align:center; padding:40px 28px 60px; }
footer a{ font-family:'Share Tech Mono',monospace; font-size:13.5px; letter-spacing:0.14em;
  text-transform:uppercase; color:var(--text-dim); text-decoration:none; }
footer a:hover{ color:var(--amber); }

@media (prefers-reduced-motion: reduce){ .scroll-cue{ animation:none !important; } }

/* =========================================================================
   WIKI PAGES — /crew/<slug>, /who/<slug>, /place/<slug>, /sessions[/<n>]
   Rendered server-side by src/render.js.
   ========================================================================= */

/* ---- inline [[wiki links]] ---- */
/* The face inside an inline [[link]]. Sized in em so it tracks the type it
   lands in, and kept inside the line box: an inline image taller than the box
   pushes only the lines that contain one, so a paragraph ends up with uneven
   leading -- which is exactly what makes a page like that look broken.
   1.45em is 25px against 17px prose. The leading of every element that can
   hold a [[link]] was raised to suit it (1.7-1.6 -> 1.85-1.8); measured at
   both extremes, a line with four faces and a line with none come out the
   same height in all of them. */
.wl-av{ width:1.45em; height:1.45em; border-radius:50%; object-fit:cover;
  vertical-align:-0.32em; margin-right:0.26em; display:inline-block;
  border:1px solid rgba(255,176,32,0.35); background:var(--void-blue); }
/* The underline belongs to the name, not to the picture in front of it. */
.wikilink.has-av{ border-bottom:none; }
.wikilink.has-av .wl-name{ border-bottom:1px solid rgba(255,176,32,0.32); }
.wikilink.has-av:hover{ background:none; }
.wikilink.has-av:hover .wl-name{ border-bottom-color:var(--amber); background:rgba(255,176,32,0.08); }

.wikilink{ color:var(--amber); text-decoration:none; border-bottom:1px solid rgba(255,176,32,0.32); }
.wikilink:hover{ border-bottom-color:var(--amber); background:rgba(255,176,32,0.08); }
.wikilink.missing{ color:var(--text-dim); border-bottom:1px dotted rgba(136,144,160,0.55); cursor:help; }
.wikilink.sealed{ color:var(--text-dim); border-bottom:1px dashed rgba(255,176,32,0.35); cursor:help; }
.wikilink.sealed::after{ content:' ▪'; font-size:10.5px; vertical-align:super; color:var(--amber-dim); }

/* ---- page chrome ---- */
.wiki{ position:relative; z-index:1; max-width:1080px; margin:0 auto; padding:26px 28px 100px; }
.breadcrumb{ font-family:'Share Tech Mono',monospace; font-size:12.5px; letter-spacing:0.12em;
  text-transform:uppercase; color:var(--text-dim); margin:0 0 26px; display:flex; flex-wrap:wrap;
  align-items:center; gap:9px; }
.breadcrumb a{ color:var(--text-dim); text-decoration:none; }
.breadcrumb a:hover{ color:var(--amber); }
.breadcrumb .sep{ color:var(--steel-lt); }
.breadcrumb .here{ color:var(--amber); }

.wiki-head{ display:grid; grid-template-columns:220px 1fr; gap:30px; align-items:start; margin:0 0 34px; }
.wiki-head.no-portrait{ grid-template-columns:1fr; }
.wiki-portrait{ border-radius:6px; overflow:hidden; border:1px solid rgba(74,85,104,0.4);
  background:var(--void-blue); aspect-ratio:4/5; }
/* Tall portraits overflow this 4/5 box vertically, and the default
   object-position keeps the MIDDLE -- the chest on a standing figure. Anchor
   to the top so the head is what survives the crop. */
.wiki-portrait img{ width:100%; height:100%; object-fit:cover;
  object-position:center top; display:block; }
/* The record's preview image, across the top of its page. Deliberately the
   same 1200/630 window the link preview uses -- the page and the Discord
   unfurl show the same picture framed the same way, which is the whole point
   of having framed it. */
.wiki-hero{ position:relative; margin:0 0 30px; border-radius:6px; overflow:hidden;
  border:1px solid rgba(74,85,104,0.4); background:var(--void-blue); }
.wiki-hero a{ display:block; }
.wiki-hero a:focus-visible{ outline:2px solid var(--amber); outline-offset:-2px; }
.wiki-hero img{ width:100%; height:auto; aspect-ratio:1200/630; object-fit:cover; display:block; }
.wiki-hero figcaption{ position:absolute; left:0; right:0; bottom:0;
  display:flex; align-items:baseline; gap:12px; flex-wrap:wrap;
  padding:34px 16px 12px; pointer-events:none;
  background:linear-gradient(180deg, transparent, rgba(3,6,10,0.9)); }
.wh-cap{ font-size:15px; color:#e6eaf0; }
.wh-by{ font-family:'Share Tech Mono',monospace; font-size:11px; letter-spacing:0.08em;
  text-transform:uppercase; color:var(--amber); }
.wiki-title .index{ font-family:'Share Tech Mono',monospace; font-size:12.5px; letter-spacing:0.14em;
  text-transform:uppercase; color:var(--amber-dim); margin:0 0 8px; }
.wiki-title h1{ font-family:'Big Shoulders Stencil',sans-serif; font-weight:800;
  font-size:clamp(38px,7vw,68px); line-height:0.92; letter-spacing:0.01em; margin:0 0 10px; color:var(--text); }
.wiki-title .role{ font-family:'Share Tech Mono',monospace; font-size:13.5px; letter-spacing:0.05em;
  text-transform:uppercase; color:var(--amber); margin:0 0 16px; }
.wiki-title .tagline{ font-family:'Oswald',sans-serif; font-weight:400; font-size:18.5px;
  color:var(--text-dim); margin:0 0 18px; max-width:52ch; }

.factbar{ display:flex; flex-wrap:wrap; gap:8px; margin:0; padding:0; list-style:none; }
.factbar li{ font-family:'Share Tech Mono',monospace; font-size:12px; letter-spacing:0.06em;
  text-transform:uppercase; color:var(--text-dim); border:1px solid rgba(74,85,104,0.45);
  border-radius:3px; padding:4px 9px; }
.factbar li b{ color:var(--text); font-weight:500; }
.factbar li.status-alive b{ color:#7fd6a0; }
.factbar li.status-dead b, .factbar li.status-dying b{ color:#e08a8a; }
.factbar li.status-unknown b{ color:var(--amber); }

/* ---- in-page tab strip (crew pages) ---- */
.wiki-tabs{ display:flex; gap:2px; border-bottom:1px solid rgba(74,85,104,0.35); margin:0 0 32px;
  overflow-x:auto; scrollbar-width:none; }
.wiki-tabs::-webkit-scrollbar{ display:none; }
.wiki-tabs button{ background:none; border:none; cursor:pointer; white-space:nowrap; position:relative;
  font-family:'Oswald',sans-serif; font-weight:500; font-size:15px; letter-spacing:0.06em;
  text-transform:uppercase; color:var(--text-dim); padding:13px 18px; transition:color 0.2s ease; }
.wiki-tabs button .count{ font-family:'Share Tech Mono',monospace; font-size:11.5px; color:var(--steel-lt);
  margin-left:7px; }
.wiki-tabs button:hover{ color:var(--text); }
.wiki-tabs button.active{ color:var(--amber); }
.wiki-tabs button.active .count{ color:var(--amber-dim); }
.wiki-tabs button.active::after{ content:''; position:absolute; left:0; right:0; bottom:-1px; height:2px;
  background:var(--amber); box-shadow:0 0 8px rgba(255,176,32,0.6); }
.wiki-tabs button:focus-visible{ outline:1px solid var(--amber); outline-offset:3px; }
.wiki-panel[hidden]{ display:none; }
.wiki-panel{ animation:panelIn 0.25s ease; }

/* ---- prose blocks ---- */
.prose p{ font-size:17px; color:var(--text-dim); margin:0 0 14px; line-height:1.85; }
.prose p:last-child{ margin-bottom:0; }
.prose .line{ display:block; font-style:italic; color:var(--text); margin:0 0 14px; padding-left:14px;
  border-left:2px solid rgba(255,176,32,0.35); }
.prose strong{ color:var(--text); font-weight:600; }

.panel-card{ background:var(--panel); border:1px solid rgba(74,85,104,0.35); border-radius:6px;
  padding:24px 28px; margin:0 0 18px; }
.panel-card h3{ font-family:'Oswald',sans-serif; font-weight:600; font-size:16.5px; letter-spacing:0.1em;
  text-transform:uppercase; color:var(--amber); margin:0 0 14px; }
.empty-note{ font-family:'Share Tech Mono',monospace; font-size:14px; color:var(--steel-lt);
  border-left:2px solid var(--steel); padding-left:14px; margin:0; }

/* ---- timeline ---- */
.timeline{ position:relative; margin:0; padding:0 0 0 26px; list-style:none; }
.timeline::before{ content:''; position:absolute; left:5px; top:6px; bottom:6px; width:1px;
  background:linear-gradient(180deg, rgba(255,176,32,0.5), rgba(74,85,104,0.25)); }
.timeline > li{ position:relative; margin:0 0 26px; }
.timeline > li:last-child{ margin-bottom:0; }
.timeline > li::before{ content:''; position:absolute; left:-25px; top:7px; width:9px; height:9px;
  border-radius:50%; background:var(--void); border:2px solid var(--amber); }
.timeline .t-meta{ display:flex; align-items:baseline; flex-wrap:wrap; gap:10px; margin:0 0 8px; }
.timeline .t-num{ font-family:'Share Tech Mono',monospace; font-size:12.5px; letter-spacing:0.1em;
  text-transform:uppercase; color:var(--amber); text-decoration:none; }
.timeline .t-num:hover{ text-decoration:underline; }
.timeline .t-title{ font-family:'Oswald',sans-serif; font-weight:500; font-size:17.5px; color:var(--text); }
.timeline .t-date{ font-family:'Share Tech Mono',monospace; font-size:12px; color:var(--steel-lt); }

/* ---- connections + reference lists ---- */
.conn-list, .ref-list{ margin:0; padding:0; list-style:none; }
.conn-list > li, .ref-list > li{ padding:15px 0; border-bottom:1px solid rgba(74,85,104,0.22); }
.conn-list > li:first-child, .ref-list > li:first-child{ padding-top:0; }
.conn-list > li:last-child, .ref-list > li:last-child{ border-bottom:none; padding-bottom:0; }
.conn-head{ display:flex; align-items:baseline; flex-wrap:wrap; gap:10px; margin:0 0 5px; }
.conn-head .name{ font-family:'Oswald',sans-serif; font-weight:600; font-size:17px;
  color:var(--amber); text-decoration:none; }
.conn-head .name:hover{ text-decoration:underline; }
.conn-head .kind{ font-family:'Share Tech Mono',monospace; font-size:11.5px; letter-spacing:0.1em;
  text-transform:uppercase; color:var(--steel-lt); border:1px solid rgba(74,85,104,0.4);
  border-radius:3px; padding:1px 7px; }
.conn-note, .ref-snippet{ margin:0; font-size:16px; color:var(--text-dim); line-height:1.8; }
.ref-snippet{ font-style:italic; }
.ref-src{ font-family:'Share Tech Mono',monospace; font-size:12.5px; letter-spacing:0.04em;
  color:var(--amber); text-decoration:none; }
.ref-src:hover{ text-decoration:underline; }
.ref-sub{ font-family:'Share Tech Mono',monospace; font-size:11.5px; letter-spacing:0.08em;
  text-transform:uppercase; color:var(--steel-lt); margin-left:8px; }

/* ---- effects (things acquired) ---- */
.effects{ margin:0; padding:0; list-style:none; }
.effects > li{ display:flex; justify-content:space-between; align-items:flex-start; gap:16px;
  padding:13px 0; border-bottom:1px solid rgba(74,85,104,0.22); }
.effects > li:first-child{ padding-top:0; }
.effects > li:last-child{ border-bottom:none; padding-bottom:0; }
.effects .item{ font-family:'Oswald',sans-serif; font-weight:500; font-size:16.5px; color:var(--text);
  margin:0 0 4px; }
.effects .from{ font-family:'Share Tech Mono',monospace; font-size:12px; color:var(--amber);
  text-decoration:none; white-space:nowrap; flex-shrink:0; }
.effects .from:hover{ text-decoration:underline; }

/* ---- directory grids (/who, /place, /sessions) ---- */
.dir-grid{ display:grid; grid-template-columns:repeat(auto-fill,minmax(280px,1fr)); gap:14px; }
.dir-card{ display:block; text-decoration:none; color:inherit; background:var(--panel);
  border:1px solid rgba(74,85,104,0.35); border-radius:6px; padding:18px 20px;
  transition:border-color 0.2s ease, transform 0.2s ease; }
.dir-card:hover{ border-color:rgba(255,176,32,0.5); transform:translateY(-2px); }
.dir-card:focus-visible{ outline:1px solid var(--amber); outline-offset:3px; }
.dir-card .dir-name{ font-family:'Oswald',sans-serif; font-weight:600; font-size:18.5px; color:var(--text);
  margin:0 0 5px; }
.dir-card .dir-meta{ font-family:'Share Tech Mono',monospace; font-size:11.5px; letter-spacing:0.08em;
  text-transform:uppercase; color:var(--amber-dim); margin:0 0 9px; }
.dir-card .dir-summary{ font-size:15.5px; color:var(--text-dim); margin:0; line-height:1.8; }
.dir-group{ margin:0 0 38px; }
.dir-group > h3{ font-family:'Oswald',sans-serif; font-weight:600; font-size:15.5px; letter-spacing:0.12em;
  text-transform:uppercase; color:var(--text-dim); margin:0 0 14px;
  padding-bottom:8px; border-bottom:1px solid rgba(74,85,104,0.28); }

/* ---- session pages ---- */
.session-nav{ display:flex; justify-content:space-between; gap:14px; margin-top:40px; padding-top:22px;
  border-top:1px solid rgba(74,85,104,0.28); }
.session-nav a{ font-family:'Share Tech Mono',monospace; font-size:12.5px; letter-spacing:0.08em;
  text-transform:uppercase; color:var(--text-dim); text-decoration:none;
  border:1px solid rgba(74,85,104,0.5); border-radius:4px; padding:9px 15px; }
.session-nav a:hover{ color:var(--amber); border-color:rgba(255,176,32,0.5); }
.passage{ margin:0 0 26px; }
.passage:last-child{ margin-bottom:0; }
.passage-head{ display:flex; align-items:center; gap:12px; margin:0 0 10px; }
.passage-head img{ width:38px; height:38px; border-radius:50%; object-fit:cover;
  border:1px solid rgba(255,176,32,0.3); flex-shrink:0; }
.passage-head a{ font-family:'Oswald',sans-serif; font-weight:600; font-size:18px; color:var(--amber);
  text-decoration:none; }
.passage-head a:hover{ text-decoration:underline; }
.threads{ margin:0; padding:0; list-style:none; }
.threads > li{ padding:16px 0; border-bottom:1px solid rgba(74,85,104,0.22); }
.threads > li:first-child{ padding-top:0; }
.threads > li:last-child{ border-bottom:none; padding-bottom:0; }
.threads .th-title{ font-family:'Oswald',sans-serif; font-weight:600; font-size:17px; color:var(--text);
  margin:0 0 5px; }
.threads .th-body{ margin:0; font-size:16px; color:var(--text-dim); line-height:1.8; }

/* ---- sealed (crewOnly, not logged in) ---- */
.sealed-box{ background:var(--panel); border:1px solid rgba(255,176,32,0.3); border-radius:6px;
  padding:38px 34px; text-align:center; }
.sealed-box h2{ font-family:'Oswald',sans-serif; font-weight:600; font-size:20.5px; letter-spacing:0.06em;
  text-transform:uppercase; color:var(--amber); margin:0 0 10px; }
.sealed-box p{ color:var(--text-dim); margin:0 0 18px; font-size:16.5px; }

/* ---- Velveteen's theme: cool teal in place of amber, plus the slow gravity
   ripple that used to live on his dossier card. Opt in with data-theme. ---- */
[data-theme="velveteen"]{ --amber:#7fe0cf; --amber-dim:#4fae9c; }
[data-theme="velveteen"] .wiki-portrait{ position:relative; overflow:hidden; }
[data-theme="velveteen"] .wiki-portrait::after{
  content:''; position:absolute; inset:0; z-index:2; pointer-events:none; mix-blend-mode:screen;
  background:repeating-radial-gradient(circle at 50% 50%,
    rgba(127,224,207,0.16) 0px, rgba(127,224,207,0.16) 1.5px, transparent 1.5px, transparent 40px);
  animation:velveteenGravity 7s ease-in-out infinite; }
@keyframes velveteenGravity{
  0%,100%{ opacity:0.5; transform:scale(1); }
  50%{ opacity:0.95; transform:scale(1.08); } }
@media (prefers-reduced-motion: reduce){ [data-theme="velveteen"] .wiki-portrait::after{ animation:none; } }

@media (max-width:720px){
  .wiki-head{ grid-template-columns:1fr; gap:20px; }
  .wiki-portrait{ max-width:220px; }
  .wiki{ padding:20px 20px 80px; }
  .effects > li{ flex-direction:column; gap:6px; }
}

/* ---- bond chips: a one-word read on a relationship ---- */
.bond{ font-family:'Share Tech Mono',monospace; font-size:11.5px; letter-spacing:0.1em;
  text-transform:uppercase; border-radius:3px; padding:2px 8px; border:1px solid; }
.bond-good{ color:#7fd6a0; border-color:rgba(127,214,160,0.45); background:rgba(127,214,160,0.08); }
.bond-open{ color:var(--amber); border-color:rgba(255,176,32,0.45); background:rgba(255,176,32,0.08); }
.bond-bad{ color:#e08a8a; border-color:rgba(224,138,138,0.45); background:rgba(224,138,138,0.08); }

/* ---- ego network: one entity centred, strongest links around it. Bounded by
   design -- a whole-cast graph is a hairball by session 2. ---- */
.ego-wrap{ width:100%; overflow:hidden; }
.ego-svg{ width:100%; height:auto; display:block; }
.ego-svg a{ cursor:pointer; }
.ego-svg a:hover circle{ stroke-width:3; }
.ego-svg a:hover .ego-name{ fill:var(--amber); }
.ego-name{ font-family:'Oswald',sans-serif; font-size:14.5px; fill:var(--text); }
.ego-self{ font-family:'Oswald',sans-serif; font-weight:600; font-size:14.5px; fill:var(--amber); }

.ego-legend{ display:flex; flex-wrap:wrap; gap:8px 20px; margin-top:14px; padding-top:14px;
  border-top:1px solid rgba(74,85,104,0.28); }
.ego-legend span{ display:inline-flex; align-items:center; gap:7px;
  font-family:'Share Tech Mono',monospace; font-size:12px; letter-spacing:0.05em;
  text-transform:uppercase; color:var(--text-dim); }
.ego-legend i{ width:15px; height:2px; border-radius:1px; flex-shrink:0; }
.ego-legend i.dashed{ background:repeating-linear-gradient(90deg,#5a6478 0 3px,transparent 3px 6px); }
.ego-legend .cast-hint{ text-transform:none; letter-spacing:0; opacity:0.7; }

/* ---- cast timeline: sessions across, one lane per person. Grows sideways
   and scrolls, so it never tangles the way a graph does. ---- */
.cast-wrap{ width:100%; overflow-x:auto; scrollbar-width:thin; }
.cast-wrap::-webkit-scrollbar{ height:6px; }
.cast-wrap::-webkit-scrollbar-thumb{ background:rgba(255,176,32,0.3); border-radius:3px; }
.cast-svg{ display:block; height:auto; max-width:100%; }
.cast-svg a{ cursor:pointer; }
.cast-name{ font-family:'Oswald',sans-serif; font-size:14px; fill:var(--text-dim); }
.cast-name.crew{ fill:var(--text); }
.cast-svg a:hover .cast-name{ fill:var(--amber); }
.cast-col{ font-family:'Share Tech Mono',monospace; font-size:12.5px; fill:var(--amber-dim); }
/* Hub follows the page theme (amber, or teal on Velveteen's page); the bond
   colours deliberately do NOT theme -- they carry fixed meaning. */
.ego-hub{ fill:var(--panel); stroke:var(--amber); stroke-width:2; }

/* ---- homepage crew map: the party ring plus whoever they have named a bond
   with. Bounded by a cap on the outer ring, so unlike a whole-cast graph it
   cannot degenerate into a hairball as the campaign runs. ---- */
.crew-map-panel{ background:var(--panel); border:1px solid rgba(74,85,104,0.35);
  border-radius:6px; padding:22px 26px 18px; margin:0 0 22px; }
.crew-map-panel[hidden]{ display:none; }
.crew-map-panel h3{ font-family:'Oswald',sans-serif; font-weight:600; font-size:16.5px;
  letter-spacing:0.1em; text-transform:uppercase; color:var(--amber); margin:0 0 8px; }
.crew-map{ width:100%; }
.crew-map-svg{ width:100%; height:auto; display:block; }
.crew-map-svg a{ cursor:pointer; }
.crew-map-svg a:hover circle{ stroke-width:3; }
.crew-map-svg a:hover .ego-name{ fill:var(--amber); }
.map-crew{ fill:var(--panel); stroke:var(--amber); stroke-width:2; }
.map-npc{ fill:var(--panel); stroke:var(--steel-lt); stroke-width:2; }
.map-crew-label{ font-weight:600; fill:var(--text); }
.map-shared{ fill:var(--panel); stroke:var(--text-dim); stroke-width:2.5; }
.crew-map-svg a:has(.map-shared) .ego-name{ fill:var(--text); }
.as-of{ font-family:'Share Tech Mono',monospace; font-size:12.5px; letter-spacing:0.1em;
  text-transform:uppercase; color:var(--steel-lt); margin:18px 0 0; }

/* ---- crew map controls: filter by bond, focus one crew member, drag to
   untangle. Layout edits persist per browser (see assets/crewmap.js). ---- */
.map-controls{ display:flex; flex-wrap:wrap; align-items:center; gap:10px 18px; margin:0 0 16px; }
.map-chips{ display:flex; flex-wrap:wrap; gap:8px; }
.map-chip{ display:inline-flex; align-items:center; gap:7px; cursor:pointer;
  font-family:'Share Tech Mono',monospace; font-size:12px; letter-spacing:0.08em;
  text-transform:uppercase; color:var(--steel-lt); background:none;
  border:1px solid rgba(74,85,104,0.45); border-radius:3px; padding:5px 10px;
  transition:color 0.2s ease, border-color 0.2s ease, opacity 0.2s ease; opacity:0.5; }
.map-chip i{ width:10px; height:10px; border-radius:2px; flex-shrink:0; opacity:0.35; }
.map-chip.on{ color:var(--text); border-color:rgba(255,176,32,0.4); opacity:1; }
.map-chip.on i{ opacity:1; }
.map-chip:hover{ border-color:rgba(255,176,32,0.6); }
.map-focus{ display:inline-flex; align-items:center; gap:8px;
  font-family:'Share Tech Mono',monospace; font-size:12px; letter-spacing:0.08em;
  text-transform:uppercase; color:var(--text-dim); }
.map-reset{ margin-left:auto; cursor:pointer; background:none; border:none; padding:5px 2px;
  font-family:'Share Tech Mono',monospace; font-size:12px; letter-spacing:0.08em;
  text-transform:uppercase; color:var(--text-dim); }
.map-reset:hover{ color:var(--amber); text-decoration:underline; }

.map-node{ cursor:grab; transition:opacity 0.2s ease; }
.map-node.dragging{ cursor:grabbing; }
.map-node.dragging circle{ stroke-width:3.5; }
.map-edge{ transition:opacity 0.2s ease; }
.crew-map-svg{ touch-action:none; }
.map-hub{ fill:var(--panel); stroke:var(--amber); stroke-width:2.5; }

/* ---- crew standing: the whole party's line on someone, which is the normal
   case now. Individual entries below it are only the ones who differ. ---- */
.crew-standing{ border-color:rgba(255,176,32,0.3); }
.standing-line{ display:flex; align-items:flex-start; gap:12px; margin:0; }
.standing-note{ font-size:16.5px; color:var(--text); line-height:1.65; }
.standing-except{ font-family:'Share Tech Mono',monospace; font-size:12px; letter-spacing:0.12em;
  text-transform:uppercase; color:var(--text-dim); margin:20px 0 4px;
  padding-top:16px; border-top:1px solid rgba(74,85,104,0.28); }

/* =========================================================================
   GLOBAL NAV — server-rendered on every page (siteNav in src/render.js), and
   injected into the static index.html via HTMLRewriter so there is only one
   definition. Behaviour lives in assets/nav.js; every link works without it.
   ========================================================================= */
.site-nav{ position:sticky; top:0; z-index:40; backdrop-filter:blur(9px);
  background:linear-gradient(180deg, rgba(5,6,10,0.94), rgba(5,6,10,0.74));
  border-bottom:1px solid rgba(74,85,104,0.28);
  transition:border-color 0.25s ease, box-shadow 0.25s ease; }
.site-nav.scrolled{ border-bottom-color:rgba(255,176,32,0.28);
  box-shadow:0 10px 30px -18px rgba(0,0,0,0.9); }
.nav-inner{ max-width:1080px; margin:0 auto; padding:0 24px;
  display:flex; align-items:center; gap:22px; height:62px; }

.nav-brand{ text-decoration:none; flex-shrink:0; }
.nav-mark{ font-family:'Big Shoulders Stencil',sans-serif; font-weight:800; font-size:21.5px;
  letter-spacing:0.06em; color:var(--text); transition:color 0.2s ease, text-shadow 0.25s ease; }
.nav-brand:hover .nav-mark{ color:var(--amber); text-shadow:0 0 18px rgba(255,176,32,0.45); }

.nav-links{ position:relative; display:flex; align-items:center; gap:2px; flex:1; min-width:0; }
.nav-link{ position:relative; white-space:nowrap; text-decoration:none;
  font-family:'Oswald',sans-serif; font-weight:500; font-size:14.5px; letter-spacing:0.07em;
  text-transform:uppercase; color:var(--text-dim); padding:9px 13px; border-radius:4px;
  transition:color 0.18s ease, background 0.18s ease; }
.nav-link:hover{ color:var(--text); background:rgba(255,255,255,0.035); }
.nav-link.active{ color:var(--amber); }
.nav-ink{ position:absolute; left:0; bottom:-1px; height:2px; width:0; opacity:0;
  background:var(--amber); border-radius:2px; box-shadow:0 0 10px rgba(255,176,32,0.7);
  transition:transform 0.32s cubic-bezier(.22,1,.36,1), width 0.32s cubic-bezier(.22,1,.36,1), opacity 0.2s ease;
  pointer-events:none; }

.nav-tools{ display:flex; align-items:center; gap:12px; flex-shrink:0; }
.nav-search-btn{ display:inline-flex; align-items:center; gap:8px; cursor:pointer;
  background:rgba(255,255,255,0.04); border:1px solid rgba(74,85,104,0.45); border-radius:5px;
  color:var(--text-dim); padding:6px 11px;
  font-family:'Share Tech Mono',monospace; font-size:12.5px; letter-spacing:0.08em; text-transform:uppercase;
  transition:border-color 0.2s ease, color 0.2s ease, background 0.2s ease; }
.nav-search-btn:hover{ color:var(--text); border-color:rgba(255,176,32,0.5); background:rgba(255,176,32,0.07); }
.nav-search-btn svg{ width:13px; height:13px; flex-shrink:0; }
.nav-search-hint{ display:inline-flex; align-items:center; gap:7px; }
.nav-search-hint kbd, .search-esc{ font-family:'Share Tech Mono',monospace; font-size:11.5px;
  border:1px solid rgba(74,85,104,0.6); border-radius:3px; padding:1px 5px; color:var(--steel-lt); }

.nav-user{ font-family:'Share Tech Mono',monospace; font-size:12.5px; color:var(--text-dim); white-space:nowrap; }
.nav-account{ display:inline-flex; align-items:center; gap:6px; text-decoration:none; white-space:nowrap;
  font-family:'Share Tech Mono',monospace; font-size:12.5px; letter-spacing:0.09em; text-transform:uppercase;
  color:var(--amber); opacity:0.85; transition:opacity 0.2s ease; }
.nav-account:hover{ opacity:1; text-decoration:underline; }
.nav-account svg{ width:13px; height:13px; flex-shrink:0; }

.nav-menu-btn{ display:none; cursor:pointer; background:none; border:none; color:var(--text-dim); padding:6px; }
.nav-menu-btn svg{ width:20px; height:20px; }
.nav-menu-btn:hover{ color:var(--amber); }
.nav-drawer{ display:none; flex-direction:column; padding:8px 24px 16px; gap:2px;
  border-top:1px solid rgba(74,85,104,0.28); animation:drawerIn 0.22s cubic-bezier(.22,1,.36,1); }
.nav-drawer[hidden]{ display:none; }
@keyframes drawerIn{ from{ opacity:0; transform:translateY(-8px); } to{ opacity:1; transform:none; } }

/* ---- search overlay ---- */
.search-overlay{ position:fixed; inset:0; z-index:60; display:flex; justify-content:center;
  align-items:flex-start; padding:12vh 20px 20px; background:rgba(3,4,7,0.78);
  opacity:0; transition:opacity 0.18s ease; }
.search-overlay.open{ opacity:1; }
.search-overlay[hidden]{ display:none; }
.search-box{ width:100%; max-width:660px; background:var(--panel);
  border:1px solid rgba(255,176,32,0.25); border-radius:8px; overflow:hidden;
  box-shadow:0 30px 80px -30px rgba(0,0,0,0.95);
  transform:translateY(-10px) scale(0.985); opacity:0;
  transition:transform 0.24s cubic-bezier(.22,1,.36,1), opacity 0.2s ease; }
.search-overlay.open .search-box{ transform:none; opacity:1; }
.search-field{ display:flex; align-items:center; gap:12px; padding:16px 18px;
  border-bottom:1px solid rgba(74,85,104,0.3); }
.search-field svg{ width:17px; height:17px; color:var(--amber); flex-shrink:0; }
.search-field input{ flex:1; min-width:0; background:none; border:none; outline:none;
  color:var(--text); font-family:'Barlow',sans-serif; font-size:18px; }
.search-field input::placeholder{ color:var(--steel-lt); }
.search-field input::-webkit-search-cancel-button{ display:none; }

.search-results{ max-height:56vh; overflow-y:auto; scrollbar-width:thin; }
.search-results::-webkit-scrollbar{ width:6px; }
.search-results::-webkit-scrollbar-thumb{ background:rgba(255,176,32,0.3); border-radius:3px; }
.sr-empty{ font-family:'Share Tech Mono',monospace; font-size:14px; color:var(--steel-lt);
  margin:0; padding:22px 20px; line-height:1.6; }
.sr-row{ display:flex; align-items:flex-start; gap:12px; padding:12px 18px; text-decoration:none;
  border-bottom:1px solid rgba(74,85,104,0.18); border-left:2px solid transparent;
  animation:srIn 0.26s cubic-bezier(.22,1,.36,1) backwards; animation-delay:calc(var(--i) * 22ms); }
@keyframes srIn{ from{ opacity:0; transform:translateY(6px); } to{ opacity:1; transform:none; } }
.sr-row:last-child{ border-bottom:none; }
.sr-row.sel{ background:rgba(255,176,32,0.08); border-left-color:var(--amber); }
.sr-type{ font-family:'Share Tech Mono',monospace; font-size:11px; letter-spacing:0.1em;
  text-transform:uppercase; padding:3px 7px; border-radius:3px; flex-shrink:0; margin-top:2px;
  border:1px solid rgba(74,85,104,0.5); color:var(--text-dim); }
.sr-crew{ color:var(--amber); border-color:rgba(255,176,32,0.45); }
.sr-npc{ color:#7fd6a0; border-color:rgba(127,214,160,0.4); }
.sr-place{ color:#8fb8e8; border-color:rgba(143,184,232,0.4); }
.sr-session{ color:#c9a6e8; border-color:rgba(201,166,232,0.4); }
.sr-text{ flex:1; min-width:0; }
.sr-name{ display:block; font-family:'Oswald',sans-serif; font-weight:500; font-size:16.5px; color:var(--text); }
.sr-snippet{ font-size:14.5px; color:var(--text-dim); line-height:1.5; margin-top:2px;
  overflow:hidden; display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical; }
.sr-row mark{ background:rgba(255,176,32,0.22); color:var(--amber); border-radius:2px; padding:0 1px; }
.sr-sub{ font-family:'Share Tech Mono',monospace; font-size:11.5px; color:var(--steel-lt);
  flex-shrink:0; margin-top:4px; white-space:nowrap; }

/* the old fixed corner login is superseded by the nav bar */
.top-nav{ display:none; }
.wiki{ padding-top:34px; }

/* 949, down from 1060: Admin and Site left the bar for the account menu, so
   a God account now sees the same four items as everybody else -- Briefing,
   Crew, Log, Archive.

   Measured, not guessed: the row needs 766px with the names it actually
   carries, and 946px in the worst case the caps allow (a 22-character
   campaign name in the brand, a 15-character name on the account control).
   The breakpoint is the worst case, so a long campaign name cannot push the
   row under the search button the way ten items used to. */
@media (max-width:949px){
  .nav-links{ display:none; }
  .nav-menu-btn{ display:inline-flex; }
  .nav-search-hint{ display:none; }
  .nav-account span{ display:none; }
  .site-nav.drawer-open .nav-drawer{ display:flex; }
  .nav-drawer .nav-link{ padding:11px 4px; }
}
@media (prefers-reduced-motion: reduce){
  .nav-ink, .search-box, .sr-row, .nav-drawer{ transition:none !important; animation:none !important; }
}

/* publish-a-dispatch control in the log header */
.log-link.publish-ready{ color:#7fd6a0; }
.log-link.publish-ready:hover{ text-decoration:underline; }
.publish-hint{ font-family:'Share Tech Mono',monospace; font-size:12.5px; letter-spacing:0.05em;
  color:var(--steel-lt); align-self:center; }

/* =========================================================================
   CREW DROPDOWN — the portrait menu under "Crew" in the global nav.
   Markup comes from navLinks()/drawerLinks() in src/render.js; behaviour from
   assets/nav.js. Without JS the :hover rules below still open it, which is why
   they are scoped to .site-nav:not(.js) -- nav.js adds .js on init and takes
   over, so hover, focus and click can never fight each other for the state.
   ========================================================================= */
.nav-item{ position:relative; display:inline-flex; align-items:center; }
.nav-item > .nav-link{ display:inline-flex; align-items:center; gap:5px; }
.nav-chev{ width:11px; height:11px; opacity:0.55; flex-shrink:0;
  transition:transform 0.28s cubic-bezier(.22,1,.36,1), opacity 0.2s ease; }
.nav-item.open > .nav-link .nav-chev,
.site-nav:not(.js) .nav-item:hover > .nav-link .nav-chev{ transform:rotate(180deg); opacity:1; }
.nav-item.open > .nav-link{ color:var(--text); }

/* The wrapper is the hover bridge: its padding-top spans the gap between the
   bar and the card, so the pointer never crosses dead space on the way down. */
.nav-pop{ position:absolute; top:100%; left:50%; z-index:50; padding-top:11px;
  transform:translateX(-50%); opacity:0; visibility:hidden; pointer-events:none;
  transition:opacity 0.16s ease, visibility 0s linear 0.22s; }
.nav-item.open > .nav-pop,
.site-nav:not(.js) .nav-item:hover > .nav-pop,
.site-nav:not(.js) .nav-item:focus-within > .nav-pop{
  opacity:1; visibility:visible; pointer-events:auto; transition-delay:0s, 0s; }

/* Without JS there is no viewport clamp, so below the width where a centred
   panel would hang off the left edge, anchor it to the trigger instead. */
@media (max-width:1120px){
  .site-nav:not(.js) .nav-pop{ left:0; transform:none; }
}

.nav-pop-card{ position:relative; width:min(660px, calc(100vw - 28px));
  background:linear-gradient(180deg, #151925, var(--panel));
  border:1px solid rgba(255,176,32,0.22); border-radius:9px; overflow:hidden;
  box-shadow:0 34px 70px -28px rgba(0,0,0,0.95), 0 0 0 1px rgba(5,6,10,0.6);
  transform:translateY(-9px) scale(0.975); transform-origin:top center; opacity:0;
  transition:transform 0.28s cubic-bezier(.22,1,.36,1), opacity 0.2s ease; }
.nav-item.open > .nav-pop > .nav-pop-card,
.site-nav:not(.js) .nav-item:hover > .nav-pop > .nav-pop-card,
.site-nav:not(.js) .nav-item:focus-within > .nav-pop > .nav-pop-card{
  transform:none; opacity:1; }
/* HUD hairline across the top, same amber sweep as the section rules */
.nav-pop-card::before{ content:''; position:absolute; left:0; right:0; top:0; height:1px;
  background:linear-gradient(90deg, transparent, var(--amber), transparent); opacity:0.55; }

.cm-grid{ display:grid; grid-template-columns:1fr; padding:7px; gap:1px; }
@media (min-width:1000px){ .cm-grid{ grid-template-columns:1fr 1fr; } }

.cm-card{ display:flex; align-items:center; gap:12px; padding:8px 10px; border-radius:6px;
  min-width:0;
  text-decoration:none; position:relative;
  transition:background 0.18s ease, transform 0.18s cubic-bezier(.22,1,.36,1); }
.cm-card:hover, .cm-card:focus-visible{ background:rgba(255,176,32,0.075); outline:none; }
.cm-card:focus-visible{ box-shadow:inset 0 0 0 1px rgba(255,176,32,0.55); }

.cm-av{ position:relative; width:46px; height:46px; flex-shrink:0; border-radius:5px;
  overflow:hidden; background:radial-gradient(circle at 50% 26%, #39415a, #141926 76%);
  border:1px solid rgba(74,85,104,0.55); display:grid; place-items:center;
  box-shadow:inset 0 1px 0 rgba(255,255,255,0.07);
  transition:border-color 0.2s ease, box-shadow 0.25s ease; }
.cm-av img{ width:100%; height:100%; object-fit:cover; display:block;
  transition:transform 0.35s cubic-bezier(.22,1,.36,1); }
.cm-card:hover .cm-av, .cm-card:focus-visible .cm-av{
  border-color:rgba(255,176,32,0.65); box-shadow:0 0 14px -2px rgba(255,176,32,0.4); }
.cm-card:hover .cm-av img{ transform:scale(1.07); }
.cm-initial{ font-family:'Big Shoulders Stencil',sans-serif; font-weight:800; font-size:24px;
  color:var(--steel-lt); }

.cm-meta{ flex:1; min-width:0; }
.cm-name{ display:flex; align-items:center; gap:7px; font-family:'Oswald',sans-serif;
  font-weight:500; font-size:16.5px; letter-spacing:0.02em; color:var(--text);
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
  transition:color 0.18s ease; }
.cm-card:hover .cm-name, .cm-card:focus-visible .cm-name{ color:var(--amber); }
.cm-nick{ font-family:'Share Tech Mono',monospace; font-size:11px; letter-spacing:0.09em;
  text-transform:uppercase; color:var(--amber-dim); border:1px solid rgba(255,176,32,0.35);
  border-radius:3px; padding:1px 5px; flex-shrink:0; }
.cm-sub{ display:block; font-family:'Barlow',sans-serif; font-size:13px; color:var(--text-dim);
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis; margin-top:1px; }
.cm-player{ font-family:'Share Tech Mono',monospace; font-size:11px; letter-spacing:0.08em;
  text-transform:uppercase; color:#66738c; flex-shrink:0; align-self:flex-start;
  margin-top:3px; }

.cm-foot{ display:flex; align-items:center; gap:8px; padding:11px 17px;
  border-top:1px solid rgba(74,85,104,0.3); background:rgba(0,0,0,0.22);
  font-family:'Share Tech Mono',monospace; font-size:12px; letter-spacing:0.1em;
  text-transform:uppercase; color:var(--text-dim); text-decoration:none;
  transition:color 0.18s ease, background 0.18s ease; }
.cm-foot:hover{ color:var(--amber); background:rgba(255,176,32,0.06); }
.cm-arrow{ width:13px; height:13px; transition:transform 0.24s cubic-bezier(.22,1,.36,1); }
.cm-foot:hover .cm-arrow{ transform:translateX(4px); }

/* Cards deal themselves in when the panel opens. `backwards` holds them
   invisible through the delay so nothing flashes at full opacity first. */
.nav-item.open .cm-card,
.site-nav:not(.js) .nav-item:hover .cm-card{
  animation:cmDeal 0.36s cubic-bezier(.22,1,.36,1) backwards;
  animation-delay:calc(var(--i) * 34ms + 40ms); }
@keyframes cmDeal{ from{ opacity:0; transform:translateY(9px); } to{ opacity:1; transform:none; } }

/* ---- the same list inside the mobile drawer ---- */
.nav-drawer{ max-height:calc(100vh - 62px); max-height:calc(100dvh - 62px);
  overflow-y:auto; overscroll-behavior:contain; scrollbar-width:thin; }
.drawer-menu summary{ display:flex; align-items:center; justify-content:space-between;
  cursor:pointer; list-style:none; }
.drawer-menu summary::-webkit-details-marker{ display:none; }
.drawer-menu[open] summary .nav-chev{ transform:rotate(180deg); opacity:1; }
.drawer-menu[open] > .cm-grid{ animation:drawerIn 0.24s cubic-bezier(.22,1,.36,1); }
.drawer-menu > .cm-grid{ padding:2px 0 4px; }
.drawer-menu .cm-card{ padding:7px 8px; }
.drawer-menu .cm-foot{ border-top:none; background:none; padding:6px 8px 12px; }

@media (prefers-reduced-motion: reduce){
  .nav-pop, .nav-pop-card, .cm-card, .cm-av, .cm-av img, .cm-arrow, .nav-chev,
  .drawer-menu[open] > .cm-grid{ transition:none !important; animation:none !important; }
}

/* =========================================================================
   FACETED DIRECTORIES — /who, /place, /sessions.
   Rail markup from facetRail()/facetLayout() in src/render.js, behaviour in
   assets/facets.js. The <noscript> block in facetLayout hides the rail when
   there is no JS, so the full server-rendered list is what remains.
   ========================================================================= */
.wiki-wide{ max-width:1280px; }

.facet-layout{ display:grid; grid-template-columns:236px minmax(0,1fr); gap:34px;
  align-items:start; }
.facet-main{ min-width:0; }

.facet-rail{ position:sticky; top:80px; align-self:start;
  max-height:calc(100vh - 102px); max-height:calc(100dvh - 102px);
  overflow-y:auto; overscroll-behavior:contain; scrollbar-width:thin;
  padding-right:4px; }
.facet-rail::-webkit-scrollbar{ width:6px; }
.facet-rail::-webkit-scrollbar-thumb{ background:rgba(255,176,32,0.25); border-radius:3px; }

.facet-search{ display:flex; align-items:center; gap:9px; background:var(--panel);
  border:1px solid rgba(74,85,104,0.45); border-radius:5px; padding:9px 11px; margin-bottom:14px;
  transition:border-color 0.2s ease; }
.facet-search:focus-within{ border-color:rgba(255,176,32,0.55); }
.facet-search svg{ width:14px; height:14px; color:var(--amber); flex-shrink:0; }
.facet-search input{ flex:1; min-width:0; background:none; border:none; outline:none;
  color:var(--text); font-family:'Barlow',sans-serif; font-size:15px; }
.facet-search input::placeholder{ color:var(--steel-lt); }
.facet-search input::-webkit-search-cancel-button{ display:none; }

.facet-clear{ display:block; width:100%; cursor:pointer; margin-bottom:18px;
  background:rgba(255,176,32,0.08); border:1px solid rgba(255,176,32,0.4); border-radius:4px;
  color:var(--amber); padding:7px 10px;
  font-family:'Share Tech Mono',monospace; font-size:11.5px; letter-spacing:0.1em; text-transform:uppercase;
  transition:background 0.18s ease; }
.facet-clear:hover{ background:rgba(255,176,32,0.16); }
.facet-clear[hidden]{ display:none; }

/* The global section{} rule carries 90px of page padding and a 960px cap --
   these are structural sections inside a column, so they opt out of both. */
.facet-group, .dir-group{ max-width:none; margin-left:0; margin-right:0; padding:0; }
.facet-group{ margin:0 0 22px; }
.facet-group h3{ font-family:'Share Tech Mono',monospace; font-size:11.5px; letter-spacing:0.13em;
  text-transform:uppercase; color:var(--amber-dim); margin:0 0 9px;
  padding-bottom:7px; border-bottom:1px solid rgba(74,85,104,0.28); }
.facet-group ul{ list-style:none; margin:0; padding:0; }
.facet-group li{ transition:opacity 0.2s ease; }
.facet-group li.fo-empty{ opacity:0.32; }
.facet-group input{ position:absolute; opacity:0; width:0; height:0; }
.facet-group label{ display:flex; align-items:center; gap:9px; cursor:pointer;
  padding:5px 7px; border-radius:4px; font-family:'Barlow',sans-serif; font-size:15px;
  color:var(--text-dim); transition:color 0.16s ease, background 0.16s ease; }
.facet-group label:hover{ color:var(--text); background:rgba(255,255,255,0.035); }
/* The box is drawn on the label so the whole row is the hit target. */
.facet-group label::before{ content:''; width:13px; height:13px; flex-shrink:0; border-radius:3px;
  border:1px solid rgba(74,85,104,0.75); background:rgba(0,0,0,0.25);
  transition:border-color 0.16s ease, background 0.16s ease, box-shadow 0.2s ease; }
.facet-group input:checked + label{ color:var(--amber); }
.facet-group input:checked + label::before{ border-color:var(--amber); background:var(--amber);
  box-shadow:0 0 9px -1px rgba(255,176,32,0.65); }
.facet-group input:focus-visible + label{ outline:1px solid var(--amber); outline-offset:2px; }
.fo-label{ flex:1; min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.fo-count{ font-family:'Share Tech Mono',monospace; font-size:11.5px; color:var(--steel-lt);
  flex-shrink:0; }

.facet-count{ font-family:'Share Tech Mono',monospace; font-size:12.5px; letter-spacing:0.09em;
  text-transform:uppercase; color:var(--amber-dim); margin:0 0 18px; }
.facet-count[hidden], .facet-empty[hidden]{ display:none; }
.facet-empty{ font-family:'Share Tech Mono',monospace; font-size:14px; color:var(--steel-lt);
  margin:0; padding:26px 0; }

/* ---- cards ---- */
/* A card is an <article>: summaries carry [[links]], and an <a> inside an <a>
   is invalid -- the browser closes the outer one and the rest of the card
   falls out of it. The name link is stretched over the card instead, so the
   card stays clickable AND the cross-references inside it keep working. */
.dir-card{ position:relative; }
.dir-card[hidden]{ display:none; }
a.dir-name{ display:block; text-decoration:none; }
a.dir-name::after{ content:''; position:absolute; inset:0; border-radius:6px; }
.dir-card .dir-summary .wikilink,
.dir-card .dir-summary a{ position:relative; z-index:1; }
.dir-card:focus-within{ border-color:rgba(255,176,32,0.5); }
a.dir-name:focus-visible{ outline:none; }
a.dir-name:focus-visible::after{ outline:1px solid var(--amber); outline-offset:3px; }

.dir-bond{ display:inline-block; margin-left:8px; padding:1px 6px; border-radius:3px;
  border:1px solid currentColor; font-size:10.5px; letter-spacing:0.09em; }
.dir-bond.bond-good{ color:#7fd6a0; }
.dir-bond.bond-open{ color:var(--amber-dim); }
.dir-bond.bond-bad{ color:#e08a7a; }

.dir-cast{ display:flex; flex-wrap:wrap; gap:5px; margin:12px 0 0; }
.dir-chip{ font-family:'Share Tech Mono',monospace; font-size:11px; letter-spacing:0.06em;
  padding:2px 6px; border-radius:3px; border:1px solid rgba(74,85,104,0.5); color:var(--text-dim); }
.dir-chip.chip-crew{ color:var(--amber); border-color:rgba(255,176,32,0.4); }
.dir-chip.chip-npc{ color:#7fd6a0; border-color:rgba(127,214,160,0.35); }
.dir-chip.chip-place{ color:#8fb8e8; border-color:rgba(143,184,232,0.35); }
.dir-chip.chip-more{ color:var(--steel-lt); }

.dir-group[hidden]{ display:none; }
.dir-group > h3 a{ color:inherit; text-decoration:none; }
.dir-group > h3 a:hover{ color:var(--amber); }
.dir-group-count{ float:right; font-family:'Share Tech Mono',monospace; font-size:11.5px;
  letter-spacing:0.08em; color:var(--steel-lt); text-transform:none; }

/* ---- places contain places ---- */
.inside-list{ list-style:none; margin:0; padding:0; display:grid;
  grid-template-columns:repeat(auto-fill,minmax(268px,1fr)); gap:2px 20px; }
.inside-list li{ display:flex; align-items:center; gap:9px; padding:8px 10px; border-radius:4px;
  transition:background 0.16s ease; }
.inside-list li:hover{ background:rgba(255,255,255,0.035); }
.inside-list a{ font-family:'Oswald',sans-serif; font-weight:500; font-size:16px;
  color:var(--text); text-decoration:none; flex:1; min-width:0; }
.inside-list li:hover a{ color:var(--amber); }
.inside-kind, .inside-status{ font-family:'Share Tech Mono',monospace; font-size:11px;
  letter-spacing:0.07em; text-transform:uppercase; color:var(--steel-lt); flex-shrink:0; }

/* ---- the rail becomes a sheet on small screens ---- */
.facet-toggle{ display:none; align-items:center; gap:8px; cursor:pointer;
  background:var(--panel); border:1px solid rgba(255,176,32,0.35); border-radius:5px;
  color:var(--amber); padding:9px 14px; margin-bottom:18px;
  font-family:'Share Tech Mono',monospace; font-size:12.5px; letter-spacing:0.1em; text-transform:uppercase; }
.facet-toggle svg{ width:14px; height:14px; }

@media (max-width:900px){
  .facet-layout{ grid-template-columns:1fr; gap:0; }
  .facet-toggle{ display:inline-flex; }
  .facet-rail{ position:static; max-height:0; overflow:hidden; padding:0;
    transition:max-height 0.3s cubic-bezier(.22,1,.36,1); }
  .facet-rail.open{ max-height:1400px; overflow-y:auto; margin-bottom:24px; }
  .facet-toggle[aria-expanded="true"] svg{ color:var(--text); }
}
@media (prefers-reduced-motion: reduce){
  .facet-rail, .facet-group li, .facet-group label, .inside-list li{
    transition:none !important; }
}

/* A panel-card that folds. The dispatch cast timeline is context for the
   archive below it, not the reason you opened the page, so it starts closed
   and the filters are what you land on. */
.panel-fold > summary{ cursor:pointer; list-style:none; display:flex; align-items:center; gap:10px; }
.panel-fold > summary::-webkit-details-marker{ display:none; }
.panel-fold > summary h3{ margin:0; }
.panel-fold > summary::after{ content:'▾'; margin-left:auto; color:var(--steel-lt); font-size:13.5px;
  transition:transform 0.25s cubic-bezier(.22,1,.36,1); }
.panel-fold[open] > summary::after{ transform:rotate(180deg); }
.panel-fold > summary:hover::after{ color:var(--amber); }

/* =========================================================================
   A.N.C.O.R. — the archive's skin.
   Everything hangs off [data-system="ancor"] on <html>, set by layout() in
   src/render.js. The two halves of the site share every component; only the
   tokens change, so a card built for Hard Times arrives here already dressed.
   Amber is the campaign. Cold phosphor is the machine.
   ========================================================================= */
[data-system="ancor"]{
  --void:#03080b; --void-2:#061014; --void-blue:#030a10; --panel:#0a161b;
  --steel:#16323a; --steel-lt:#3d6b76;
  --amber:#39d4c8; --amber-dim:#1f8f88; --rust:#2a6a72;
  --text:#cfe6e6; --text-dim:#7e9ca1;
}
[data-system="ancor"] body{ background:var(--void); }

/* Phosphor scanlines over the whole system, faint enough to read through. */
[data-system="ancor"] .static{
  background-image:repeating-linear-gradient(0deg,
    rgba(57,212,200,0.045) 0px, rgba(57,212,200,0.045) 1px, transparent 1px, transparent 3px);
  opacity:1; mix-blend-mode:screen; }
[data-system="ancor"] .hud-bg{ opacity:0.5; }

[data-system="ancor"] .nav-mark{ font-family:'Share Tech Mono',monospace; font-size:17.5px;
  letter-spacing:0.16em; }
.nav-brand-sys{ display:flex; align-items:baseline; gap:9px; }
.nav-sub{ font-family:'Share Tech Mono',monospace; font-size:10.5px; letter-spacing:0.22em;
  color:var(--steel-lt); }
[data-system="ancor"] .nav-link{ font-family:'Share Tech Mono',monospace; font-size:12.5px;
  letter-spacing:0.13em; }
[data-system="ancor"] .site-nav{ border-bottom-color:rgba(57,212,200,0.22); }

/* The archive carries six sections where the campaign carries four, so its
   bar gets the width its own record pages use and slightly tighter tracking. */
[data-system="ancor"] .nav-inner{ max-width:1280px; }
[data-system="ancor"] .nav-link{ padding:9px 10px; letter-spacing:0.09em; }

/* The campaign name beside the wordmark is the first thing to go when the row
   gets tight. It is the nicest thing in the bar and the most redundant: the
   section next to it says Overview and goes to the same campaign, and the
   account menu names it again. Dropping it here buys about 90px, which is the
   difference between the archive keeping its bar on a 1080p laptop and not. */
@media (max-width:1240px){
  [data-system="ancor"] .nav-sub{ display:none; }
}

/* ---- the front door ---- */
.sys-boot{ font-family:'Share Tech Mono',monospace; font-size:13px; letter-spacing:0.08em;
  color:var(--amber-dim); border:1px solid rgba(57,212,200,0.22); border-radius:5px;
  background:rgba(3,12,16,0.6); padding:16px 18px; margin:0 0 34px; }
.boot-line{ margin:0 0 4px; opacity:0; animation:bootIn 0.3s steps(1) forwards;
  animation-delay:calc(var(--i) * 260ms); }
.boot-line:last-child{ color:var(--amber); margin-bottom:0; }
.boot-line::before{ content:'> '; color:var(--steel-lt); }
@keyframes bootIn{ to{ opacity:1; } }

.sys-head{ margin:0 0 32px; }
.sys-head h1{ font-family:'Share Tech Mono',monospace; font-size:clamp(34px,7vw,62px);
  letter-spacing:0.14em; color:var(--text); margin:0;
  text-shadow:0 0 26px rgba(57,212,200,0.35); }
.sys-expand{ font-family:'Share Tech Mono',monospace; font-size:13px; letter-spacing:0.16em;
  text-transform:uppercase; color:var(--amber-dim); margin:8px 0 0; }
.sys-blurb{ font-family:'Barlow',sans-serif; font-size:17px; color:var(--text-dim);
  max-width:60ch; line-height:1.7; margin:16px 0 0; }

.sys-stats{ display:grid; grid-template-columns:repeat(auto-fit,minmax(128px,1fr)); gap:1px;
  background:rgba(57,212,200,0.16); border:1px solid rgba(57,212,200,0.16); border-radius:6px;
  overflow:hidden; margin:0 0 30px; }
.sys-stat{ background:var(--panel); padding:18px 16px; text-decoration:none; display:block;
  transition:background 0.2s ease; }
.sys-stat:hover{ background:#0e2129; }
.sys-n{ display:block; font-family:'Share Tech Mono',monospace; font-size:32px; color:var(--amber);
  line-height:1; text-shadow:0 0 16px rgba(57,212,200,0.4); }
.sys-l{ display:block; font-family:'Share Tech Mono',monospace; font-size:11px; letter-spacing:0.14em;
  text-transform:uppercase; color:var(--text-dim); margin-top:8px; }

.sys-doors{ display:grid; grid-template-columns:repeat(auto-fit,minmax(260px,1fr)); gap:12px;
  margin:0 0 34px; }
.sys-door{ display:flex; align-items:center; gap:12px; text-decoration:none; padding:16px 18px;
  background:var(--panel); border:1px solid rgba(57,212,200,0.18); border-radius:5px;
  transition:border-color 0.2s ease, transform 0.2s ease, background 0.2s ease; }
.sys-door:hover{ border-color:rgba(57,212,200,0.55); transform:translateY(-2px); background:#0e2129; }
.sd-label{ font-family:'Share Tech Mono',monospace; font-size:14.5px; letter-spacing:0.12em;
  text-transform:uppercase; color:var(--amber); flex-shrink:0; }
.sd-sub{ font-family:'Barlow',sans-serif; font-size:14px; color:var(--text-dim); flex:1; min-width:0; }
.sys-door .cm-arrow{ width:15px; height:15px; color:var(--steel-lt); flex-shrink:0; }
.sys-door:hover .cm-arrow{ color:var(--amber); transform:translateX(3px); }

.sys-cols{ display:grid; grid-template-columns:repeat(auto-fit,minmax(300px,1fr)); gap:16px;
  align-items:start; }
.sys-record{ display:flex; align-items:baseline; flex-wrap:wrap; gap:10px; margin:0; }
.sys-tag{ font-family:'Share Tech Mono',monospace; font-size:11px; letter-spacing:0.12em;
  color:var(--amber-dim); border:1px solid rgba(57,212,200,0.35); border-radius:3px; padding:2px 6px; }
.sys-record a{ font-family:'Oswald',sans-serif; font-weight:600; font-size:17.5px;
  color:var(--text); text-decoration:none; }
.sys-record a:hover{ color:var(--amber); }
.sys-date{ font-family:'Share Tech Mono',monospace; font-size:12px; color:var(--steel-lt); }
.sys-sum{ font-size:15.5px; color:var(--text-dim); line-height:1.8; margin:10px 0 0; }
.sys-more{ margin:12px 0 0; font-family:'Share Tech Mono',monospace; font-size:12px;
  letter-spacing:0.09em; text-transform:uppercase; }

.sys-footer{ display:flex; flex-direction:column; align-items:center; gap:10px; }
.sys-sig{ font-family:'Share Tech Mono',monospace; font-size:10.5px; letter-spacing:0.18em;
  color:var(--steel-lt); text-align:center; }

/* ---- loose ends ---- */
.thread-grid{ display:grid; grid-template-columns:repeat(auto-fill,minmax(330px,1fr)); gap:14px; }
.thread-card{ background:var(--panel); border:1px solid rgba(74,85,104,0.35); border-radius:6px;
  padding:18px 20px; border-left:2px solid var(--amber); }
.thread-card.resolved{ border-left-color:var(--steel-lt); opacity:0.72; }
.thread-card h3{ font-family:'Oswald',sans-serif; font-weight:600; font-size:18px;
  color:var(--text); margin:0 0 8px; }
.th-meta{ display:flex; flex-wrap:wrap; align-items:center; gap:10px; margin:0 0 10px; }
.th-state{ font-family:'Share Tech Mono',monospace; font-size:10.5px; letter-spacing:0.12em;
  text-transform:uppercase; padding:2px 7px; border-radius:3px; border:1px solid currentColor; }
.th-open{ color:var(--amber); }
.th-resolved{ color:var(--steel-lt); }
.th-src{ font-family:'Share Tech Mono',monospace; font-size:11.5px; color:var(--steel-lt);
  text-decoration:none; }
.th-src:hover{ color:var(--amber); text-decoration:underline; }
.thread-card .th-body{ font-size:16px; color:var(--text-dim); line-height:1.8; margin:0; }
.th-res{ font-size:15.5px; color:var(--text); line-height:1.6; margin:12px 0 0;
  padding-left:12px; border-left:1px solid rgba(57,212,200,0.4); }
.th-about{ display:flex; flex-wrap:wrap; gap:5px; margin:14px 0 0; }
.th-about .dir-chip{ text-decoration:none; }
.th-about .dir-chip:hover{ border-color:var(--amber); color:var(--amber); }

/* the compact list used on entry pages and the terminal */
.thread-mini{ list-style:none; margin:0; padding:0; }
.thread-mini li{ display:flex; align-items:baseline; gap:10px; padding:8px 0;
  border-bottom:1px solid rgba(74,85,104,0.2); }
.thread-mini li:last-child{ border-bottom:none; }
.thread-mini a{ flex:1; min-width:0; color:var(--text); text-decoration:none; font-size:16px; }
.thread-mini a:hover{ color:var(--amber); }
.th-raised{ font-family:'Share Tech Mono',monospace; font-size:11px; color:var(--steel-lt);
  flex-shrink:0; }

/* ---- crew index ---- */
.crew-index-card{ display:flex; gap:15px; align-items:flex-start; }
.cm-av-lg{ width:64px; height:64px; }
.ci-meta{ flex:1; min-width:0; }
.ci-seen{ font-family:'Share Tech Mono',monospace; font-size:11px; letter-spacing:0.07em;
  text-transform:uppercase; color:var(--steel-lt); margin:10px 0 0; }

@media (prefers-reduced-motion: reduce){
  .boot-line{ animation:none !important; opacity:1 !important; }
  .sys-door, .sys-stat{ transition:none !important; }
}

/* the blinking cursor assets/ancor.js appends while the readout runs */
.boot-cursor{ display:inline-block; font-family:'Share Tech Mono',monospace; color:var(--amber);
  animation:bootBlink 1s steps(1) infinite; }
@keyframes bootBlink{ 50%{ opacity:0; } }
.sys-boot.booted .boot-cursor{ display:none; }

/* The archive carries six sections in monospace where the campaign carries
   four, so it needs its own, wider breakpoint. 1039, down from 1119: the row
   needs 1018px of layout width in the worst case the caps allow, and the
   media query is matched against a viewport that still includes the ~15px
   scrollbar -- hence 1033 plus a little headroom, not 1018.

   Below this it goes to the drawer rather than crowding the row into the
   search button. The drawer carries every section and the crew list. */
@media (max-width:1039px){
  [data-system="ancor"] .nav-links{ display:none; }
  [data-system="ancor"] .nav-menu-btn{ display:inline-flex; }
  [data-system="ancor"] .nav-search-hint{ display:none; }
  [data-system="ancor"] .site-nav.drawer-open .nav-drawer{ display:flex; }
  [data-system="ancor"] .nav-drawer .nav-link{ padding:11px 4px; }
}

/* =========================================================================
   A.N.C.O.R. — console motion. Everything below is decoration over content
   that is already server-rendered and readable; assets/ancor.js performs it,
   and prefers-reduced-motion turns the whole lot off.
   ========================================================================= */

/* A refresh line crawling down the system, slow enough to notice only once. */
.sys-scan{ position:fixed; inset:0; pointer-events:none; z-index:2; overflow:hidden; }
.sys-scan::after{ content:''; position:absolute; left:0; right:0; height:180px;
  background:linear-gradient(180deg, transparent, rgba(57,212,200,0.055), transparent);
  animation:sysSweep 7.5s linear infinite; }
@keyframes sysSweep{ from{ transform:translateY(-190px); } to{ transform:translateY(100vh); } }

/* The readout: a solid block cursor that walks the line as it types. */
.sys-boot{ position:relative; overflow:hidden; }
.sys-boot::after{ content:''; position:absolute; inset:0; pointer-events:none;
  background:linear-gradient(180deg, rgba(57,212,200,0.07), transparent 60%); }
.boot-line{ min-height:1.35em; }
.boot-cursor{ display:inline-block; width:0.62em; margin-left:1px;
  color:var(--amber); animation:bootBlink 0.9s steps(1) infinite; }
.boot-line.typing .boot-cursor{ animation:none; opacity:1; }
.sys-boot.booted .boot-cursor{ display:none; }

/* The border breathes, so the panel never reads as a static box. */
.sys-boot{ animation:sysPulse 4.2s ease-in-out infinite; }
@keyframes sysPulse{
  0%,100%{ border-color:rgba(57,212,200,0.22); box-shadow:none; }
  50%{ border-color:rgba(57,212,200,0.42); box-shadow:0 0 26px -12px rgba(57,212,200,0.55); }
}

/* Counters land rather than stop: a faint glow while they roll. */
.sys-n{ transition:text-shadow 0.4s ease; }
.sys-stat:hover .sys-n{ text-shadow:0 0 22px rgba(57,212,200,0.75); }

/* The wordmark keeps a phosphor shimmer after it resolves. */
.sys-head h1{ position:relative; }
.sys-head h1::after{ content:''; position:absolute; left:0; right:0; top:0; bottom:0;
  background:linear-gradient(90deg, transparent, rgba(57,212,200,0.14), transparent);
  background-size:220% 100%; animation:sysShimmer 6s ease-in-out infinite;
  pointer-events:none; mix-blend-mode:screen; }
@keyframes sysShimmer{ 0%,100%{ background-position:220% 0; } 50%{ background-position:-120% 0; } }

/* A door being read: a line runs the width of it on hover. */
.sys-door{ position:relative; overflow:hidden; }
.sys-door::after{ content:''; position:absolute; left:0; bottom:0; height:1px; width:100%;
  background:linear-gradient(90deg, transparent, var(--amber), transparent);
  transform:translateX(-100%); transition:transform 0.55s cubic-bezier(.22,1,.36,1); }
.sys-door:hover::after{ transform:translateX(100%); }

@media (prefers-reduced-motion: reduce){
  .sys-scan{ display:none; }
  .sys-boot, .sys-boot::after, .sys-head h1::after, .boot-cursor{ animation:none !important; }
  .sys-head h1::after{ display:none; }
  .sys-door::after{ transition:none !important; }
}

/* "talked about, never on screen" — the presence split, said out loud. */
.ref-sub.ref-off{ color:var(--steel-lt); font-style:italic; }

/* ---- reader-contributed images -------------------------------------------
   Every tile is the same box no matter what was uploaded into it: one aspect
   ratio, cover-cropped, captions on a scrim INSIDE the frame rather than
   below it. That is what keeps a record with nine photographs and a record
   with one looking like the same site. A record with none renders no card at
   all, so there is never an empty frame to explain.
   Colours come from the theme tokens, so this block is amber on Hard Times
   and teal inside A.N.C.O.R. without a second ruleset. */

.gal-card h3{ display:flex; align-items:baseline; gap:12px; flex-wrap:wrap; }
.gal-card h3 .ref-sub{ font-family:'Share Tech Mono',monospace; font-size:12.5px;
  letter-spacing:0.08em; color:var(--text-dim); text-transform:none; }

.gal-hint{ font-family:'Share Tech Mono',monospace; font-size:12px; line-height:1.65;
  color:var(--text-dim); margin:-6px 0 14px; }
.gal-hint b{ color:var(--amber); font-weight:400; }

.gal-grid{ display:grid; gap:10px; margin:0 0 4px;
  grid-template-columns:repeat(auto-fill, minmax(152px, 1fr)); }

.gal-tile{ position:relative; margin:0; aspect-ratio:4/3; overflow:hidden;
  border-radius:5px; border:1px solid rgba(74,85,104,0.4); background:var(--void-2); }
.gal-tile img{ width:100%; height:100%; object-fit:cover; display:block;
  transition:transform 0.35s ease; }
.gal-tile:hover img{ transform:scale(1.04); }
.gal-tile.is-cover{ border-color:color-mix(in srgb, var(--amber) 55%, transparent); }
.gal-open{ display:block; width:100%; height:100%; }
.gal-open:focus-visible{ outline:2px solid var(--amber); outline-offset:-2px; }

.gal-tile figcaption{ position:absolute; left:0; right:0; bottom:0; padding:22px 10px 8px;
  display:flex; flex-direction:column; gap:1px; pointer-events:none;
  background:linear-gradient(180deg, transparent, rgba(3,6,10,0.88)); }
.gal-cap{ font-size:12.5px; line-height:1.35; color:#e6eaf0;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.gal-by{ font-family:'Share Tech Mono',monospace; font-size:10.5px; letter-spacing:0.07em;
  text-transform:uppercase; color:var(--amber); opacity:0.9; }

.gal-badge{ position:absolute; top:7px; left:7px; padding:2px 7px; border-radius:3px;
  font-family:'Share Tech Mono',monospace; font-size:9.5px; letter-spacing:0.11em;
  text-transform:uppercase; color:var(--void); background:var(--amber); }

/* Management sits out of the way until you ask for it, but never behind a
   hover alone -- keyboard users get it on focus-within too. */
.gal-acts{ position:absolute; top:6px; right:6px; display:flex; gap:5px;
  opacity:0; transition:opacity 0.18s ease; }
.gal-tile:hover .gal-acts, .gal-tile:focus-within .gal-acts{ opacity:1; }
.gal-act{ font-family:'Share Tech Mono',monospace; font-size:10px; letter-spacing:0.07em;
  text-transform:uppercase; cursor:pointer; padding:4px 7px; border-radius:3px;
  color:var(--text); background:rgba(5,7,12,0.86); border:1px solid rgba(74,85,104,0.7); }
.gal-act:hover{ border-color:var(--amber); color:var(--amber); }
.gal-act.gal-del:hover{ border-color:#e08a8a; color:#e08a8a; }
.gal-act[disabled]{ opacity:0.5; cursor:default; }
/* A phone has no hover, so hiding these behind one hides them for good --
   :focus-within only rescues somebody already tabbing through the grid. On a
   coarse pointer they are simply always there, and big enough to hit.
   AFTER the base .gal-act rules, not before: same specificity, so source
   order is the only thing deciding which size wins. */
@media (hover: none){
  .gal-acts{ opacity:1; }
  .gal-act{ font-size:11px; padding:8px 10px; }
}

/* ---- the uploader ---- */
.gal-add{ margin-top:16px; }
.gal-btn{ display:inline-flex; align-items:center; gap:8px; cursor:pointer;
  font-family:'Share Tech Mono',monospace; font-size:12.5px; letter-spacing:0.09em;
  text-transform:uppercase; padding:9px 15px; border-radius:4px;
  color:var(--amber); background:none; border:1px solid color-mix(in srgb, var(--amber) 45%, transparent);
  transition:background 0.2s ease, color 0.2s ease; }
.gal-btn:hover{ background:color-mix(in srgb, var(--amber) 12%, transparent); }
.gal-btn svg{ width:15px; height:15px; }
.gal-btn.gal-go{ background:var(--amber); color:var(--void); border-color:var(--amber); }
.gal-btn.gal-go:hover{ filter:brightness(1.1); }
.gal-btn[disabled]{ opacity:0.45; cursor:default; filter:none; }
.gal-btn.gal-cancel{ color:var(--text-dim); border-color:rgba(74,85,104,0.5); }

.gal-form{ display:flex; flex-direction:column; gap:14px; margin-top:4px;
  padding:18px; border-radius:5px; background:var(--void-2);
  border:1px solid rgba(74,85,104,0.4); }
.gal-form[hidden]{ display:none; }
.gal-file{ position:relative; display:block; }
.gal-file input{ position:absolute; inset:0; width:100%; height:100%; opacity:0; cursor:pointer; }
.gal-file span{ display:block; text-align:center; padding:22px 14px; border-radius:5px;
  font-family:'Share Tech Mono',monospace; font-size:13px; letter-spacing:0.08em;
  color:var(--text-dim); border:1px dashed rgba(74,85,104,0.7); }
.gal-file:hover span{ color:var(--amber); border-color:color-mix(in srgb, var(--amber) 50%, transparent); }
.gal-file input:focus-visible + span{ outline:2px solid var(--amber); outline-offset:2px; }

.gal-caption{ display:flex; flex-direction:column; gap:6px; }
.gal-caption > span{ font-family:'Share Tech Mono',monospace; font-size:11.5px;
  letter-spacing:0.08em; text-transform:uppercase; color:var(--text-dim); }
.gal-caption > span i{ font-style:normal; opacity:0.65; text-transform:none; }
.gal-caption input{ font-family:'Barlow',sans-serif; font-size:15px; color:var(--text);
  background:var(--panel); border:1px solid rgba(74,85,104,0.6); border-radius:4px; padding:9px 11px; }
.gal-caption input:focus{ outline:none; border-color:var(--amber); }

.gal-preview{ display:flex; flex-wrap:wrap; gap:8px; }
.gal-preview:empty{ display:none; }
.gal-preview img{ width:74px; height:74px; object-fit:cover; border-radius:4px;
  border:1px solid rgba(74,85,104,0.5); }

.gal-actions{ display:flex; gap:10px; flex-wrap:wrap; }
.gal-note{ font-family:'Share Tech Mono',monospace; font-size:11.5px; line-height:1.6;
  color:var(--text-dim); margin:0; }
.gal-note.is-bad{ color:#e08a8a; }

/* ---- lightbox ---- */
.gal-box{ position:fixed; inset:0; z-index:200; display:none;
  align-items:center; justify-content:center; padding:44px 60px;
  background:rgba(3,5,9,0.94); backdrop-filter:blur(3px); }
.gal-box.is-open{ display:flex; animation:galIn 0.18s ease; }
@keyframes galIn{ from{ opacity:0; } to{ opacity:1; } }
.gal-box.no-anim{ animation:none; }
.gal-box figure{ margin:0; display:flex; flex-direction:column; align-items:center; gap:14px;
  max-width:100%; max-height:100%; }
.gal-box img{ max-width:min(1100px, 92vw); max-height:80vh; object-fit:contain;
  border-radius:4px; border:1px solid rgba(74,85,104,0.5); }
.gal-box figcaption{ font-size:14.5px; color:var(--text-dim); text-align:center;
  max-width:60ch; }
.gal-box figcaption[hidden]{ display:none; }
.gb-close, .gb-nav{ position:absolute; cursor:pointer; color:var(--text);
  background:rgba(10,14,20,0.8); border:1px solid rgba(74,85,104,0.6); border-radius:4px;
  line-height:1; padding:0; }
.gb-close{ top:16px; right:18px; width:40px; height:40px; font-size:26px; }
.gb-nav{ top:50%; transform:translateY(-50%); width:42px; height:60px; font-size:30px; }
.gb-prev{ left:12px; }
.gb-next{ right:12px; }
.gb-nav[hidden]{ display:none; }
.gb-close:hover, .gb-nav:hover{ color:var(--amber); border-color:var(--amber); }
body.gal-locked{ overflow:hidden; }

/* ---- covers on directory cards ---- */
/* Absolutely placed and painted UNDER the stretched .dir-name link, so a
   click on the picture still opens the record it belongs to. */
.dir-card.has-thumb{ padding-right:96px; }
.dir-thumb{ position:absolute; top:16px; right:16px; width:64px; height:64px;
  border-radius:5px; overflow:hidden; border:1px solid rgba(74,85,104,0.5);
  background:var(--void-2); }
.dir-thumb img{ width:100%; height:100%; object-fit:cover; display:block; }
.dir-thumb-n{ position:absolute; top:74px; right:16px; width:64px; text-align:center;
  font-family:'Share Tech Mono',monospace; font-size:10px; letter-spacing:0.08em;
  color:var(--text-dim); }

@media (max-width:620px){
  .gal-grid{ grid-template-columns:repeat(auto-fill, minmax(120px, 1fr)); }
  .gal-box{ padding:56px 12px 24px; }
  .gb-nav{ width:36px; height:52px; font-size:24px; }
}

@media (prefers-reduced-motion: reduce){
  .gal-tile img, .gal-acts{ transition:none; }
  .gal-tile:hover img{ transform:none; }
  .gal-box.is-open{ animation:none; }
}

/* ---- the link preview, and the frame that sets it ------------------------
   A fixed 1200x630 window you move the picture behind, the way Discord sets a
   banner. The strip on the record page shows the live card at the real aspect
   so nobody has to post a link to find out what it kept. */

.gal-social{ display:flex; gap:18px; align-items:flex-start; flex-wrap:wrap;
  margin:0 0 18px; padding:16px; border-radius:5px; background:var(--void-2);
  border:1px solid rgba(74,85,104,0.4); }
.gal-social-frame{ flex:0 0 300px; max-width:100%; aspect-ratio:1200/630;
  border-radius:4px; overflow:hidden; border:1px solid rgba(74,85,104,0.55);
  background:var(--void); }
.gal-social-frame img{ width:100%; height:100%; object-fit:cover; display:block; }
.gal-social-side{ flex:1 1 220px; min-width:0; }
.gal-social-label{ font-family:'Oswald',sans-serif; font-weight:600; font-size:14.5px;
  letter-spacing:0.1em; text-transform:uppercase; color:var(--amber); margin:0 0 6px; }
.gal-social-sub{ font-size:14.5px; line-height:1.6; color:var(--text-dim); margin:0 0 14px; }
.gal-frame-btn svg{ width:16px; height:16px; }

.gal-crop{ position:fixed; inset:0; z-index:210; display:none;
  align-items:center; justify-content:center; padding:24px;
  background:rgba(3,5,9,0.94); backdrop-filter:blur(3px); }
.gal-crop.is-open{ display:flex; }
.gc-panel{ width:min(620px, 100%); max-height:100%; overflow:auto;
  background:var(--panel); border:1px solid rgba(74,85,104,0.5); border-radius:6px;
  padding:22px 24px; }
.gc-panel h4{ display:flex; align-items:baseline; gap:12px; margin:0 0 16px;
  font-family:'Oswald',sans-serif; font-weight:600; font-size:16.5px;
  letter-spacing:0.1em; text-transform:uppercase; color:var(--amber); }
.gc-panel h4 span{ font-family:'Share Tech Mono',monospace; font-size:11.5px;
  letter-spacing:0.09em; color:var(--text-dim); }

/* The window itself. overflow:hidden IS the crop -- what you can see is
   exactly what the canvas will later draw. */
.gc-frame{ position:relative; width:100%; aspect-ratio:1200/630; overflow:hidden;
  border-radius:4px; background:var(--void); cursor:grab; touch-action:none;
  border:1px solid rgba(74,85,104,0.6); }
.gc-frame.is-dragging{ cursor:grabbing; }
.gc-frame img{ position:absolute; left:0; top:0; transform-origin:0 0;
  max-width:none; user-select:none; -webkit-user-drag:none; pointer-events:none; }
/* Rule-of-thirds guides, so a face can be placed rather than guessed at. */
.gc-frame::after{ content:''; position:absolute; inset:0; pointer-events:none;
  background:
    linear-gradient(90deg, transparent 33.2%, rgba(255,255,255,0.16) 33.2%, rgba(255,255,255,0.16) 33.5%, transparent 33.5%,
      transparent 66.4%, rgba(255,255,255,0.16) 66.4%, rgba(255,255,255,0.16) 66.7%, transparent 66.7%),
    linear-gradient(180deg, transparent 33.2%, rgba(255,255,255,0.16) 33.2%, rgba(255,255,255,0.16) 33.5%, transparent 33.5%,
      transparent 66.4%, rgba(255,255,255,0.16) 66.4%, rgba(255,255,255,0.16) 66.7%, transparent 66.7%); }

.gc-zoom{ display:flex; align-items:center; gap:14px; margin:16px 0 4px; }
.gc-zoom span{ font-family:'Share Tech Mono',monospace; font-size:11.5px;
  letter-spacing:0.09em; text-transform:uppercase; color:var(--text-dim); }
.gc-zoom input{ flex:1; accent-color:var(--amber); }
.gc-note{ font-family:'Share Tech Mono',monospace; font-size:11.5px; line-height:1.65;
  color:var(--text-dim); margin:10px 0 18px; }
.gc-note.is-bad{ color:#e08a8a; }
.gc-acts{ display:flex; gap:10px; flex-wrap:wrap; }

@media (max-width:620px){
  .gal-social{ gap:14px; padding:14px; }
  .gal-social-frame{ flex-basis:100%; }
  .gal-crop{ padding:12px; }
  .gc-panel{ padding:18px 16px; }
}

/* ---- a record's face beside every mention of it --------------------------
   Small on purpose. These sit next to names in connection lists, backlinks,
   chips and nested-place lists, and the job is recognition, not display: the
   text has to stay the thing you read. A record with no image renders no
   circle at all, so a list never turns into a row of empty holes. */

.ref-av{ display:inline-block; width:26px; height:26px; flex:0 0 auto;
  border-radius:50%; overflow:hidden; vertical-align:middle; align-self:center;
  background:var(--void-blue); border:1px solid rgba(74,85,104,0.5); }
.ref-av img{ width:100%; height:100%; object-fit:cover; display:block; }

/* .conn-head aligns on the baseline so the name and its bond chip sit level;
   a circle has no baseline worth aligning to, so it centres instead. */
.conn-head .ref-av{ width:30px; height:30px; }

.inside-list .ref-av,
.ref-list .ref-av{ width:22px; height:22px; margin-right:8px; }
.ref-list li > p:first-child{ display:flex; align-items:center; flex-wrap:wrap; gap:10px; }
.ref-list .ref-av{ margin-right:0; }
.inside-list li{ display:flex; align-items:center; gap:10px; }

/* Inside a chip the circle is barely more than a colour cue, which is all it
   needs to be at eleven-pixel type. */
.dir-chip{ display:inline-flex; align-items:center; gap:5px; }
.dir-chip .ref-av{ width:15px; height:15px; border-width:0;
  margin:1px -1px 1px -2px; }

/* Drag a file anywhere over the images card. */
.gal-card.is-dropping{ border-color:var(--amber); box-shadow:0 0 0 1px var(--amber) inset; }
.gal-card.is-dropping *{ pointer-events:none; }

@media (prefers-reduced-motion: reduce){
  .gal-card.is-dropping{ transition:none; }
}

/* ---- hover cards ---------------------------------------------------------
   A reference, previewed: the record's picture, what it is, and a sentence.
   Positioned in page coordinates by assets/hovercard.js, so it is absolute
   rather than fixed and stays put with the link it belongs to. */

.hcard{ position:absolute; z-index:180; display:none;
  border-radius:6px; overflow:hidden; background:var(--panel);
  border:1px solid rgba(74,85,104,0.6);
  box-shadow:0 18px 40px -12px rgba(0,0,0,0.75);
  pointer-events:auto; }
.hcard.is-open{ display:block; animation:hcIn 0.14s ease-out; }
.hcard.no-anim{ animation:none; }
@keyframes hcIn{ from{ opacity:0; transform:translateY(-3px); } to{ opacity:1; transform:none; } }

.hc-img{ aspect-ratio:1200/630; background:var(--void-blue);
  border-bottom:1px solid rgba(74,85,104,0.45); }
.hcard.no-img .hc-img{ display:none; }
.hc-img img{ width:100%; height:100%; object-fit:cover; display:block; }

.hc-body{ padding:12px 14px 14px; }
.hc-name{ font-family:'Oswald',sans-serif; font-weight:600; font-size:17px;
  color:var(--amber); margin:0 0 4px; line-height:1.25; }
.hc-meta{ font-family:'Share Tech Mono',monospace; font-size:11px; letter-spacing:0.08em;
  text-transform:uppercase; color:var(--text-dim); margin:0 0 8px; }
.hc-meta[hidden], .hc-sum[hidden]{ display:none; }
.hc-sum{ font-size:14.5px; line-height:1.6; color:var(--text-dim); margin:0; }

/* No card at all where there is no hover to intend -- a tap follows the link. */
@media (hover: none){ .hcard{ display:none !important; } }
@media (prefers-reduced-motion: reduce){ .hcard.is-open{ animation:none; } }

/* ==========================================================================
   CONSOLE MOTION
   The archive should feel like something running, not like a document. The
   rules below are the whole of that: a rain layer behind the page, records
   that print in rather than appear, and a caret on every section tag.
   Everything here is switchable — see the [data-motion="off"] block at the
   end, which is what the footer switch and prefers-reduced-motion both hit.
   ========================================================================== */

/* The falling glyphs, drawn by assets/matrix.js. Sits with the other
   background layers at z-index 0; every scrap of content is 1 or above. Its
   opacity is set by the script so it can fade in rather than snap on. */
.sys-rain{ position:fixed; inset:0; z-index:0; pointer-events:none;
  opacity:0; transition:opacity 0.8s ease; }

/* Records print in rather than appearing. Staggered by position so a page
   reads top-down, the way a terminal fills one. `backwards` holds the start
   state during the delay, or every card would flash at full opacity first. */
[data-system="ancor"] .panel-card,
[data-system="ancor"] .dir-group,
[data-system="ancor"] .wiki-hero,
[data-system="ancor"] .wiki-head{
  animation:sysPrint 0.4s cubic-bezier(.22,1,.36,1) backwards; }
@keyframes sysPrint{ from{ opacity:0; transform:translateY(10px); } to{ opacity:1; transform:none; } }
[data-system="ancor"] .wiki-head{ animation-delay:0.02s; }
[data-system="ancor"] .panel-card:nth-of-type(1){ animation-delay:0.06s; }
[data-system="ancor"] .panel-card:nth-of-type(2){ animation-delay:0.12s; }
[data-system="ancor"] .panel-card:nth-of-type(3){ animation-delay:0.18s; }
[data-system="ancor"] .panel-card:nth-of-type(4){ animation-delay:0.24s; }
[data-system="ancor"] .panel-card:nth-of-type(n+5){ animation-delay:0.3s; }
[data-system="ancor"] .dir-group:nth-of-type(1){ animation-delay:0.06s; }
[data-system="ancor"] .dir-group:nth-of-type(2){ animation-delay:0.14s; }
[data-system="ancor"] .dir-group:nth-of-type(n+3){ animation-delay:0.22s; }

/* A caret after every section tag, blinking the way a prompt does. */
[data-system="ancor"] .sec-head .tag::after,
[data-system="ancor"] .panel-card > h3::after{
  content:'▊'; margin-left:0.4em; opacity:0.55;
  animation:sysCaret 1.15s steps(1,end) infinite; }
@keyframes sysCaret{ 50%{ opacity:0; } }

/* The heading being decoded by the script: monospaced-ish tracking while the
   glyphs churn, so the line does not reflow on every frame as it resolves. */
[data-system="ancor"] .wiki-title h1,
[data-system="ancor"] .sec-head h2{ font-variant-ligatures:none; }

/* The reader's switch, in the archive footer. */
.sys-motion{ font-family:'Share Tech Mono',monospace; font-size:11px; letter-spacing:0.14em;
  cursor:pointer; padding:5px 10px; border-radius:3px; margin-left:14px;
  color:var(--text-dim); background:none; border:1px solid rgba(74,85,104,0.5); }
.sys-motion:hover{ color:var(--amber); border-color:color-mix(in srgb, var(--amber) 50%, transparent); }
.sys-motion[aria-pressed="true"]{ color:var(--amber-dim); }

/* ---- the switch ---------------------------------------------------------
   One place that turns the whole lot off, hit by the footer button and by
   prefers-reduced-motion alike. Animations are cancelled rather than sped up,
   and the rain is removed from the page instead of merely made transparent —
   a canvas repainting invisibly is still a canvas repainting. */
[data-motion="off"] .sys-rain{ display:none; }
[data-motion="off"] .sys-scan{ display:none; }
[data-motion="off"] *,
[data-motion="off"] *::before,
[data-motion="off"] *::after{
  animation:none !important;
  transition-duration:0.01ms !important;
  scroll-behavior:auto !important; }
/* The caret is a character, not motion: keep it, stop the blink. */
[data-motion="off"] [data-system="ancor"] .sec-head .tag::after{ opacity:0.55; }

@media (prefers-reduced-motion: reduce){
  .sys-rain{ display:none; }
  [data-system="ancor"] .panel-card,
  [data-system="ancor"] .dir-group,
  [data-system="ancor"] .wiki-hero,
  [data-system="ancor"] .wiki-head{ animation:none; }
  [data-system="ancor"] .sec-head .tag::after,
  [data-system="ancor"] .panel-card > h3::after{ animation:none; }
}

/* ---- the campaign registry panel ----------------------------------------
   God only. Each row is one archive inside A.N.C.O.R.; the form below both
   creates and edits, so there is one set of fields rather than two. */

.camp-intro{ font-size:16px; line-height:1.7; color:var(--text-dim); max-width:66ch; margin:0 0 22px; }
.camp-form{ margin-top:22px; }
.camp-form textarea{ font-family:'Share Tech Mono',monospace; font-size:13.5px; }
.camp-dot{ display:inline-block; width:10px; height:10px; border-radius:50%;
  margin-right:9px; vertical-align:baseline; }

/* The colour wells sit in a row and label themselves. */
.camp-look{ display:flex; flex-wrap:wrap; gap:18px; align-items:flex-end; margin:16px 0 4px; }
.camp-look > label{ display:flex; flex-direction:column; gap:7px;
  font-family:'Share Tech Mono',monospace; font-size:11.5px; letter-spacing:0.1em;
  text-transform:uppercase; color:var(--text-dim); }
.camp-look input[type=color]{ width:56px; height:32px; padding:0; cursor:pointer;
  background:none; border:1px solid rgba(74,85,104,0.6); border-radius:4px; }
.camp-look select{ min-width:150px; }

.camp-actions{ display:flex; align-items:center; gap:12px; flex-wrap:wrap; margin-top:18px; }
.camp-msg{ font-family:'Share Tech Mono',monospace; font-size:12px; color:var(--text-dim); }
.camp-msg.is-bad{ color:#e08a8a; }

/* ---- the campaign portal and the switcher --------------------------------
   A.N.C.O.R. holds one archive per campaign. The portal is its front door
   when there is more than one; the switcher in the nav is how you cross
   between them once you are inside. With a single campaign neither appears —
   there is no choice to present. */

.camp-doors{ margin-top:8px; }
.camp-door{ position:relative; }
/* Each door wears its campaign's accent rather than the archive's, so the
   choice is colour-coded before you read a word of it. */
.camp-door::before{ content:''; position:absolute; left:0; top:0; bottom:0; width:3px;
  background:var(--camp, var(--amber)); border-radius:6px 0 0 6px; }
.camp-door:hover{ border-color:color-mix(in srgb, var(--camp, var(--amber)) 55%, transparent); }
.camp-door .sd-label{ color:var(--camp, var(--amber)); }
.camp-sys{ font-family:'Share Tech Mono',monospace; font-size:10.5px; letter-spacing:0.12em;
  text-transform:uppercase; color:var(--text-dim); margin-top:8px; display:block; }

.nav-camp-link{ display:inline-flex; align-items:center; gap:6px; }
.nav-pop-camp{ min-width:280px; }
.nav-pop-camp .cm-grid{ grid-template-columns:1fr; gap:4px; }
.camp-card{ display:flex; align-items:center; gap:11px; }
.camp-card.is-here{ background:color-mix(in srgb, var(--amber) 10%, transparent); }
.camp-card .camp-dot{ width:12px; height:12px; flex:0 0 auto; }
.camp-card .cm-meta{ min-width:0; }

/* The intake report: what a bundle did, or would do. */
.in-force{ display:flex; align-items:center; gap:9px; font-family:'Share Tech Mono',monospace;
  font-size:12px; letter-spacing:0.08em; text-transform:uppercase; color:var(--text-dim); margin-top:14px; }
.intake-report{ margin-top:20px; padding:16px 18px; border-radius:5px;
  background:var(--void-2); border:1px solid rgba(74,85,104,0.4); }
.ir-verdict{ font-family:'Oswald',sans-serif; font-weight:600; font-size:15px; letter-spacing:0.08em;
  text-transform:uppercase; color:var(--amber); margin:0 0 12px; }
.ir-verdict.is-bad{ color:#e08a8a; }
.ir-head{ font-family:'Share Tech Mono',monospace; font-size:11px; letter-spacing:0.12em;
  text-transform:uppercase; color:var(--text-dim); margin:14px 0 6px; }
.ir-head.is-bad{ color:#e08a8a; }
.ir-list{ margin:0; padding-left:20px; font-size:14.5px; line-height:1.7; color:var(--text-dim); }

/* The archive menu on a campaign page: a plain list, not the crew grid. */
.nav-pop-arch{ min-width:300px; }
.nav-pop-arch .cm-grid{ grid-template-columns:1fr; gap:3px; }
.arch-card{ display:flex; align-items:center; gap:10px; }
.arch-card .cm-meta{ flex:1; min-width:0; }

/* =========================================================================
   THE ACCOUNT MENU — admin, A.N.C.O.R., campaign, you.

   One control at the right end of the bar holding everything that is about
   the reader rather than about the record they are reading. Markup comes from
   accountMenu()/acctMenuBody() in src/render.js; the open/close behaviour is
   the same .nav-item machinery every other menu in the bar already uses, so
   there is no second implementation of a dropdown here.
   ========================================================================= */

.nav-acct{ flex-shrink:0; }
.nav-acct-link{ gap:7px; cursor:pointer; }
.nav-acct-name{ max-width:15ch; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.nav-acct .nav-chev{ opacity:0.6; }
.nav-acct.open > .nav-acct-link{ opacity:1; }

/* Narrower than the crew grid: these are one-line destinations, not
   portraits. The panel hangs off the right end of the bar, where there is
   nothing to centre it under -- nav.js's viewport clamp does the aligning. */
.nav-pop-acct .nav-pop-card{ width:min(330px, calc(100vw - 28px)); min-width:0; }
/* Anchored in CSS rather than by nav.js's viewport clamp, which only runs on
   open: a centred panel at the right end of the bar overhangs the viewport
   from the moment the page loads, and an overhang is horizontal scroll. */
.nav-pop[data-align="right"]{ left:auto; right:0; transform:none; }
.nav-pop[data-align="right"] > .nav-pop-card{ transform-origin:top right; }

/* A rung with nothing in it is never rendered at all (see acctGroup), so a
   divider can be unconditional: there is no empty group for it to sit under. */
.acct-group + .acct-group{ border-top:1px solid rgba(74,85,104,0.28); }
.acct-head{ font-family:'Share Tech Mono',monospace; font-size:10.5px; letter-spacing:0.16em;
  text-transform:uppercase; color:var(--steel-lt); margin:0; padding:11px 17px 3px; }
.acct-row{ width:100%; text-align:left; background:none; border:none; cursor:pointer;
  font:inherit; color:inherit; }
.acct-out .cm-name{ color:var(--amber); }

/* The motion switch is the one row that is a control rather than a
   destination, so it carries a readout instead of an arrow. It is written
   hidden and revealed by nav.js -- nothing here works without JS. */
.acct-motion{ justify-content:space-between; }
.acct-motion[hidden]{ display:none; }
.acct-motion[aria-pressed="true"] .cm-role{ color:var(--amber-dim); }

/* Below the bar's breakpoint the sections move into the drawer, and the
   account rungs go with them -- the trigger stays in the bar, but a panel
   hanging off it has nowhere to go on a phone. */
.drawer-acct{ margin-top:10px; padding-top:4px; border-top:1px solid rgba(74,85,104,0.3); }
.drawer-acct .acct-head{ padding-left:4px; padding-right:4px; }
.drawer-acct .cm-grid{ padding:0; }
.drawer-acct .acct-group + .acct-group{ margin-top:6px; }

/* Campaign names come out of the registry in whatever case somebody typed
   them; the wordmark and its sub-label have always been upper. */
.nav-mark, .nav-sub{ text-transform:uppercase; }

/* The sub-label is a campaign name out of the registry, so its length is
   whatever somebody typed. Capped so the bar has a bounded width and the
   breakpoints below can be a measurement rather than a guess. */
.nav-brand-sys{ min-width:0; }
.nav-sub{ max-width:16ch; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
/* Same reason, one level up: on a campaign's own pages the wordmark IS the
   campaign name, so it is user input too. */
.nav-mark{ display:inline-block; max-width:22ch; overflow:hidden; text-overflow:ellipsis;
  white-space:nowrap; vertical-align:bottom; }

/* =========================================================================
   THE FRONT PAGE — one block per campaign, not one door per campaign.
   Markup from systemHome() in src/render.js, built off the shelf that
   homeShelf() in src/worker.js gathers.

   Every picture here is optional and nothing collapses without one: a
   campaign with no uploads renders the same block with no strip, and the
   crew fall back to an initial. Same rule as the reference avatars — the
   decoration is always subordinate to the text.
   ========================================================================= */

.home-camps{ display:grid; gap:18px; margin-top:8px; }

.home-camp{ position:relative; min-width:0; padding:22px 24px 20px; border-radius:8px;
  background:linear-gradient(180deg, #0d1620, var(--panel));
  border:1px solid rgba(74,85,104,0.4); overflow:hidden;
  transition:border-color 0.2s ease; }
/* Each campaign wears its own accent rather than the archive's, so the block
   is colour-coded before you read a word of it. */
.home-camp::before{ content:''; position:absolute; left:0; top:0; bottom:0; width:3px;
  background:var(--camp, var(--amber)); }
.home-camp:hover{ border-color:color-mix(in srgb, var(--camp, var(--amber)) 45%, transparent); }

.hc-head{ display:flex; align-items:center; gap:12px; text-decoration:none; }
.hc-name{ font-family:'Big Shoulders Stencil',sans-serif; font-weight:800; font-size:30px;
  letter-spacing:0.04em; text-transform:uppercase; color:var(--camp, var(--amber)); line-height:1.1; }
.hc-sys{ font-family:'Share Tech Mono',monospace; font-size:11px; letter-spacing:0.14em;
  text-transform:uppercase; color:var(--text-dim); }
.hc-head .cm-arrow{ width:16px; height:16px; margin-left:auto; flex-shrink:0; color:var(--steel-lt);
  transition:transform 0.2s ease, color 0.2s ease; }
.hc-head:hover .cm-arrow{ color:var(--camp, var(--amber)); transform:translateX(4px); }
.hc-tag{ margin:7px 0 0; color:var(--text-dim); font-size:15.5px; line-height:1.6; }

/* The uploads. A reel rather than a grid: a campaign with twenty pictures
   must not push its own crew off the bottom of the screen. It scrolls inside
   its own box — the page itself never scrolls sideways. */
.hc-strip{ display:flex; gap:10px; margin-top:16px; overflow-x:auto; padding-bottom:4px;
  scrollbar-width:thin; }
.hc-shot{ position:relative; flex:0 0 auto; width:186px; border-radius:6px; overflow:hidden;
  text-decoration:none; border:1px solid rgba(74,85,104,0.5);
  transition:border-color 0.2s ease, transform 0.2s cubic-bezier(.22,1,.36,1); }
.hc-shot img{ display:block; width:100%; height:98px; object-fit:cover; }
.hc-shot-cap{ display:block; padding:6px 9px 7px; background:rgba(3,6,10,0.72);
  font-family:'Share Tech Mono',monospace; font-size:10.5px; letter-spacing:0.06em;
  color:var(--text-dim); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.hc-shot:hover{ transform:translateY(-2px);
  border-color:color-mix(in srgb, var(--camp, var(--amber)) 60%, transparent); }
.hc-shot:hover .hc-shot-cap{ color:var(--text); }

/* The crew wrap rather than scroll: a roster is meant to be read whole. */
.hc-crew{ display:flex; flex-wrap:wrap; gap:8px; margin-top:16px; }
.hc-pc{ display:flex; align-items:center; gap:9px; text-decoration:none;
  padding:5px 13px 5px 5px; border-radius:99px; background:rgba(255,255,255,0.028);
  border:1px solid rgba(74,85,104,0.4);
  transition:border-color 0.18s ease, background 0.18s ease; }
.hc-pc:hover{ background:rgba(255,255,255,0.06);
  border-color:color-mix(in srgb, var(--camp, var(--amber)) 55%, transparent); }
.hc-pc .cm-av{ width:34px; height:34px; border-radius:50%; }
.hc-pc-name{ font-family:'Oswald',sans-serif; font-weight:500; font-size:14.5px;
  letter-spacing:0.04em; color:var(--text); }
.hc-pc-sub{ font-family:'Share Tech Mono',monospace; font-size:10.5px; color:var(--steel-lt);
  white-space:nowrap; }

.hc-facts{ display:flex; flex-wrap:wrap; align-items:center; gap:16px; margin-top:16px;
  padding-top:13px; border-top:1px solid rgba(74,85,104,0.28);
  font-family:'Share Tech Mono',monospace; font-size:11.5px; letter-spacing:0.1em;
  text-transform:uppercase; color:var(--steel-lt); }
.hc-fact b{ color:var(--text); font-weight:400; }
.hc-latest{ margin-left:auto; min-width:0; color:var(--text-dim); text-decoration:none;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.hc-latest:hover{ color:var(--camp, var(--amber)); }

@media (max-width:620px){
  .home-camp{ padding:18px 16px 16px; }
  .hc-name{ font-size:25px; }
  .hc-latest{ margin-left:0; }
}
@media (prefers-reduced-motion: reduce){
  .hc-shot, .hc-pc, .home-camp, .hc-head .cm-arrow{ transition:none !important; }
}

/* ---- naming a Dungeon Master ---------------------------------------------
   In the accounts list, because that is the only place the people have names;
   the campaign form edits the same gms[] as raw Discord ids. Markup from
   dmPicker() in assets/admin.js. God only — the endpoint refuses anybody
   else, and a hidden control is a convenience, never the lock. */

.acct-dm{ display:flex; flex-wrap:wrap; align-items:center; gap:7px; margin-top:6px; }
.dm-lead{ color:var(--steel-lt); }
.dm-pick{ display:inline-flex; align-items:center; gap:7px; cursor:pointer;
  padding:4px 11px 4px 8px; border-radius:99px;
  border:1px solid rgba(74,85,104,0.45); background:rgba(255,255,255,0.025);
  font-family:'Share Tech Mono',monospace; font-size:11.5px; letter-spacing:0.05em;
  color:var(--text-dim); transition:border-color 0.18s ease, color 0.18s ease, background 0.18s ease; }
.dm-pick:hover{ color:var(--text); border-color:rgba(255,176,32,0.45); }
/* Checked reads as a badge rather than a form control: at a glance the row
   should say "this person runs that game", not "this box is ticked". */
.dm-pick.is-on{ color:var(--text); border-color:color-mix(in srgb, var(--amber) 55%, transparent);
  background:color-mix(in srgb, var(--amber) 12%, transparent); }
.dm-pick input{ width:13px; height:13px; margin:0; cursor:pointer; accent-color:var(--amber); }
.dm-pick input:disabled{ cursor:progress; opacity:0.5; }
.dm-pick .camp-dot{ width:8px; height:8px; border-radius:50%; flex:0 0 auto; }

.camp-runby{ margin:14px 0 0; font-family:'Share Tech Mono',monospace; font-size:12px;
  letter-spacing:0.06em; color:var(--text-dim); }
.camp-runby b{ color:var(--text); font-weight:400; }
.camp-runby a{ color:var(--amber); }

@media (prefers-reduced-motion: reduce){ .dm-pick{ transition:none !important; } }

/* The audit row's three spans had no rules at all, so an entry read as one
   run-on string: "8/31/2026, 9:51:11 AMdarthchurchillcampaign created". */
.audit-row{ display:flex; flex-wrap:wrap; gap:4px 16px; align-items:baseline; }
.au-when{ color:var(--steel-lt); white-space:nowrap; }
.au-who{ color:var(--text); }
.au-what{ flex:1; min-width:0; }

/* ---- the Dungeon Master credit ------------------------------------------
   On the crew roster and on each front-page campaign block. The table is the
   players AND the person running it, so it reads as part of the roster rather
   than as a footnote under it. Never rendered empty — see crewIndexPage. */
.dm-credit{ display:flex; align-items:baseline; gap:12px; flex-wrap:wrap;
  margin:22px 0 0; padding-top:16px; border-top:1px solid rgba(74,85,104,0.28); }
.dmc-role{ font-family:'Share Tech Mono',monospace; font-size:11px; letter-spacing:0.16em;
  text-transform:uppercase; color:var(--steel-lt); }
.dmc-name{ font-family:'Oswald',sans-serif; font-weight:600; font-size:17px;
  letter-spacing:0.05em; color:var(--amber); }
/* In a campaign block it wears that campaign's accent, like everything else
   in there, and sits tighter — it is one line among several, not a coda. */
.hc-dm{ margin-top:14px; padding-top:12px; }
.hc-dm .dmc-name{ font-size:15px; color:var(--camp, var(--amber)); }

/* =========================================================================
   FORM CONTROLS — one look, everywhere.

   The site had a good field and a good button, but only inside .entry-form:
   everything the admin panels grew later fell through to the browser. A
   submit rendered as a grey Arial OS button on a console-black page, selects
   kept their native chrome at a different height and font from the inputs
   above them, and checkboxes were system blue.

   So the treatment .entry-form already had is generalised here rather than
   invented: same dark inset field, same amber focus, same Oswald uppercase
   button. Anything below that re-states an existing rule is doing it to keep
   a deliberate exception working, and says which.

   Every control shares one geometry — 40px tall, 4px radius, 1px border — so
   a row of mixed controls lines up instead of stepping.
   ========================================================================= */

/* ---- the field ---- */
.entry-form input[type=text],
.entry-form input[type=search],
.entry-form input[type=number],
.entry-form textarea,
.entry-form select,
.camp-field input[type=text],
.camp-look select,
.acct-select{
  width:100%; max-width:100%; box-sizing:border-box;
  background:var(--void);
  border:1px solid rgba(74,85,104,0.55);
  border-radius:4px;
  color:var(--text);
  font-family:'Barlow',sans-serif; font-size:16px; line-height:1.4;
  padding:9px 12px; min-height:40px;
  transition:border-color 0.18s ease, box-shadow 0.18s ease, background 0.18s ease;
}
/* A select is a control, not prose: it never wraps and it needs room for the
   chevron drawn on its right. */
.entry-form select, .camp-look select, .acct-select{
  width:auto; min-width:170px; padding-right:34px;
  font-family:'Share Tech Mono',monospace; font-size:13.5px; letter-spacing:0.04em;
  appearance:none; -webkit-appearance:none; -moz-appearance:none;
  background-image:url("data:image/svg+xml;charset=UTF-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%238890a0' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
  background-repeat:no-repeat; background-position:right 11px center; background-size:13px;
  cursor:pointer;
}
.entry-form select:hover, .camp-look select:hover, .acct-select:hover{ border-color:rgba(255,176,32,0.45); }
/* The list itself is drawn by the OS, so its colours have to be set outright
   or a dark field drops open into white. */
.entry-form select option, .camp-look select option, .acct-select option{
  background:var(--void-2); color:var(--text);
}

.entry-form textarea{ min-height:96px; resize:vertical; display:block; }
/* Identifiers, JSON and snowflakes are read character by character. */
.camp-form textarea, #in-bundle{ font-family:'Share Tech Mono',monospace; font-size:13.5px; }

.entry-form input::placeholder, .entry-form textarea::placeholder,
.camp-field input::placeholder{ color:var(--steel-lt); opacity:1; }

.entry-form input[type=text]:hover, .entry-form textarea:hover,
.camp-field input[type=text]:hover{ border-color:rgba(74,85,104,0.85); }

/* Focus is the same amber the rest of the console uses to say "here", with a
   ring rather than a thicker border so nothing shifts by a pixel. */
.entry-form input[type=text]:focus, .entry-form input[type=search]:focus,
.entry-form input[type=number]:focus, .entry-form textarea:focus,
.entry-form select:focus, .camp-field input[type=text]:focus,
.camp-look select:focus, .acct-select:focus{
  outline:none; border-color:var(--amber);
  box-shadow:0 0 0 3px rgba(255,176,32,0.14), inset 0 0 12px -6px rgba(255,176,32,0.5);
  background:#070a10;
}

.entry-form input:disabled, .entry-form textarea:disabled, .entry-form select:disabled,
.acct-select:disabled{ opacity:0.45; cursor:not-allowed; }

/* Chrome paints its own near-white background over autofilled fields, which
   on a black page is a white slab. The inset shadow is the only way to cover
   it, so it is done deliberately rather than fought. */
.entry-form input:-webkit-autofill, .camp-field input:-webkit-autofill{
  -webkit-text-fill-color:var(--text);
  -webkit-box-shadow:0 0 0 60px var(--void) inset;
  caret-color:var(--text);
}

/* ---- labels and help ---- */
.entry-form label, .camp-field label{
  display:block; font-family:'Share Tech Mono',monospace; font-size:12.5px;
  letter-spacing:0.08em; text-transform:uppercase; color:var(--text-dim);
  margin:16px 0 6px;
}
.entry-form label:first-child{ margin-top:0; }
/* The parenthetical half of a label is guidance, not part of the name. */
.entry-form label i, .camp-field label i{
  font-style:normal; text-transform:none; letter-spacing:0.02em;
  color:var(--steel-lt); font-size:12px;
}
.camp-field{ margin-top:4px; max-width:420px; }
.camp-field label{ margin-top:0; }

/* ---- buttons ---- */
/* The .entry-form-actions treatment, promoted to the site's button. */
.btn, .entry-form-actions button{
  display:inline-flex; align-items:center; justify-content:center; gap:7px;
  font-family:'Oswald',sans-serif; font-weight:600; font-size:14.5px;
  letter-spacing:0.06em; text-transform:uppercase;
  padding:10px 18px; min-height:40px; border-radius:4px; border:1px solid transparent;
  background:var(--amber); color:#1a1305; cursor:pointer; white-space:nowrap;
  transition:filter 0.18s ease, box-shadow 0.2s ease, transform 0.12s ease;
}
.btn[hidden], .entry-form-actions button[hidden]{ display:none; }
.btn:hover, .entry-form-actions button:hover{
  filter:brightness(1.08); box-shadow:0 6px 20px -10px rgba(255,176,32,0.8);
}
.btn:active, .entry-form-actions button:active{ transform:translateY(1px); }
.btn svg, .entry-form-actions button svg{ flex-shrink:0; width:14px; height:14px; }
.btn:disabled{ opacity:0.45; cursor:not-allowed; filter:none; box-shadow:none; }

/* The second action in a pair: present, clearly not the one being offered. */
.btn-ghost, .entry-form-actions .btn-ghost{
  /* border, not border-color: the older .entry-form-actions rule sets
     border:none at the same specificity, so only restating the whole
     shorthand brings the outline back and makes ghosts match everywhere. */
  background:none; color:var(--text-dim); border:1px solid rgba(74,85,104,0.55);
}
.btn-ghost:hover, .entry-form-actions .btn-ghost:hover{
  filter:none; box-shadow:none; color:var(--text);
  border-color:rgba(255,176,32,0.5); background:rgba(255,176,32,0.06);
  text-decoration:none;
}

/* ---- checkbox ---- */
/* Drawn rather than native, because a system-blue tick is the one thing on
   these pages that belongs to somebody else's design. */
.entry-form input[type=checkbox], .dm-pick input[type=checkbox]{
  appearance:none; -webkit-appearance:none;
  width:16px; height:16px; flex:0 0 auto; margin:0; padding:0;
  border:1px solid rgba(74,85,104,0.8); border-radius:3px;
  background:var(--void); cursor:pointer; position:relative;
  transition:border-color 0.15s ease, background 0.15s ease;
}
.entry-form input[type=checkbox]:hover, .dm-pick input[type=checkbox]:hover{
  border-color:rgba(255,176,32,0.65);
}
.entry-form input[type=checkbox]:checked, .dm-pick input[type=checkbox]:checked{
  background:var(--amber); border-color:var(--amber);
}
.entry-form input[type=checkbox]:checked::after,
.dm-pick input[type=checkbox]:checked::after{
  content:''; position:absolute; left:4.5px; top:1px; width:4px; height:8px;
  border:solid #1a1305; border-width:0 2px 2px 0; transform:rotate(42deg);
}
.entry-form input[type=checkbox]:focus-visible,
.dm-pick input[type=checkbox]:focus-visible{
  outline:2px solid var(--amber); outline-offset:2px;
}
/* The faceted rail hides its input and draws the box on the label so the whole
   row is the hit target. It was here first and it is better; this keeps the
   rule above from reaching it. */
.facet-group input[type=checkbox]{
  position:absolute; opacity:0; width:0; height:0; appearance:none; border:none; background:none;
}

/* A checkbox and its words are one control, so they sit on one line. */
.in-force{ display:flex; align-items:center; gap:9px; }
.in-force input[type=checkbox]{ margin:0; }

/* ---- colour wells ---- */
/* Native swatches carry an inner border and their own padding, which reads as
   a control from another operating system. Strip both and let the wrapper be
   the frame. */
.camp-look input[type=color]{
  width:62px; height:40px; padding:0; border-radius:4px; cursor:pointer;
  border:1px solid rgba(74,85,104,0.55); background:var(--void);
  appearance:none; -webkit-appearance:none;
  transition:border-color 0.18s ease, box-shadow 0.18s ease;
}
.camp-look input[type=color]::-webkit-color-swatch-wrapper{ padding:3px; }
.camp-look input[type=color]::-webkit-color-swatch{ border:none; border-radius:2px; }
.camp-look input[type=color]::-moz-color-swatch{ border:none; border-radius:2px; }
.camp-look input[type=color]:hover{ border-color:rgba(255,176,32,0.5); }
.camp-look input[type=color]:focus-visible{
  outline:none; border-color:var(--amber); box-shadow:0 0 0 3px rgba(255,176,32,0.14);
}
.camp-look{ align-items:flex-end; }
.camp-look > label{ margin:0; }

/* ---- range ---- */
/* The crop editor's zoom. A native track is grey and 4px of another century. */
.gc-zoom input[type=range]{
  appearance:none; -webkit-appearance:none; height:18px; background:none; cursor:pointer;
}
.gc-zoom input[type=range]::-webkit-slider-runnable-track{
  height:3px; border-radius:2px; background:rgba(74,85,104,0.7);
}
.gc-zoom input[type=range]::-moz-range-track{
  height:3px; border-radius:2px; background:rgba(74,85,104,0.7);
}
.gc-zoom input[type=range]::-webkit-slider-thumb{
  appearance:none; -webkit-appearance:none; margin-top:-6px;
  width:15px; height:15px; border-radius:50%; background:var(--amber);
  border:none; box-shadow:0 0 10px -2px rgba(255,176,32,0.9);
}
.gc-zoom input[type=range]::-moz-range-thumb{
  width:15px; height:15px; border-radius:50%; background:var(--amber);
  border:none; box-shadow:0 0 10px -2px rgba(255,176,32,0.9);
}
.gc-zoom input[type=range]:focus-visible{ outline:2px solid var(--amber); outline-offset:4px; }

/* ---- the form as a whole ---- */
/* Admin forms are panels, not the amber-edged callout the log's add-entry box
   is -- they are the page's content rather than an interruption in it. */
.camp-form{ border-color:rgba(74,85,104,0.4); }
.camp-actions{ align-items:center; }

@media (prefers-reduced-motion: reduce){
  .btn, .entry-form-actions button,
  .entry-form input, .entry-form textarea, .entry-form select,
  .camp-field input, .acct-select, .camp-look input[type=color],
  .entry-form input[type=checkbox], .dm-pick input[type=checkbox]{
    transition:none !important;
  }
  .btn:active, .entry-form-actions button:active{ transform:none; }
}

/* The colour wells label themselves underneath, which the generic label rule
   above flattens — it sets display:block at the same specificity and wins on
   order. Restated here so the row keeps its columns. */
.camp-look > label{
  display:flex; flex-direction:column; gap:7px; margin:0;
  font-family:'Share Tech Mono',monospace; font-size:11.5px; letter-spacing:0.1em;
  text-transform:uppercase; color:var(--text-dim);
}
/* A well is a colour, and reads better as a broad chip than a small square. */
.camp-look input[type=color]{ width:74px; }

/* The label on a filled button, derived from the accent in themeStyle() —
   the default amber wants near-black, a crimson campaign wants white. */
.btn, .entry-form-actions button{ color:var(--on-accent, #1a1305); }
.btn-ghost, .entry-form-actions .btn-ghost{ color:var(--text-dim); }
.btn-ghost:hover, .entry-form-actions .btn-ghost:hover{ color:var(--text); }

/* Everything else that puts content directly ON the accent. Same reason as
   the button: the default amber is light and these were all written against
   it, but a campaign choosing a dark accent would otherwise be reading its
   own badges and ticks at about 3.7:1. The facet box has no mark inside it,
   so it is not in this list. */
::selection{ color:var(--on-accent, #1a1305); }
.gal-badge{ color:var(--on-accent, #1a1305); }
.gal-btn.gal-go{ color:var(--on-accent, #1a1305); }
.entry-form input[type=checkbox]:checked::after,
.dm-pick input[type=checkbox]:checked::after{ border-color:var(--on-accent, #1a1305); }

/* A <button> does not inherit the page's font, so any button without its own
   rule — the icon-only ones in the nav — was falling back to Arial. Harmless
   while they hold only an SVG, and wrong the moment one holds a word. */
button{ font-family:inherit; }
