/* ═══════════════════════════════════════════════════════════
   KN/OS - Kay_N's signal outpost
   hand-rolled css · no framework · flat and dense on purpose
   one font for everything. one palette: black, white, red.
   ═══════════════════════════════════════════════════════════ */

:root {
  /* the machine's own terminal face - no webfont, every OS brings its own */
  --font-ui: ui-monospace, "Cascadia Mono", "Cascadia Code", Consolas,
             "Lucida Console", Menlo, monospace;
}

/* the palette. black, white, red - nothing else. */
body {
  --ink-0: #050505;  /* page void          */
  --ink-1: #0d0d0d;  /* panel body         */
  --ink-2: #141414;  /* panel raised       */
  --ink-3: #1d1d1d;  /* deco fills         */
  --line:  #2e2e2e;  /* borders            */
  --fg:    #e6e6e6;  /* body text          */
  --fg-dim:#878787;  /* secondary text     */
  --accent:   #ff2323;  /* red - links, marks   */
  --accent-2: #ff7a6e;  /* soft red             */
  --accent-3: #bdbdbd;  /* silver               */
  --warn:     #ff2323;  /* NEW marks            */
}

/* ── base ─────────────────────────────────────────────── */

* { margin: 0; padding: 0; box-sizing: border-box; }

html {
  scroll-behavior: smooth;
  /* always reserve the scrollbar. without this, a short page has no
     scrollbar and a long one does, so the content width jumps between
     pages and everything appears to resize. */
  overflow-y: scroll;
  scrollbar-gutter: stable;
}

body {
  background: var(--ink-0);
  color: var(--fg);
  font-family: var(--font-ui);
  font-size: 12.5px;
  line-height: 1.65;
  min-height: 100vh;   /* paint the whole viewport even on short pages */
  transition: background-color .35s, color .35s;
}

/* CRT scanlines - faint, the tube never really turns off */
body::after {
  content: "";
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 90;
  background: repeating-linear-gradient(
    0deg,
    rgba(255, 255, 255, 0.022) 0 1px,
    transparent 1px 3px
  );
}

/* tube vignette - the corners were never lit */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 89;
  background: radial-gradient(ellipse at 50% 38%, transparent 55%, rgba(0, 0, 0, 0.42) 100%);
}


/* ── background field ─────────────────────────────────────
   a faint dot grid behind the column, and columns of system
   chatter drifting down both margins - the machine keeps its
   own records whether anyone reads them or not. */
