/* jen zombie -- public site.
   Dark, mobile first, no imagery that is not the demo's own. The model thread
   is the widest, tallest thing on the page because it is the point. */

:root {
  --bg:      #0b0d10;
  --panel:   #12161c;
  --panel-2: #161b22;
  --line:    #1e242d;
  --fg:      #e8ecf1;
  --dim:     #8b96a5;   /* 6.5:1 on --bg */
  /* Was #5d6772, which is 3.4:1 -- under AA for the 11px timestamps and photo
     captions that use it. Raised until it clears 4.5:1 at any size. */
  --dimmer:  #79838f;   /* 5.0:1 on --bg */
  --ok:      #35d07f;
  --bad:     #ff5c5c;
  --warn:    #ffb020;
  --accent:  #4aa3ff;
  --gemini:  #a78bfa;
  --nemo:    #35d07f;
  --game:    #4aa3ff;
  --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
  --sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Inter, system-ui, sans-serif;
}

* { box-sizing: border-box; }

/* An author `display` beats the UA stylesheet's `[hidden] { display: none }`,
   whatever the specificity. So any element given `display: grid` below would
   silently ignore its own hidden attribute -- which is exactly what happened:
   `.lightbox` shipped as a permanent rgba(0,0,0,.92) sheet over the entire
   page, swallowing every click, and `.intro` never really hid either.
   Stated once, here, so it cannot happen again. */
[hidden] { display: none !important; }

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

body {
  margin: 0;
  background: var(--bg);
  color: var(--fg);
  font: 16px/1.55 var(--sans);
  padding: 0 16px env(safe-area-inset-bottom) 16px;
  overflow-wrap: break-word;
}

/* ------------------------------------------------------------- header -- */

header { max-width: 1100px; margin: 0 auto; padding: 26px 0 0; }
.brand h1 {
  font: 700 27px/1.1 var(--mono);
  margin: 0 0 8px;
  letter-spacing: -0.5px;
}
.brand p { margin: 0 0 18px; color: var(--dim); font-size: 15px; max-width: 62ch; }

.tabs { display: flex; gap: 8px; border-bottom: 1px solid var(--line); }
.tabs button {
  appearance: none; background: none; border: 0;
  border-bottom: 2px solid transparent;
  color: var(--dim); font: 700 13px/1 var(--mono); letter-spacing: 1.6px;
  padding: 12px 14px; cursor: pointer; margin-bottom: -1px;
}
.tabs button[aria-selected="true"] { color: var(--fg); border-bottom-color: var(--accent); }
.tabs button:hover { color: var(--fg); }
.tabs button:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }

main { max-width: 1100px; margin: 0 auto; padding: 20px 0 48px; }

/* ------------------------------------------------------------- banner -- */

.banner {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 12px 15px; border-radius: 11px;
  border: 1px solid var(--line); background: var(--panel);
  font: 700 14px/1.3 var(--mono); letter-spacing: 0.8px;
  margin-bottom: 18px;
}
.banner .dot { width: 9px; height: 9px; border-radius: 50%; background: var(--dimmer); flex: none; }
.banner .when { font-weight: 400; letter-spacing: 0; color: var(--dim); font-size: 13px; }

.banner.live     { border-color: rgba(53,208,127,.45); background: rgba(53,208,127,.10); color: var(--ok); }
.banner.live .dot{ background: var(--ok); animation: pulse 1.6s ease-in-out infinite; }
.banner.quiet    { border-color: rgba(255,176,32,.40); background: rgba(255,176,32,.09); color: var(--warn); }
.banner.quiet .dot { background: var(--warn); }
.banner.finished { border-color: rgba(255,255,255,.10); color: var(--dim); }
.banner.finished .dot { background: var(--dimmer); }
.banner.waiting  { color: var(--dim); }
.banner.error    { border-color: rgba(255,92,92,.40); background: rgba(255,92,92,.08); color: var(--bad); }
.banner.error .dot { background: var(--bad); }

@keyframes pulse { 0%,100% { opacity: 1; } 50% { opacity: .25; } }
@media (prefers-reduced-motion: reduce) { .banner.live .dot { animation: none; } }

/* Marking a finished session.
   Nothing on the page is dimmed or desaturated for this. Both opacity and
   saturate() degrade the data to carry a message ABOUT the data, and the data
   is the whole point. The state is stated instead: in words in the banner, and
   in the badge below, which is deliberately the loudest thing on the page.
   `.past` is left on <body> as a hook, but it must not make anything quieter. */