.bgfx {
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  overflow: hidden;
  background-image: radial-gradient(var(--ink-2) 1px, transparent 1px);
  background-size: 42px 42px;
  /* a short, tight fade only at the very edges. a long gradient made
     every line brighten and dim as it travelled, which read as the
     whole sidebar pulsing. */
  -webkit-mask-image: linear-gradient(180deg, transparent, #000 3%, #000 97%, transparent);
          mask-image: linear-gradient(180deg, transparent, #000 3%, #000 97%, transparent);
}

/* lore streams - built by main.js from KN.lore.
   deliberately faint: legible if someone looks, ignorable if not. */
/* edge rails - a measuring-tape spine with regular ticks and a red
   major mark every fifth. nothing like the old diagonal hazard bands. */
.bgfx::before,
.bgfx::after {
  content: "";
  position: absolute;
  /* overhangs by one pattern period top and bottom so the element can
     slide without ever showing an edge */
  top: -130px;
  height: calc(100% + 260px);
  width: 20px;
  opacity: .5;
  background-repeat: no-repeat, repeat-y, repeat-y;
  background-size: 1px 100%, 11px 26px, 19px 130px;
  background-position: 3px 0, 4px 0, 1px 0;
  background-image:
    linear-gradient(var(--line), var(--line)),
    repeating-linear-gradient(180deg, var(--fg-dim) 0 1px, transparent 1px 26px),
    repeating-linear-gradient(180deg, var(--accent) 0 2px, transparent 2px 130px);
  animation: rail 40s linear infinite;
  will-change: transform;
}
.bgfx::before { left: 2px; }
/* the right rail is the same pattern flipped, and runs the other way */
.bgfx::after {
  right: 2px;
  background-position: 16px 0, 5px 0, 0 0;
  animation-duration: 52s;
  animation-direction: reverse;
}

/* Travels exactly one 130px period, which is also a whole number of
   26px ticks, so the loop is seamless. transform keeps this on the
   compositor - animating background-position would repaint every frame. */
@keyframes rail {
  to { transform: translateY(130px); }
}
@media (max-width: 840px) { .bgfx::before, .bgfx::after { display: none; } }

.stream {
  position: absolute;
  top: 0;
  width: 112px;
  overflow: hidden;
  font-size: 10px;
  line-height: 2.5;
  letter-spacing: .05em;
  white-space: nowrap;
  color: var(--fg);
  opacity: .38;
  animation: stream-up linear infinite;
  will-change: transform;
}
.stream i { font-style: normal; color: var(--accent); }
.stream--down { animation-name: stream-down; }

/* every column sits at the same strength - mixed opacities made the
   margins look like they were fading in and out */
.stream--l1 { left: 28px; }
.stream--r1 { right: 28px; text-align: right; }
.stream--l2 { left: 146px; }
.stream--r2 { right: 146px; text-align: right; }

@keyframes stream-up   { from { transform: translateY(0); }    to { transform: translateY(-50%); } }
@keyframes stream-down { from { transform: translateY(-50%); } to { transform: translateY(0); } }

/* only run them where there is real margin to spare, so they can
   never crowd or overlap the content column */
@media (max-width: 1320px) { .stream--l2, .stream--r2 { display: none; } }
@media (max-width: 1090px) { .stream { display: none; } }

.statusbar, .frame { position: relative; z-index: 1; }

/* panels step in on page load */
main .panel { animation: rise .38s ease backwards; }
main .panel:nth-of-type(2) { animation-delay: .07s; }
main .panel:nth-of-type(3) { animation-delay: .14s; }
main .panel:nth-of-type(4) { animation-delay: .21s; }
main .panel:nth-of-type(5) { animation-delay: .28s; }
@keyframes rise {
  from { opacity: 0; transform: translateY(9px); }
}

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

a { color: var(--accent); text-decoration-thickness: 1px; text-underline-offset: 2px; }
a:hover { color: var(--fg); background: var(--ink-3); }
a:visited { text-decoration-style: dotted; }

.frame {
  max-width: 760px;
  margin: 0 auto;
  padding: 0 16px 24px;
}

/* placeholder copy - swap the bracketed text for the real thing,
   then drop the .ph class */
.ph { color: var(--fg-dim); font-style: italic; }

/* art slot - a marked hole where an image or video goes later */
.artslot {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
  aspect-ratio: 16 / 9;
  border: 1px dashed var(--line);
  color: var(--fg-dim);
  font-size: 10px;
  letter-spacing: .08em;
  text-transform: uppercase;
}
.artslot__mark { font-size: 18px; color: var(--accent); }
.artslot--square { aspect-ratio: 1; }

/* "coming soon" chip - a link that isn't one yet */
.soon {
  color: var(--fg-dim);
  cursor: default;
  border-bottom: 1px dashed var(--line);
}
.soon i {
  font-style: normal;
  font-size: 9px;
  color: var(--accent);
  text-transform: uppercase;
  letter-spacing: .08em;
  margin-left: 3px;
}

/* ── boot screen ──────────────────────────────────────── */

/* boot - a terminal, top-left, like the machine is talking to itself */
#boot {
  position: fixed;
  inset: 0;
  z-index: 200;
  background: var(--ink-0);
  display: flex;
  align-items: flex-start;
  justify-content: flex-start;
  padding: 7vh 7vw;
  transition: opacity .4s;
}
#boot.boot--out { opacity: 0; pointer-events: none; }
#boot pre {
  font-family: var(--font-ui);
  font-size: 13px;
  line-height: 1.7;
  color: var(--fg);
  min-height: 15em;
}
#boot pre .b-dim  { color: var(--fg-dim); }
#boot pre .b-ok   { color: var(--fg); }
#boot pre .b-acc  { color: var(--accent); }
#boot pre .b-warn { color: var(--accent); }
#boot pre .b-cur  { color: var(--accent); animation: blink .8s steps(1) infinite; }

/* ── access control gate ──────────────────────────────── */

/* The gate is hidden by default and switched on by the `gated` class,
   which an inline script in <head> sets before the body is parsed. That
   way an unregistered visitor never sees a frame of the site first. */
#gate { display: none; }

html.gated #gate {
  position: fixed;
  inset: 0;
  z-index: 250;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  background: var(--ink-0);
  background-image: repeating-linear-gradient(
    0deg, rgba(255, 255, 255, .022) 0 1px, transparent 1px 3px);
  transition: opacity .36s;
}
html.gated .frame,
html.gated .statusbar,
html.gated #boot { display: none !important; }

#gate.gate--out { opacity: 0; pointer-events: none; }

#gate form {
  width: 100%;
  max-width: 430px;
  border: 1px solid var(--line);
  background: var(--ink-1);
  padding: 18px 18px 14px;
  box-shadow: 0 0 0 1px rgba(255, 35, 35, .1), 0 24px 60px rgba(0, 0, 0, .6);
}

#gate-head {
  font-family: var(--font-ui);
  font-size: 12px;
  line-height: 1.75;
  color: var(--fg-dim);
  min-height: 12em;
  white-space: pre-wrap;
}

.gate__row {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 10px;
  padding: 7px 9px;
  border: 1px solid var(--line);
  background: var(--ink-0);
}
.gate__ps {
  color: var(--accent);
  font-size: 12px;
  white-space: nowrap;
  letter-spacing: .06em;
}
/* the fixed half of the designation - shown, not typed */
.gate__fix {
  color: var(--fg-dim);
  font-size: 14px;
  letter-spacing: .14em;
  user-select: none;
}
#gate-input {
  flex: 1;
  min-width: 0;
  background: transparent;
  border: 0;
  outline: none;
  color: var(--fg);
  font: inherit;
  font-size: 14px;
  letter-spacing: .14em;
  text-transform: uppercase;
  caret-color: var(--accent);
}

.gate__err {
  min-height: 1.5em;
  margin-top: 6px;
  font-size: 11px;
  color: var(--accent);
}
.gate__err:not(:empty)::before { content: "! "; }

.gate__actions { display: flex; gap: 8px; margin-top: 4px; }
.gate__actions .btn { cursor: pointer; font: inherit; }
.gate__actions .btn:disabled { opacity: .55; cursor: wait; }

.gate__fine {
  margin-top: 11px;
  padding-top: 9px;
  border-top: 1px dashed var(--line);
  font-size: 10px;
  color: var(--fg-dim);
}

/* the designation, once issued */
#subject-cell { color: var(--accent); letter-spacing: .06em; }

/* ── status bar ───────────────────────────────────────── */

.statusbar {
  position: sticky;
  top: 0;
  z-index: 10;
  display: flex;
  align-items: stretch;
  gap: 1px;
  background: var(--line);
  border-bottom: 1px solid var(--line);
  font-size: 10px;
  letter-spacing: .04em;
}

.statusbar__cell {
  background: var(--ink-1);
  color: var(--fg-dim);
  padding: 3px 9px;
  white-space: nowrap;
  display: flex;
  align-items: center;
  gap: 5px;
}

.statusbar__sys {
  color: var(--accent);
  font-weight: 700;
  text-shadow: 0 0 7px rgba(255, 35, 35, 0.45);
}
.statusbar__sig { letter-spacing: 1px; transition: color .3s; }
.statusbar__sig b { color: var(--accent); font-weight: 400; }
.statusbar__sig i { color: var(--line); font-style: normal; }
/* full dropout - the whole cell goes cold for a beat */
.statusbar__sig--lost { color: var(--accent); }
.statusbar__sig--lost i { color: var(--accent); opacity: .35; }
.statusbar__spacer { flex: 1; }
.statusbar__clock { color: var(--fg); font-variant-numeric: tabular-nums; }

/* ── masthead ─────────────────────────────────────────── */

.masthead { padding: 18px 0 4px; }

/* static - not a link, not clickable */
.wordmark { display: inline-block; cursor: default; user-select: none; }

.wordmark__text {
  position: relative;
  font-size: 21px;
  font-weight: 700;
  letter-spacing: .14em;
  color: var(--fg);
  text-shadow: 0 0 10px rgba(255, 35, 35, 0.22);
}

/* transmission interference on the name - rare, brief */
.wordmark__text::before,
.wordmark__text::after {
  content: attr(data-text);
  position: absolute;
  left: 0;
  top: 0;
  opacity: 0;
  pointer-events: none;
}
.wordmark__text::before { color: var(--accent); animation: glitch-a 3.7s steps(1) infinite; }
.wordmark__text::after  { color: var(--fg);     animation: glitch-b 4.3s steps(1) infinite; }