/* ------------------------------------------------------------- badge ----- */
/* Fixed, white on black text, always on top. Inverted against a dark page so
   it cannot be mistaken for content -- the one element here that is supposed
   to shout. 21:1 contrast. */
.recbadge {
  position: fixed;
  top: max(12px, env(safe-area-inset-top));
  right: max(12px, env(safe-area-inset-right));
  z-index: 60;
  display: flex; align-items: center; gap: 8px;
  background: #fff; color: #000;
  border-radius: 8px;
  padding: 7px 11px 7px 9px;
  font: 800 11.5px/1 var(--mono);
  letter-spacing: 1.3px;
  box-shadow: 0 2px 14px rgba(0, 0, 0, .55), 0 0 0 1px rgba(0, 0, 0, .35);
  white-space: nowrap;
  max-width: calc(100vw - 32px);
}
.recbadge .rec {
  width: 10px; height: 10px; border-radius: 50%;
  background: #000; flex: none;
}
.recbadge .when {
  font-weight: 500; letter-spacing: .2px; color: #3a3a3a;
  border-left: 1px solid rgba(0, 0, 0, .22); padding-left: 8px;
}

/* The record lamp is the only colour on the badge, so the state reads at a
   glance without relying on reading the word. */
.recbadge.live .rec     { background: #d40000; }
.recbadge.quiet .rec    { background: #c07000; }
.recbadge.finished .rec { background: #000; }
.recbadge.waiting .rec  { background: #6a6a6a; }
.recbadge.error .rec    { background: #d40000; }

/* A live session is the one case where motion earns its place: it is the
   difference between "this is happening now" and "this happened". Purely
   decorative -- the word LIVE is already there if it never animates. */
@media (prefers-reduced-motion: no-preference) {
  .recbadge.live .rec { animation: recpulse 1.4s ease-in-out infinite; }
}
@keyframes recpulse { 0%, 100% { opacity: 1; } 50% { opacity: .2; } }

@media (max-width: 460px) {
  .recbadge { font-size: 10.5px; padding: 6px 9px 6px 8px; gap: 6px; }
  .recbadge .when { display: none; }   /* the banner carries the timestamp */
}

/* ------------------------------------------------ the arrival disclaimer -- */
/* Says what you are looking at the moment you land, then flies to the corner
   and stays there as the badge.
   NO backdrop, NO scrim, nothing behind it is dimmed -- the overlay is a
   transparent, click-through layer holding a single card. */
.intro {
  position: fixed; inset: 0; z-index: 70;
  display: grid; place-items: center;
  padding: 20px;
  background: none;
  pointer-events: none;
}
.intro-card {
  pointer-events: auto;
  background: #fff; color: #000;
  border-radius: 13px;
  padding: 18px 20px;
  max-width: min(420px, calc(100vw - 40px));
  box-shadow: 0 18px 50px rgba(0, 0, 0, .6), 0 0 0 1px rgba(0, 0, 0, .3);
  transform-origin: top right;   /* it shrinks toward where it is going */
  cursor: pointer;
}
.intro-head {
  display: flex; align-items: center; gap: 9px;
  font: 800 15px/1 var(--mono); letter-spacing: 1.6px;
}
.intro-head .rec { width: 12px; height: 12px; border-radius: 50%; background: #000; flex: none; }
.intro-head span:last-child { margin-left: auto; font-weight: 500; letter-spacing: .2px; color: #3a3a3a; font-size: 12.5px; }
.intro-card p {
  margin: 10px 0 0;
  font: 400 13.5px/1.5 var(--sans);
  color: #23262b;
}
.intro-card .hint {
  display: block; margin-top: 9px;
  font: 500 11px/1 var(--mono); letter-spacing: 1px; color: #5b6069;
}

.intro.live     .intro-head .rec { background: #d40000; }
.intro.quiet    .intro-head .rec { background: #c07000; }
.intro.finished .intro-head .rec { background: #000; }
.intro.waiting  .intro-head .rec { background: #6a6a6a; }

/* The flight. The transform and opacity are set from JS against the badge's
   measured position, so it lands exactly on it at any viewport size. */
.intro-card.flying {
  transition: transform .72s cubic-bezier(.6, .02, .3, 1), opacity .72s ease-in;
  opacity: 0;
}
@media (prefers-reduced-motion: reduce) {
  .intro-card.flying { transition: opacity .2s linear; transform: none !important; }
}

/* The badge is invisible only while the card is standing in for it, and the
   resting state is plain visible -- so if the flight never runs, the badge is
   still there. */
.recbadge.handoff { opacity: 0; }

/* -------------------------------------------------------------- stats -- */

.stats {
  display: grid; gap: 10px; margin-bottom: 18px;
  grid-template-columns: repeat(2, minmax(0, 1fr));
}
@media (min-width: 620px) { .stats { grid-template-columns: repeat(4, minmax(0, 1fr)); } }

.stat {
  background: var(--panel); border: 1px solid var(--line);
  border-radius: 11px; padding: 12px 13px; min-width: 0;
}
.stat.wide { grid-column: span 2; }
.stat .label {
  display: block; font: 700 10.5px/1.3 var(--mono);
  letter-spacing: 1.4px; text-transform: uppercase; color: var(--dim);
  margin-bottom: 7px;
}
.stat .label i { font-style: normal; font-weight: 400; letter-spacing: .4px; text-transform: none; color: var(--dimmer); }
.stat b { display: block; font: 800 25px/1.1 var(--mono); letter-spacing: -0.5px; }
.stat .sub { display: block; margin-top: 4px; font: 400 12px/1.3 var(--mono); color: var(--dim); }
.stat b.hearts { letter-spacing: 1px; color: #e23b3b; }
.stat b.dead { color: var(--bad); }
.stat b.ok { color: var(--ok); }
.stat b.warn { color: var(--warn); }
.stat b.dim { color: var(--dim); }

.bar { height: 5px; border-radius: 3px; background: #0a0d11; border: 1px solid var(--line); margin-top: 9px; overflow: hidden; }
.bar i { display: block; height: 100%; width: 0; background: var(--accent); transition: width .25s linear; }
.bar i.hot { background: var(--bad); }
.bar i.warm { background: var(--warn); }
.bar i.ready { background: var(--ok); }

/* ---------------------------------------------------------- world now -- */

.worldnow {
  background: var(--panel); border: 1px solid var(--line);
  border-radius: 11px; padding: 13px 15px; margin-bottom: 22px;
}
.worldnow .label {
  display: block; font: 700 10.5px/1.3 var(--mono); letter-spacing: 1.4px;
  text-transform: uppercase; color: var(--dim); margin-bottom: 7px;
}
.worldnow b { font: 800 19px/1.25 var(--mono); }
.worldnow .biome {
  display: inline-block; margin-left: 9px; padding: 2px 8px; border-radius: 5px;
  font: 700 10.5px/1.6 var(--mono); letter-spacing: 1.2px;
  background: rgba(255,255,255,.06); color: var(--dim);
}
.worldnow p { margin: 8px 0 0; color: var(--dim); font-size: 14.5px; font-style: italic; }

/* ------------------------------------------------------------- thread -- */

.threadhead { margin: 30px 0 14px; }
.threadhead h2 { font: 700 15px/1.2 var(--mono); letter-spacing: 1.4px; text-transform: uppercase; margin: 0 0 8px; }
.threadhead p { margin: 0 0 12px; color: var(--dim); font-size: 14.5px; max-width: 66ch; }
.threadmeta { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.threadmeta span { font: 400 12.5px/1 var(--mono); color: var(--dim); }
.threadmeta button {
  appearance: none; background: var(--panel-2); border: 1px solid var(--line);
  color: var(--dim); border-radius: 7px; padding: 6px 11px;
  font: 400 12.5px/1 var(--mono); cursor: pointer;
}
.threadmeta button:hover { color: var(--fg); border-color: #2b3440; }

.thread { display: flex; flex-direction: column; gap: 14px; }

.leg {
  align-self: center; margin: 12px 0 2px; padding: 4px 12px;
  border-radius: 999px; background: var(--panel-2); border: 1px solid var(--line);
  font: 700 10.5px/1.6 var(--mono); letter-spacing: 1.3px; color: var(--dim);
  text-align: center;
}

.msg { display: flex; gap: 10px; align-items: flex-start; max-width: 100%; }
.msg.in { flex-direction: row; }
.msg.out { flex-direction: row-reverse; }

.who {
  flex: none; width: 34px; height: 34px; border-radius: 9px;
  display: grid; place-items: center;
  font: 800 10px/1 var(--mono); letter-spacing: .3px;
  background: var(--panel-2); border: 1px solid var(--line); color: var(--dim);
}
.who.game    { color: var(--game);   border-color: rgba(74,163,255,.35);  background: rgba(74,163,255,.10); }
.who.gemini  { color: var(--gemini); border-color: rgba(167,139,250,.35); background: rgba(167,139,250,.10); }
.who.nemotron{ color: var(--nemo);   border-color: rgba(53,208,127,.35);  background: rgba(53,208,127,.10); }
.who.err     { color: var(--bad);    border-color: rgba(255,92,92,.35);   background: rgba(255,92,92,.10); }

.col { min-width: 0; flex: 1; display: flex; flex-direction: column; }
.msg.out .col { align-items: flex-end; }

.name { font: 700 11px/1.4 var(--mono); letter-spacing: 1.1px; color: var(--dim); margin-bottom: 4px; }
.name em { font-style: normal; font-weight: 400; color: var(--dimmer); letter-spacing: .3px; }

.bub {
  background: var(--panel); border: 1px solid var(--line);
  border-radius: 12px; padding: 11px 13px;
  font: 400 14px/1.6 var(--mono); white-space: pre-wrap;
  max-width: 100%; overflow-wrap: anywhere;
}
.msg.out .bub { background: var(--panel-2); border-color: #212832; }
.msg.bad .bub { border-color: rgba(255,92,92,.35); background: rgba(255,92,92,.07); color: #ffb4b4; }
.bub.clip {
  display: -webkit-box; -webkit-line-clamp: 7; -webkit-box-orient: vertical;
  overflow: hidden;
}
.more {
  margin-top: 5px; font: 400 12px/1 var(--mono); color: var(--accent);
  cursor: pointer; background: none; border: 0; padding: 4px 0; text-align: left;
}
.stamp { margin-top: 5px; font: 400 11.5px/1.3 var(--mono); color: var(--dimmer); }

.shot { margin-top: 10px; }
.shot img {
  display: block; width: 100%; max-width: 300px; border-radius: 9px;
  border: 1px solid var(--line); cursor: zoom-in; background: #000;
}
.shot .cap { margin-top: 5px; font: 400 11.5px/1.3 var(--mono); color: var(--dimmer); }
.shot .cap.missing { color: var(--warn); }

@media (min-width: 720px) {
  .bub { font-size: 14.5px; }
  .msg .col { max-width: 82%; }
}

/* --------------------------------------------------------------- play -- */

.videowrap {
  border-radius: 13px; overflow: hidden; border: 1px solid var(--line);
  background: #000; margin-bottom: 22px;
}
.videowrap video { display: block; width: 100%; height: auto; max-height: 76vh; background: #000; }

.notes h2 { font: 700 13px/1.2 var(--mono); letter-spacing: 1.4px; text-transform: uppercase; color: var(--dim); margin: 0 0 10px; }
.notes p { color: var(--dim); font-size: 15px; max-width: 66ch; margin: 0 0 13px; }

/* -------------------------------------------------------------- misc --- */

.empty {
  color: var(--dimmer); font: 400 14px/1.6 var(--mono);
  border: 1px dashed var(--line); border-radius: 11px;
  padding: 26px 18px; text-align: center; margin: 0;
}

footer {
  max-width: 1100px; margin: 0 auto; padding: 20px 0 34px;
  border-top: 1px solid var(--line);
  color: var(--dimmer); font: 400 12.5px/1.6 var(--mono);
  display: flex; gap: 9px; flex-wrap: wrap;
}
/* --line is a border colour; on text it renders at 1.25:1, i.e. invisible.
   A separator nobody can see is not separating anything. */
footer .sep { color: var(--dimmer); }

.lightbox {
  position: fixed; inset: 0; z-index: 50; background: rgba(0,0,0,.92);
  display: grid; place-items: center; padding: 18px; cursor: zoom-out;
}
.lightbox img { max-width: 100%; max-height: 100%; border-radius: 10px; }

/* -------------------------------------------------------- play headings -- */
.cliphead {
  display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap;
  margin: 0 0 10px;
}
.cliphead h2 {
  font: 700 13px/1.2 var(--mono); letter-spacing: 1.4px;
  text-transform: uppercase; color: var(--fg); margin: 0;
}
.cliphead span { font: 400 12px/1.3 var(--mono); color: var(--dimmer); }
#clip-block, #video-block { margin-bottom: 26px; }