@keyframes glitch-a {
  0%, 91%, 100% { opacity: 0; }
  92% { opacity: .8; transform: translate(-2px, 1px); clip-path: inset(10% 0 55% 0); }
  94% { opacity: .8; transform: translate(2px, -1px); clip-path: inset(60% 0 5% 0); }
  96% { opacity: 0; }
}
@keyframes glitch-b {
  0%, 87%, 100% { opacity: 0; }
  88% { opacity: .5; transform: translate(2px, 0);  clip-path: inset(40% 0 30% 0); }
  90% { opacity: .5; transform: translate(-2px, 0); clip-path: inset(0 0 70% 0); }
  92% { opacity: 0; }
}

.cursor { color: var(--accent); animation: blink 1.1s steps(1) infinite; }
@keyframes blink { 50% { opacity: 0; } }

.masthead__tagline { color: var(--fg-dim); font-style: italic; }

.masthead__status {
  font-size: 10px;
  color: var(--fg-dim);
  margin-top: 2px;
}
.masthead__status::before { content: "▸ "; color: var(--accent); }

/* nav - chunky terminal tabs with a sweeping underline */
.deck {
  margin: 8px 0 12px;
  display: flex;
  flex-wrap: nowrap;          /* every button stays on one line */
  align-items: center;
  gap: 4px;
  color: var(--fg-dim);
}
/* below the desktop column width there isn't room for one line,
   so let it wrap rather than overflow the screen */
@media (max-width: 700px) {
  .deck { flex-wrap: wrap; gap: 5px; }
}
/* rule drawn between the nav buttons, inserted by main.js */
.deck__sep {
  color: var(--line);
  letter-spacing: -1px;
  user-select: none;
  pointer-events: none;
}
.deck a {
  position: relative;
  display: inline-block;
  white-space: nowrap;
  padding: 3px 9px;
  border: 1px solid var(--line);
  background: var(--ink-1);
  color: var(--fg);
  text-decoration: none;
  transition: color .18s, border-color .18s, background-color .18s, transform .18s;
}
.deck a::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: -1px;
  width: 100%;
  height: 2px;
  background: var(--accent);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform .22s ease;
}
.deck a:hover {
  color: var(--accent);
  border-color: var(--accent);
  background: var(--ink-2);
  transform: translateY(-1px);
}
.deck a:hover::after { transform: scaleX(1); }
.deck a.here {
  color: var(--ink-0);
  background: var(--accent);
  border-color: var(--accent);
  font-weight: 700;
}
.deck a.here::after { display: none; }
.deck__ext { border-style: dashed; }

/* ── panels ───────────────────────────────────────────── */

.panel {
  border: 1px solid var(--line);
  background: var(--ink-1);
  margin-bottom: 12px;
}

.panel__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  padding: 4px 9px;
  background: linear-gradient(180deg, var(--ink-3), var(--ink-2));
  border-bottom: 1px solid var(--line);
}

.panel__title {
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .14em;
  color: var(--fg);
}
.panel__title::before {
  content: "> ";
  color: var(--accent);
  text-shadow: 0 0 7px rgba(255, 35, 35, 0.55);
}
.panel__title::after {
  content: "_";
  color: var(--accent);
  animation: blink 1.3s steps(1) infinite;
}

.panel__meta { font-size: 10px; color: var(--fg-dim); }
a.panel__meta:hover { color: var(--accent); background: none; }

.panel__body { padding: 9px; }

.panel__foot {
  margin-top: 8px;
  padding-top: 6px;
  border-top: 1px dashed var(--line);
  font-size: 11px;
  color: var(--fg-dim);
}

.panel--empty { border-style: dashed; opacity: .75; }

/* ── workbench / feature ──────────────────────────────── */

.feature {
  display: grid;
  grid-template-columns: 240px 1fr;
  gap: 12px;
  align-items: start;
}

.feature__screen { border: 1px solid var(--line); background: var(--ink-0); padding: 5px; }
.feature__screen img,
.feature__screen video { display: block; width: 100%; height: auto; }
.feature__screen .artslot { border-style: dashed; }

.feature__name {
  font-size: 15px;
  font-weight: 700;
  letter-spacing: .08em;
  color: var(--fg);
  margin-bottom: 3px;
}

/* \n in a pitch / bio / spec line becomes a real line break */
.feature__pitch,
.feature__specs,
.operator__bio p,
.cart__desc { white-space: pre-line; }

.feature__specs { color: var(--fg-dim); font-size: 11px; margin: 4px 0 6px; }

/* ── protocol monitor (workbench, homepage) ───────────────
   fills the right column with something that feels switched on:
   a live readout that knows who is looking at it. */
.mon {
  margin-top: 12px;
  padding: 8px 10px;
  border: 1px dashed var(--line);
  background: var(--ink-0);
  font-size: 10.5px;
  line-height: 1.9;
  color: var(--fg-dim);
}
.mon__title {
  color: var(--fg);
  letter-spacing: .12em;
  text-transform: uppercase;
  font-size: 9.5px;
}
.mon__title::before { content: "┌─ "; color: var(--line); }
.mon__title::after { content: " ─┐"; color: var(--line); }
.mon__row::before { content: "│ "; color: var(--line); }
.mon__row b { font-weight: 400; color: var(--fg); }
.mon__dots { color: var(--line); }
.mon__live { color: var(--accent); }
.mon__live::before { content: "● "; animation: blink 1.5s steps(1) infinite; }
.mon__rot { transition: opacity .4s; }
.mon__rot.is-swap { opacity: 0; }
.mon__foot::before { content: "└ "; color: var(--line); }
.mon__foot i { font-style: normal; color: var(--accent); }

.btn {
  display: inline-block;
  padding: 2px 10px;
  border: 1px solid var(--accent);
  color: var(--accent);
  text-decoration: none;
  font-size: 11px;
}
.btn:hover { background: var(--ink-3); color: var(--fg); }

.btn--dl {
  background: var(--accent);
  color: var(--ink-0);
  font-weight: 700;
}
.btn--dl:hover { background: var(--fg); border-color: var(--fg); color: var(--ink-0); }

/* an unreleased build - looks like a button, does nothing */
.btn--locked {
  border-style: dashed;
  border-color: var(--line);
  color: var(--fg-dim);
  cursor: not-allowed;
  letter-spacing: .06em;
}

.dl { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-top: 6px; }
.dl__note { font-size: 10px; color: var(--fg-dim); margin-top: 4px; }

/* ── download dropdown (one entry per platform) ───────── */

.dlmenu { position: relative; display: inline-block; }
.dlmenu .btn { cursor: pointer; font: inherit; }

.dlmenu__list {
  position: absolute;
  top: calc(100% + 3px);
  left: 0;
  z-index: 20;
  min-width: 100%;
  white-space: nowrap;
  border: 1px solid var(--accent);
  background: var(--ink-1);
  box-shadow: 0 10px 26px rgba(0, 0, 0, .55);
}
.dlmenu__list[hidden] { display: none; }

.dlmenu__item {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  padding: 5px 11px;
  color: var(--fg);
  text-decoration: none;
  font-size: 11px;
  border-bottom: 1px solid var(--line);
}
.dlmenu__item:last-child { border-bottom: 0; }
.dlmenu__item:hover,
.dlmenu__item:focus-visible {
  background: var(--accent);
  color: var(--ink-0);
  outline: none;
}
.dlmenu__os { letter-spacing: .06em; }
.dlmenu__os::before { content: "▸ "; }
.dlmenu__sz { font-size: 10px; color: var(--fg-dim); }
.dlmenu__item:hover .dlmenu__sz,
.dlmenu__item:focus-visible .dlmenu__sz { color: var(--ink-0); }

/* ── transmission log ─────────────────────────────────── */

.log { list-style: none; }

.log__row {
  display: grid;
  grid-template-columns: auto auto 1fr auto;
  align-items: baseline;
  gap: 8px;
  padding: 2px 4px;
}
.log__row:nth-child(odd) { background: var(--ink-2); }
.log__row:hover { background: var(--ink-3); }
.log__row:first-child .log__link::after {
  content: " !!! NEW !!!";
  color: var(--warn);
  font-weight: 700;
  animation: blink 1.4s steps(1) infinite;
}

.log__date {
  font-size: 11px;
  color: var(--fg-dim);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.log__link { color: var(--fg); text-decoration-color: var(--line); }
.log__link:hover { color: var(--accent); background: none; }

.log__ago {
  font-size: 10px;
  color: var(--fg-dim);
  white-space: nowrap;
  text-align: right;
}

.log__year {
  text-align: center;
  font-size: 10px;
  letter-spacing: .3em;
  color: var(--fg-dim);
  margin: 4px 0;
}

.tag {
  font-size: 9px;
  letter-spacing: .08em;
  text-transform: uppercase;
  padding: 0 5px;
  border: 1px solid currentColor;
  white-space: nowrap;
}
.tag--devlog  { color: var(--accent-3); }
.tag--release { color: var(--accent); }
.tag--patch   { color: var(--accent-2); }
.tag--misc    { color: var(--fg-dim); }

/* ── dispatch carts ───────────────────────────────────── */

.shelf {
  list-style: none;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
  gap: 9px;
}
.shelf li { display: grid; }

.cart {
  display: block;
  height: 100%;
  text-decoration: none;
  color: var(--fg);
  background: var(--ink-2);
  border: 1px solid var(--line);
  border-top: 3px solid var(--accent);
  clip-path: polygon(0 0, 100% 0, 100% 100%, 12% 100%, 0 calc(100% - 12px));
  transition: transform .12s;
}
.cart:hover {
  transform: translateY(-3px);
  background: var(--ink-3);
  color: var(--fg);
}

.cart__ridges {
  display: block;
  height: 10px;
  background: repeating-linear-gradient(90deg, transparent 0 7px, var(--line) 7px 9px);
  border-bottom: 1px solid var(--line);
}

.cart__label { display: block; padding: 7px 10px 11px; }

.cart__year { font-size: 9px; color: var(--accent); letter-spacing: .2em; }

.cart__name {
  display: block;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: .05em;
  margin: 2px 0 3px;
  color: var(--fg);
}
.cart:hover .cart__name { color: var(--accent); }

.cart__desc {
  display: block;
  font-size: 11px;
  color: var(--fg-dim);
  min-height: 2.4em;
}

.cart__tags { display: flex; gap: 5px; margin-top: 5px; }
.cart__tags i {
  font-style: normal;
  font-size: 9px;
  color: var(--fg-dim);
  border: 1px dotted var(--line);
  padding: 0 4px;
}

.cart--empty {
  opacity: .5;
  border-top-color: var(--line);
  border-style: dashed;
  cursor: default;
  transform: rotate(-1.2deg);   /* it's leaning against the other one */
}
.cart--empty:hover { transform: rotate(-1.2deg); background: var(--ink-2); }

/* ── operator ─────────────────────────────────────────── */

.operator__card {
  display: grid;
  grid-template-columns: 72px 1fr;
  gap: 11px;
  align-items: start;
}

.operator__portrait { background: var(--ink-0); }
.operator__portrait img { display: block; width: 100%; image-rendering: pixelated; }

/* an <img> used directly as the avatar: fills the square, crops the
   overflow, whatever shape the source file is */
img.operator__portrait {
  width: 100%;
  aspect-ratio: 1;
  object-fit: cover;
  border: 1px solid var(--line);
}

.chipset { margin-top: 6px; color: var(--fg-dim); }

.linklist { list-style: none; }
.linklist li { padding: 2px 0; }
.linklist li::before { content: "▸ "; color: var(--accent); }

/* ── terminal ─────────────────────────────────────────── */

.term__out {
  min-height: 90px;
  max-height: 240px;
  overflow-y: auto;
  white-space: pre-wrap;
  word-break: break-word;
  font-size: 12px;
}
.term__out .t-dim { color: var(--fg-dim); }
.term__out .t-acc { color: var(--accent); }

.term__board {
  font-family: var(--font-ui);
  font-size: 13px;
  line-height: 1.15;
  letter-spacing: 2px;
  color: var(--fg);
  margin: 8px 0 2px;
  text-shadow: 0 0 10px rgba(255, 35, 35, 0.12);
}

.term__in {
  display: flex;
  align-items: center;
  gap: 7px;
  margin-top: 7px;
  padding-top: 7px;
  border-top: 1px dashed var(--line);
}
.term__ps { color: var(--accent); font-size: 12px; white-space: nowrap; }
.term__in input {
  flex: 1;
  background: transparent;
  border: 0;
  outline: none;
  color: var(--fg);
  font: inherit;
  font-size: 12px;
  caret-color: var(--accent);
}

/* ── archive entries: each one its own dropdown ───────── */

#archive .log__row { grid-template-columns: 13px auto auto 1fr auto; }
#archive .log__row.is-expandable { cursor: pointer; }
#archive .log__row.is-expandable:hover { background: var(--ink-3); }
#archive .log__row:focus-visible { outline: 1px solid var(--accent); outline-offset: -1px; }

.log__caret {
  color: var(--accent);
  font-size: 9px;
  line-height: 1;
  user-select: none;
}
.is-open > .log__caret { color: var(--fg); }

/* the panel spans the full row width and sits under its own entry */
.log__detail {
  grid-column: 1 / -1;
  margin: 4px 0 8px 13px;
  padding-top: 6px;
  border-top: 1px dotted var(--line);
}
.log__detail[hidden] { display: none; }

/* the longer write-up under a log entry (archive page) */
.log__desc {
  max-width: 62ch;
  margin: 6px 0 8px 4px;
  padding-left: 9px;
  border-left: 1px solid var(--line);
  font-size: 11.5px;
  line-height: 1.75;
  color: var(--fg-dim);
  white-space: pre-line;      /* \n in content.js becomes a real break */
}
.log__desc.ph { font-style: italic; }

/* media attached to archive entries */
.log__media {
  border: 1px solid var(--line);
  background: var(--ink-0);
  padding: 5px;
  margin: 6px 0 10px;
  max-width: 420px;
}

/* ── media gallery ────────────────────────────────────────
   one item or many. the strip only appears when there's
   more than one thing to show. */

.gal__stage {
  position: relative;
  background: var(--ink-0);
}
.gal__stage img.is-zoomable { cursor: zoom-in; }

/* stage controls: expand, arrows, counter */
.gal__expand,
.gal__arrow {
  position: absolute;
  border: 1px solid var(--line);
  background: rgba(5, 5, 5, .74);
  color: var(--fg);
  font: inherit;
  cursor: pointer;
  opacity: 0;
  transition: opacity .15s, color .15s, border-color .15s;
}
.gal:hover .gal__expand,
.gal:hover .gal__arrow,
.gal__expand:focus-visible,
.gal__arrow:focus-visible { opacity: 1; }

.gal__expand {
  top: 5px;
  right: 5px;
  width: 22px;
  height: 22px;
  line-height: 1;
  font-size: 12px;
}
.gal__arrow {
  top: 50%;
  transform: translateY(-50%);
  width: 22px;
  height: 38px;
  font-size: 17px;
  line-height: 1;
  padding: 0;
}
.gal__arrow--prev { left: 5px; }
.gal__arrow--next { right: 5px; }
.gal__expand:hover,
.gal__arrow:hover { color: var(--accent); border-color: var(--accent); }

.gal__count {
  position: absolute;
  left: 5px;
  bottom: 5px;
  padding: 1px 6px;
  font-size: 9px;
  color: var(--fg-dim);
  background: rgba(5, 5, 5, .74);
  border: 1px solid var(--line);
  opacity: 0;
  transition: opacity .15s;
}
.gal:hover .gal__count { opacity: 1; }

/* touch screens have no hover - keep the controls visible */
@media (hover: none) {
  .gal__expand, .gal__arrow, .gal__count { opacity: 1; }
}

/* ── maximised gallery ────────────────────────────────────
   The gallery itself fills the screen; nothing is copied or moved,
   so a playing video simply keeps playing at a larger size. */

.gal.is-max {
  position: fixed;
  inset: 0;
  z-index: 300;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 40px 56px;
  background: rgba(0, 0, 0, .94);
  animation: maxin .18s ease;
}
@keyframes maxin { from { opacity: 0; } }

.gal.is-max .gal__stage {
  display: flex;
  align-items: center;
  justify-content: center;
  max-width: 100%;
  background: transparent;
}
.gal.is-max .gal__stage img,
.gal.is-max .gal__stage video {
  max-width: 100%;
  max-height: 82vh;
  width: auto;
  height: auto;
  border: 1px solid var(--line);
}
/* 145vh is 82vh scaled to 16:9, so the player is bounded by whichever
   of width or height runs out first and can never overflow */
.gal.is-max .ytbox { width: min(88vw, 1180px, 145vh); }
.gal.is-max .aud { width: min(88vw, 560px); }
.gal.is-max .gal__cap { text-align: center; font-size: 11px; }

/* controls stay put and stay visible while maximised */
.gal.is-max .gal__expand,
.gal.is-max .gal__arrow,
.gal.is-max .gal__count { opacity: 1; }
.gal.is-max .gal__expand { width: 28px; height: 28px; font-size: 12px; }
.gal.is-max .gal__arrow { width: 30px; height: 56px; font-size: 22px; }
.gal.is-max .gal__strip { justify-content: center; max-width: 100%; }

@media (max-width: 620px) {
  .gal.is-max { padding: 40px 10px; }
}

.gal__stage img,
.gal__stage video,
.gal__stage iframe {
  display: block;
  width: 100%;
  height: auto;
  border: 0;
}
.gal__stage[data-kind="youtube"] iframe { aspect-ratio: 16 / 9; height: auto; }
.gal__wrap { display: block; }
.gal__cap {
  font-size: 10px;
  color: var(--fg-dim);
  padding: 4px 2px 0;
}

.gal__strip {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  margin-top: 5px;
}
.gal__thumb {
  width: 40px;
  height: 30px;
  padding: 0;
  border: 1px solid var(--line);
  background: var(--ink-2) center/cover no-repeat;
  color: var(--fg-dim);
  font: inherit;
  font-size: 12px;
  cursor: pointer;
  opacity: .55;
  transition: opacity .15s, border-color .15s, transform .15s;
}
.gal__thumb:hover { opacity: 1; transform: translateY(-1px); }
.gal__thumb.is-on {
  opacity: 1;
  border-color: var(--accent);
  box-shadow: inset 0 -2px 0 var(--accent);
}
.gal__thumb--video, .gal__thumb--youtube, .gal__thumb--audio { color: var(--accent); }
.gal__thumb--image { font-size: 10px; color: var(--fg-dim); }

/* ── audio player ─────────────────────────────────────── */

.aud {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 8px 9px;
  border: 1px solid var(--line);
  background: var(--ink-2);
}
.aud__btn {
  flex: 0 0 auto;
  width: 26px;
  height: 26px;
  border: 1px solid var(--accent);
  background: transparent;
  color: var(--accent);
  font: inherit;
  font-size: 11px;
  line-height: 1;
  cursor: pointer;
}
.aud__btn:hover { background: var(--accent); color: var(--ink-0); }
.aud__mid { flex: 1; min-width: 0; }
.aud__name {
  font-size: 10px;
  color: var(--fg-dim);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  margin-bottom: 3px;
}
.aud__bar {
  height: 6px;
  background: var(--ink-0);
  border: 1px solid var(--line);
  cursor: pointer;
}
.aud__fill {
  height: 100%;
  width: 0;
  background: repeating-linear-gradient(-45deg, var(--accent) 0 4px, transparent 4px 7px);
}
.aud__time {
  flex: 0 0 auto;
  font-size: 10px;
  color: var(--fg-dim);
  font-variant-numeric: tabular-nums;
}

/* ── youtube facade - no request to google until clicked ── */

.yt { position: relative; aspect-ratio: 16 / 9; background: var(--ink-0); }
.yt iframe { width: 100%; height: 100%; }
.yt__play {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 5px;
  width: 100%;
  height: 100%;
  border: 1px dashed var(--line);
  background:
    repeating-linear-gradient(0deg, rgba(255,255,255,.02) 0 1px, transparent 1px 3px),
    var(--ink-1);
  color: var(--fg-dim);
  font: inherit;
  cursor: pointer;
  transition: border-color .15s, color .15s;
}
.yt__play:hover { border-color: var(--accent); color: var(--fg); }
.yt__tri { font-size: 22px; color: var(--accent); }
.yt__lbl { font-size: 11px; }

/* ── footer ───────────────────────────────────────────── */

/* the email address - shown, not linked, but still red */
.js-mail { color: var(--accent); }

.basement {
  text-align: center;
  color: var(--fg-dim);
  font-size: 11px;
  padding-top: 10px;
}
.basement::before {
  content: "──────────── ▚ ────────────";
  display: block;
  color: var(--line);
  letter-spacing: 2px;
  margin-bottom: 6px;
}
.basement__fine { margin-top: 2px; font-size: 10px; }

/* ── responsive ───────────────────────────────────────── */

@media (max-width: 620px) {
  .feature { grid-template-columns: 1fr; }
  .log__row { grid-template-columns: auto auto 1fr; }
  .log__ago { display: none; }
  #visit-counter { display: none; }
}

@media (max-width: 420px) {
  .operator__card { grid-template-columns: 1fr; }
  .operator__portrait { width: 72px; }
}

/* note: the lore streams and signal meter stay animated on purpose -
   they ARE the ambience, and the owner wants them moving everywhere. */
@media (prefers-reduced-motion: reduce) {
  .cursor, .frame, .panel__title::after,
  main .panel, .wordmark__text::before, .wordmark__text::after,
  .log__row:first-child .log__link::after {
    animation: none;
  }
  html { scroll-behavior: auto; }
}
