@font-face {
  font-family: vtFont;
  src: url(/VT323-Regular.ttf);
}

* { box-sizing: border-box; }

::selection {
  background: #000;
  color: #00c800;
}

::placeholder {
  color: inherit;
  opacity: 0.45;
}

::-webkit-scrollbar { width: 8px; height: 8px; }
::-webkit-scrollbar-track { background: #fff; }
::-webkit-scrollbar-thumb { background: #000; }
::-webkit-scrollbar-corner { background: #fff; }
* { scrollbar-color: #000 #fff; scrollbar-width: thin; }

html, body {
  margin: 0;
  padding: 0;
}

body {
  background: #00c800;
  color: #000;
  font-family: vtFont, "Courier New", monospace;
  font-size: 22px;
  line-height: 1.2;
  min-height: 100vh;
  display: flow-root;
  caret-color: #00c800;
  cursor: crosshair;
  accent-color: #000;
}

/* CRT scanlines — fixed overlay, no animation */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 9999;
  background: repeating-linear-gradient(
    to bottom,
    rgba(0, 0, 0, 0.18) 0 1px,
    transparent 1px 3px
  );
}

/* CRT vignette — darker corners, lighter middle */
body::after {
  content: "";
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 9998;
  background: radial-gradient(
    ellipse at center,
    transparent 55%,
    rgba(0, 0, 0, 0.35) 100%
  );
}

/* Top bar with exit-to-index link, used by non-index pages */
.top-bar {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 0.25em 0.8em;
  background: #fff;
  color: #000;
  border-bottom: 2px solid #000;
  z-index: 10000;
  font-family: vtFont, "Courier New", monospace;
  font-size: 0.85em;
  letter-spacing: 0.04em;
}
/* ios safari (26+) fills the strip under its see-through top bar with the
   colour of the fixed element at the top edge: the bar has to be that element,
   so it sits above the crt overlays (whose transparency Safari would pick
   instead, letting scrolled posts show) and carries its own scanlines */
.top-bar::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: repeating-linear-gradient(to bottom, rgba(0, 0, 0, 0.18) 0 1px, transparent 1px 3px);
}
.top-bar a,
.top-bar a:visited {
  color: inherit;
  text-decoration: none;
  padding: 0 0.4em;
}
.top-bar a:hover,
.top-bar a:focus-visible {
  background: #000;
  color: #fff;
  outline: none;
}

/* Title bar with pinstripes */
h1 {
  margin: 0;
  padding: 0;
  background: #fff;
  border-bottom: 2px solid #000;
  text-align: center;
  font-size: 1.4em;
  font-weight: normal;
  line-height: 1.8em;
  letter-spacing: 0.04em;
  white-space: nowrap;
  overflow: hidden;
}

h1::before,
h1::after {
  content: "";
  display: inline-block;
  width: 22%;
  height: 0.6em;
  vertical-align: middle;
  margin: 0 0.8em;
  background: repeating-linear-gradient(
    to bottom,
    #000 0 1px,
    transparent 1px 3px
  );
}

h2 {
  display: table;
  margin: 1.4em 1em 0.4em;
  padding: 0.15em 0.6em;
  font-size: 1.25em;
  font-weight: normal;
  background: #000;
  color: #fff;
  letter-spacing: 0.06em;
}

h3 {
  margin: 1em 1em 0.2em;
  font-size: 1.1em;
  font-weight: normal;
  text-decoration: underline;
}

p {
  margin: 0.4em 1.2em;
}

ul {
  margin: 0.2em 0 0.8em;
  padding: 0 1.2em 0 2.4em;
  list-style: none;
}

li { padding: 0.05em 0; }

li::before {
  content: "\25B8  ";
}

a,
a:visited {
  color: #000;
  text-decoration: underline;
}

a:hover,
a:focus-visible {
  background: #000;
  color: #fff;
  text-decoration: none;
  outline: none;
}

code {
  background: #000;
  color: #fff;
  padding: 0 0.3em;
  font-family: inherit;
  font-size: 1em;
}

/* Home page widget stack — cap each widget at the legacy window width and
   center them so the page reads the same after the wrapper was dropped.
   The width clamp keeps a 1em gutter on either side at narrow viewports
   so widgets don't run flush against the screen edges on mobile. */
body.home-page > aside {
  width: min(820px, calc(100% - 2em));
  margin-left: auto;
  margin-right: auto;
}

/* On the index, the radio is one widget in a vertical stack — not the
   floating overlay used on /space. Strip the fixed positioning and let it
   fill the column like the BBS panel below it. The bar font-size matches
   the other widget bars on this page (0.85em vs the player's 1em). */
body.home-page .radio {
  position: static;
  width: min(820px, calc(100% - 2em));
  margin: 0.8em auto 1.2em;
  box-shadow: 4px 4px 0 #000;
}
body.home-page .radio__bar { font-size: 0.85em; }

/* "Trending on space" widget — small list of random artist links.
   Mirrors the BBS chat panel so the home page reads as a stack of
   matching widgets. */
.trending {
  margin: 0.8em 1em 1.2em;
  background: #fff;
  border: 2px solid #000;
  box-shadow: 4px 4px 0 #000;
  font-family: vtFont, "Courier New", monospace;
  display: flex;
  flex-direction: column;
}
.trending__bar {
  background: #fff;
  color: #000;
  border-bottom: 2px solid #000;
  font-size: 0.85em;
  line-height: 1.6em;
  letter-spacing: 0.06em;
  white-space: nowrap;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.5em;
  padding: 0 0.5em;
}
.trending__bar::before,
.trending__bar::after {
  content: "";
  flex: 1;
  min-width: 0;
  height: 0.45em;
  background: repeating-linear-gradient(
    to bottom,
    #000 0 1px,
    transparent 1px 3px
  );
}
.trending__list {
  list-style: none;
  margin: 0;
  padding: 0.7em 0.6em 0.8em;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 0.6em 0.4em;
}
.trending__list > li { min-width: 0; }
.trending__list > li::before { content: none; }
.trending__list a,
.trending__list a:visited {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 0.3em;
  padding: 0.2em 0.15em;
  font-size: 0.8em;
  text-decoration: none;
  color: inherit;
}
.trending__list a:hover,
.trending__list a:focus-visible {
  background: #000;
  color: #fff;
  outline: none;
}
.trending__pic {
  width: 56px;
  height: 56px;
  border: 2px solid currentColor;
  box-shadow: 2px 2px 0 currentColor;
  line-height: 0;
}
.trending__pic svg { display: block; width: 100%; height: 100%; }
.trending__name {
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* "// TUBE //" home-page widget — mirrors the trending grid but with
   16:9 video thumbs instead of square avatars. Each tile is a stand-in
   for a procedural music video; the click goes to /tube.html where a
   fresh track is built. */
.tube-feat {
  margin: 0.8em 1em 1.2em;
  background: #fff;
  border: 2px solid #000;
  box-shadow: 4px 4px 0 #000;
  font-family: vtFont, "Courier New", monospace;
  display: flex;
  flex-direction: column;
}
.tube-feat__bar {
  background: #fff;
  color: #000;
  border-bottom: 2px solid #000;
  font-size: 0.85em;
  line-height: 1.6em;
  letter-spacing: 0.06em;
  white-space: nowrap;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.5em;
  padding: 0 0.5em;
}
.tube-feat__bar::before,
.tube-feat__bar::after {
  content: "";
  flex: 1;
  min-width: 0;
  height: 0.45em;
  background: repeating-linear-gradient(
    to bottom,
    #000 0 1px,
    transparent 1px 3px
  );
}
.tube-feat__list {
  list-style: none;
  margin: 0;
  padding: 0.7em 0.6em 0.8em;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 0.6em 0.4em;
}
.tube-feat__list > li { min-width: 0; }
.tube-feat__list > li::before { content: none; }
.tube-feat__list a,
.tube-feat__list a:visited {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  text-align: center;
  gap: 0.25em;
  padding: 0.2em 0.15em;
  font-size: 0.8em;
  text-decoration: none;
  color: inherit;
}
.tube-feat__list a:hover,
.tube-feat__list a:focus-visible {
  background: #000;
  color: #fff;
  outline: none;
}
.tube-feat__thumb {
  position: relative;
  aspect-ratio: 16 / 9;
  border: 2px solid currentColor;
  background: #000;
  color: #00c800;
  font-size: 1.1em;
  line-height: 1;
  letter-spacing: 0.1em;
  box-shadow: 2px 2px 0 currentColor;
  overflow: hidden;
}
.tube-feat__thumb svg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
}
/* Center-darkening vignette so the play arrow stays readable regardless of
   how dense (or what color) the underlying Truchet weave is. */
.tube-feat__thumb::before {
  content: '';
  position: absolute;
  inset: 0;
  background: radial-gradient(ellipse at center, rgba(0, 0, 0, 0.7) 0%, rgba(0, 0, 0, 0.15) 75%);
  pointer-events: none;
}
.tube-feat__thumb-play {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  color: #fff;
  text-shadow: 0 0 4px rgba(0, 0, 0, 0.85);
}
.tube-feat__list a:hover .tube-feat__thumb,
.tube-feat__list a:focus-visible .tube-feat__thumb {
  /* Keep the box-shadow visible against the inverted black hover bg. */
  background: #000;
  color: #00c800;
}
/* Title (track title) is the prominent line; the artist drops to a muted
   byline beneath it, with views as the smallest line. Mirrors the
   tube-home tile hierarchy and the related-videos sidebar inside /tube. */
.tube-feat__title {
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  letter-spacing: 0.02em;
}
.tube-feat__name {
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 0.9em;
  opacity: 0.75;
  letter-spacing: 0.02em;
}
.tube-feat__sub {
  font-size: 0.85em;
  opacity: 0.6;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* "▸ OPEN FEED" footer link — mirrors .roll-feat__more / .flux-feat__more so
   the three video-ish widgets read as a family. Leads to the /tube homepage
   added in 20260507a (4×3 recommended grid). */
.tube-feat__more {
  display: block;
  text-align: center;
  text-decoration: none;
  color: #000;
  border-top: 2px solid #000;
  padding: 0.4em 0.8em;
  font-size: 0.85em;
  letter-spacing: 0.08em;
}
.tube-feat__more:hover,
.tube-feat__more:focus-visible {
  background: #000;
  color: #fff;
  outline: none;
}

/* "// ROLL //" home-page widget — same structure as TUBE, but with square
   1:1 photo thumbs rendered by the /roll image pipeline. */
.roll-feat {
  margin: 0.8em 1em 1.2em;
  background: #fff;
  border: 2px solid #000;
  box-shadow: 4px 4px 0 #000;
  font-family: vtFont, "Courier New", monospace;
  display: flex;
  flex-direction: column;
}
.roll-feat__bar {
  background: #fff;
  color: #000;
  border-bottom: 2px solid #000;
  font-size: 0.85em;
  line-height: 1.6em;
  letter-spacing: 0.06em;
  white-space: nowrap;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.5em;
  padding: 0 0.5em;
}
.roll-feat__bar::before,
.roll-feat__bar::after {
  content: "";
  flex: 1;
  min-width: 0;
  height: 0.45em;
  background: repeating-linear-gradient(
    to bottom,
    #000 0 1px,
    transparent 1px 3px
  );
}
.roll-feat__list {
  list-style: none;
  margin: 0;
  padding: 0.7em 0.6em 0.8em;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 0.6em 0.4em;
}
.roll-feat__list > li { min-width: 0; }
.roll-feat__list > li::before { content: none; }
.roll-feat__list a,
.roll-feat__list a:visited {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  text-align: center;
  gap: 0.25em;
  padding: 0.2em 0.15em;
  font-size: 0.8em;
  text-decoration: none;
  color: inherit;
}
.roll-feat__list a:hover,
.roll-feat__list a:focus-visible {
  background: #000;
  color: #fff;
  outline: none;
}
.roll-feat__thumb {
  display: block;
  width: 100%;
  aspect-ratio: 1 / 1;
  border: 2px solid currentColor;
  background: #000;
  image-rendering: pixelated;
  image-rendering: crisp-edges;
  box-shadow: 2px 2px 0 currentColor;
}
.roll-feat__name {
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  letter-spacing: 0.02em;
}
.roll-feat__sub {
  font-size: 0.85em;
  opacity: 0.7;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.roll-feat__more {
  display: block;
  text-align: center;
  text-decoration: none;
  color: #000;
  border-top: 2px solid #000;
  padding: 0.4em 0.8em;
  font-size: 0.85em;
  letter-spacing: 0.08em;
}
.roll-feat__more:hover,
.roll-feat__more:focus-visible {
  background: #000;
  color: #fff;
  outline: none;
}

/* "// FLUX //" home-page widget — text-only snippets. Same panel chrome as
   ROLL / TUBE but rows are nick + truncated body, no thumbs. */
.flux-feat {
  margin: 0.8em 1em 1.2em;
  background: #fff;
  border: 2px solid #000;
  box-shadow: 4px 4px 0 #000;
  font-family: vtFont, "Courier New", monospace;
  display: flex;
  flex-direction: column;
}
.flux-feat__bar {
  background: #fff;
  color: #000;
  border-bottom: 2px solid #000;
  font-size: 0.85em;
  line-height: 1.6em;
  letter-spacing: 0.06em;
  white-space: nowrap;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.5em;
  padding: 0 0.5em;
}
.flux-feat__bar::before,
.flux-feat__bar::after {
  content: "";
  flex: 1;
  min-width: 0;
  height: 0.45em;
  background: repeating-linear-gradient(
    to bottom,
    #000 0 1px,
    transparent 1px 3px
  );
}
.flux-feat__list {
  list-style: none;
  margin: 0;
  padding: 0.6em 0.6em 0.7em;
  display: flex;
  flex-direction: column;
  gap: 0.55em;
}
.flux-feat__list > li { min-width: 0; }
.flux-feat__list > li::before { content: none; }
.flux-feat__list a,
.flux-feat__list a:visited {
  display: grid;
  grid-template-columns: auto 1fr;
  column-gap: 0.55em;
  align-items: start;
  text-decoration: none;
  color: inherit;
  padding: 0.45em 0.55em;
  border: 2px solid #000;
  background: #fff;
  box-shadow: 3px 3px 0 #000;
}
.flux-feat__list a:hover,
.flux-feat__list a:focus-visible {
  background: #000;
  color: #fff;
  outline: none;
}
.flux-feat__avatar {
  width: 36px;
  height: 36px;
  border: 1px solid #000;
  background: #000;
  image-rendering: pixelated;
  image-rendering: crisp-edges;
  flex-shrink: 0;
}
.flux-feat__avatar svg { display: block; width: 100%; height: 100%; }
.flux-feat__main { min-width: 0; }
.flux-feat__nick {
  font-size: 0.85em;
  letter-spacing: 0.04em;
  font-weight: bold;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.flux-feat__body {
  font-size: 0.9em;
  line-height: 1.25;
  word-break: break-word;
  margin-top: 0.1em;
}
.flux-feat__more {
  display: block;
  text-align: center;
  text-decoration: none;
  color: #000;
  border-top: 2px solid #000;
  padding: 0.4em 0.8em;
  font-size: 0.85em;
  letter-spacing: 0.08em;
}
.flux-feat__more:hover,
.flux-feat__more:focus-visible {
  background: #000;
  color: #fff;
  outline: none;
}

/* "// PORTALSCRIPT //" home-page widget — the developer portal as a small
   Portalis OS window (portalis/os.css; .os-here carries its tokens on this
   page): the network's pale banner, three tutorials as a document list, each
   ending on one line of its code in the club's vtFont on black, so the
   language shows before anyone clicks, then the buttons and a status bar.
   Populated by index.js from window.PORTALSCRIPT. */
.ps-feat { margin: 0.8em 1em 1.4em; }
.ps-feat .os-body { background: #fff; }
.ps-feat.is-min .os-body { display: none; }
.ps-feat .os-cap--min { cursor: pointer; }
.ps-feat .os-cap--x { cursor: default; }
.ps-feat__head,
.ps-feat__head:visited {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 14px;
  background: linear-gradient(90deg, #dff1f3, #f4fafa 55%, #fff);
  border-bottom: 1px solid #c4d9dc;
  color: var(--os-t1);
  text-decoration: none;
}
.ps-feat__head:hover,
.ps-feat__head:focus-visible { background: linear-gradient(90deg, #cfeaee, #eef8f9 55%, #fff); color: var(--os-t1); outline: none; }
.ps-feat__head img { width: 34px; height: 34px; flex: none; filter: drop-shadow(1px 2px 0 rgba(7, 47, 61, 0.35)); }
.ps-feat__head b { display: block; font: 26px/1 vtFont, monospace; letter-spacing: 0.02em; }
.ps-feat__head small { display: block; font-size: 11px; color: #5d6b6a; margin-top: 2px; }
.ps-feat__h {
  margin: 10px 14px 2px;
  padding-bottom: 3px;
  color: var(--os-t1);
  font-weight: bold;
  border-bottom: 2px solid transparent;
  border-image: linear-gradient(90deg, var(--os-t2), rgba(21, 122, 144, 0.25) 60%, transparent) 1;
}
.ps-feat__list { list-style: none; margin: 0; padding: 2px 14px 4px; }
.ps-feat__list > li { min-width: 0; padding: 0; border-bottom: 1px solid #e3eaea; }
.ps-feat__list > li:last-child { border-bottom: 0; }
.ps-feat__list > li::before { content: none; }
/* each tutorial: a page icon (folded corner) beside title, intro and code */
.ps-feat__list a,
.ps-feat__list a:visited {
  position: relative;
  display: block;
  padding: 7px 4px 8px 22px;
  color: var(--os-ink);
  text-decoration: none;
}
.ps-feat__list a::before {
  content: "";
  position: absolute;
  left: 3px;
  top: 10px;
  width: 11px;
  height: 13px;
  background: linear-gradient(135deg, #fff, #cfe9ee);
  border: 1px solid var(--os-line);
  clip-path: polygon(0 0, 65% 0, 100% 30%, 100% 100%, 0 100%);
}
.ps-feat__list a:hover,
.ps-feat__list a:focus-visible { background: #e2f2f4; outline: none; }
.ps-feat__title { color: var(--os-t2); text-decoration: underline; line-height: 1.3; }
.ps-feat__list a:hover .ps-feat__title { color: var(--os-t1); }
.ps-feat__lv {
  display: inline-block;
  font-size: 10px;
  padding: 0 4px;
  margin-left: 6px;
  vertical-align: 1px;
  white-space: nowrap;
  color: var(--os-t1);
  background: #e2f2f4;
  border: 1px solid #9fc9d1;
  text-decoration: none;
}
.ps-feat__body { font-size: 12px; line-height: 1.35; color: #5d6b6a; margin-top: 2px; }
.ps-feat__code {
  margin-top: 5px;
  padding: 1px 7px;
  background: #000;
  color: #fff;
  font: 16px/1.25 vtFont, monospace;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  border: 1px solid;
  border-color: var(--os-dk) #fff #fff var(--os-dk);
  box-shadow: 0 0 0 1px var(--os-sh);
}
/* the teaser's highlighting matches the portal's listings */
.ps-feat__code .p { color: #9a9; }
.ps-feat__code .t { color: #45f0ff; }
.ps-feat__code .u,
.ps-feat__code .n { color: #ffc857; }
.ps-feat__code .s { color: #7dff7d; }
.ps-feat__code .c { opacity: 0.5; }
.ps-feat__acts { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 6px; padding: 8px 14px 12px; }
.ps-feat .os-status { margin: 0; background: var(--os-face); }

/* "// MORPHOGENICS //" home-page widget — Portalis Morphogenics' breeder as a
   small Portalis OS window under the developer network's, sharing its banner
   and buttons: a live specimen on its pad (a dark well, as in the lab) beside
   what the lab files about it. Populated by index.js, drawn by
   portalis/morphoview.js. */
.mg-feat { margin: 0.8em 1em 1.4em; }
.mg-feat .os-body { background: #fff; }
.mg-feat.is-min .os-body { display: none; }
.mg-feat .os-cap--min { cursor: pointer; }
.mg-feat .os-cap--x { cursor: default; }
.mg-feat__row { display: flex; gap: 14px; align-items: center; padding: 12px 14px 4px; }
.mg-feat__stage { flex: 0 0 min(46%, 260px); display: block; }
.mg-feat__pad {
  display: block;
  width: 100%;
  aspect-ratio: 1;
  background: radial-gradient(ellipse at 50% 85%, #0f4352, #04141b 70%);
  box-shadow: inset 1px 1px 0 var(--os-dk), inset -1px -1px 0 #fff;
}
.mg-feat__stage:focus-visible { outline: 2px solid var(--os-gold); outline-offset: 2px; }
.mg-feat__info { flex: 1; min-width: 0; font-size: 12px; color: #5d6b6a; }
.mg-feat__info p { margin: 0 0 6px; }
.mg-feat__h { font-size: 11px; font-weight: bold; color: var(--os-t1); text-transform: uppercase; letter-spacing: 0.06em; }
.mg-feat__id { font: 24px/1 vtFont, monospace; color: var(--os-t1); }
.mg-feat__cls { color: var(--os-t2); }
.mg-feat__note { font-style: italic; line-height: 1.35; }
.mg-feat__watch b { font: 15px vtFont, monospace; color: #8a5a00; }
.mg-feat .os-status { margin: 0; background: var(--os-face); }
@media (max-width: 520px) {
  .mg-feat__row { flex-direction: column; align-items: stretch; }
  .mg-feat__stage { flex-basis: auto; }
}

/* "// LIBRARY //" home-page widget — display-only "tag cloud" of the most-
   recently-favorited tracks. Same panel chrome as the other -feat widgets
   (white card, hard 4px shadow, dotted-bar header) so it reads as part of
   the home stack. The differentiator is the inside: each track is a small
   pill (border + tight padding) flowing in a flex-wrap row, so 8–10 tracks
   stack visually without looking like a feed of "things to click". The only
   interactive surface is the // OPEN LIBRARY // link at the bottom that
   leads to /library.html. Populated by index.js from window.NOBODY_LIBRARY. */
.library-feat {
  margin: 0.8em 1em 1.2em;
  background: #fff;
  border: 2px solid #000;
  box-shadow: 4px 4px 0 #000;
  font-family: vtFont, "Courier New", monospace;
  display: flex;
  flex-direction: column;
}
.library-feat__bar {
  background: #fff;
  color: #000;
  border-bottom: 2px solid #000;
  font-size: 0.85em;
  line-height: 1.6em;
  letter-spacing: 0.06em;
  white-space: nowrap;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.5em;
  padding: 0 0.5em;
}
.library-feat__bar::before,
.library-feat__bar::after {
  content: "";
  flex: 1;
  min-width: 0;
  height: 0.45em;
  background: repeating-linear-gradient(
    to bottom,
    #000 0 1px,
    transparent 1px 3px
  );
}
/* Pill cloud — flex-wrap so 8–10 short titles flow naturally over 2–3 lines.
   Each pill is a tight black-bordered tag carrying the track title. The list
   is display-only; no hover affordance to imply clickability. */
.library-feat__list {
  list-style: none;
  margin: 0;
  padding: 0.6em 0.6em 0.7em;
  display: flex;
  flex-wrap: wrap;
  gap: 0.3em;
  font-size: 0.78em;
}
.library-feat__list > li {
  min-width: 0;
  max-width: 100%;
  background: #fff;
  color: #000;
  border: 1px solid #000;
  /* Left padding gives the inverted artist block some breathing room from
     the pill border — without it the two black edges crash into each other
     and the artist tag reads as a corner stamp rather than its own block.
     Top padding is heavier than bottom because the inverted artist tag
     fills the full line-box height: a small top pad would still let the
     tag's black edge touch the pill's top border. Bottom is lighter because
     VT323 leaves some descender space below the baseline naturally. */
  padding: 0.25em 0.4em 0.15em 0.35em;
  letter-spacing: 0.02em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.library-feat__list > li::before { content: none; }
/* Inverted artist tag — same idiom as .radio__track-artist on the marquee. */
.library-feat__pill-artist {
  background: #000;
  color: #fff;
  padding: 0 0.3em;
  margin-right: 0.25em;
  letter-spacing: 0.04em;
}
.library-feat__empty {
  margin: 0;
  padding: 0.7em 0.7em 0.8em;
  font-size: 0.85em;
  opacity: 0.75;
  text-align: center;
}
.library-feat__more {
  display: block;
  text-align: center;
  text-decoration: none;
  color: #000;
  border-top: 2px solid #000;
  padding: 0.4em 0.8em;
  font-size: 0.85em;
  letter-spacing: 0.08em;
}
.library-feat__more:hover,
.library-feat__more:focus-visible {
  background: #000;
  color: #fff;
  outline: none;
}

/* "// PACKAGES //" home-page widget — Program-Manager-style desktop with
   one icon per first-party program (seek.exe, zone.exe). Same panel chrome
   (border + 4px shadow + dotted bar) as the other home widgets. The icon
   tile uses currentColor for both border and SVG strokes so the whole tile
   inverts cleanly when the link is hovered/focused (black-on-white →
   white-on-black) — matches the .trending tile idiom. */
.packages {
  margin: 0.8em 1em 1.2em;
  background: #fff;
  border: 2px solid #000;
  box-shadow: 4px 4px 0 #000;
  font-family: vtFont, "Courier New", monospace;
  display: flex;
  flex-direction: column;
}
.packages__bar {
  background: #fff;
  color: #000;
  border-bottom: 2px solid #000;
  font-size: 0.85em;
  line-height: 1.6em;
  letter-spacing: 0.06em;
  white-space: nowrap;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.5em;
  padding: 0 0.5em;
}
.packages__bar::before,
.packages__bar::after {
  content: "";
  flex: 1;
  min-width: 0;
  height: 0.45em;
  background: repeating-linear-gradient(
    to bottom,
    #000 0 1px,
    transparent 1px 3px
  );
}
.packages__list {
  list-style: none;
  margin: 0;
  padding: 1em 0.6em 1.1em;
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 0.6em;
}
.packages__list > li { min-width: 0; }
.packages__list > li::before { content: none; }
.packages__item,
.packages__item:visited {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.45em;
  padding: 0.6em 0.4em;
  text-decoration: none;
  color: inherit;
}
.packages__item:hover,
.packages__item:focus-visible {
  background: #000;
  color: #fff;
  outline: none;
}
/* No fixed background on the icon tile — the link's bg shows through, so
   the SVG's currentColor strokes always have the correct contrast (black
   strokes on white at rest, white strokes on black on hover). */
.packages__icon {
  width: 64px;
  height: 64px;
  border: 2px solid currentColor;
  box-shadow: 2px 2px 0 currentColor;
  display: block;
  line-height: 0;
}
.packages__icon svg {
  display: block;
  width: 100%;
  height: 100%;
}
/* voidlane.exe's ship: shaded faces mixed from currentColor and the link's
   own background (--pk-bg), so it inverts on hover with the rest */
.packages__item { --pk-bg: #fff; --pk-fg: #000; }
.packages__item:hover,
.packages__item:focus-visible { --pk-bg: #000; --pk-fg: #fff; }
.packages__icon--ship svg { stroke: currentColor; stroke-width: 0.6; stroke-linejoin: round; }
.packages__icon--ship .sh-a { fill: var(--pk-bg); }
.packages__icon--ship .sh-b { fill: color-mix(in srgb, currentColor 35%, var(--pk-bg)); }
.packages__icon--ship .sh-c { fill: color-mix(in srgb, currentColor 70%, var(--pk-bg)); }
.packages__icon--ship .sh-h { fill: color-mix(in srgb, currentColor 12%, var(--pk-bg)); }
.packages__icon--ship .sh-n { fill: currentColor; }
.packages__name {
  font-size: 0.9em;
  letter-spacing: 0.04em;
}
/* the featured slot (STRATA :: DRIFT, placed by Portalis Ltd): the whole
   row, icon beside the text, and the one icon in colour. the icon keeps its
   own night sky when the link inverts; only its frame follows currentColor */
.packages__feat { grid-column: 1 / -1; }
/* four icons under it make two rows of two; psstudio.exe, once it turns up,
   makes five: three columns then, so none sits alone on the last row */
.packages__list:not(:has(> li[hidden])) { grid-template-columns: repeat(3, 1fr); }
.packages__feat .packages__item {
  flex-direction: row;
  justify-content: center;
  gap: 0.9em;
  padding: 0.7em 0.6em;
}
.packages__icon--city {
  width: 80px;
  height: 80px;
  flex: none;
}
.packages__icon--city svg { filter: drop-shadow(0 0 3px rgba(255, 63, 180, 0.5)); }
.packages__txt {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.3em;
  min-width: 0;
}
.packages__feat .packages__name { font-size: 1.05em; }
.packages__line { font-size: 0.8em; opacity: 0.75; }
/* a black chip so the pale mark reads on white; outlined so it still shows
   once the link goes black */
.packages__by {
  display: inline-flex;
  align-items: center;
  gap: 0.35em;
  padding: 0.1em 0.45em 0.1em 0.3em;
  background: #000;
  color: #45f0ff;
  border: 1px solid currentColor;
  font-size: 0.7em;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.packages__by img { display: block; }
/* the windows go on and off on their own clocks; the beacon blinks */
.pk-w { animation: pk-win 7s steps(1) infinite; }
.pk-w2 { animation-duration: 5.3s; animation-delay: -2s; }
.pk-w3 { animation-duration: 9.1s; animation-delay: -4s; }
.pk-w4 { animation-duration: 6.2s; animation-delay: -1s; }
.pk-w5 { animation-duration: 11s; animation-delay: -6s; }
.pk-w6 { animation-duration: 4.7s; animation-delay: -3s; }
@keyframes pk-win { 0%, 100% { opacity: 1; } 62% { opacity: 0.15; } 71% { opacity: 1; } }
.pk-beacon { animation: pk-beacon 1.6s steps(1) infinite; }
@keyframes pk-beacon { 0%, 100% { opacity: 1; } 50% { opacity: 0.1; } }
@media (prefers-reduced-motion: reduce) {
  .pk-w, .pk-beacon { animation: none; }
}

/* "// SYSOP.NFO //" home-page widget — last in the stack. Same panel
   chrome as the others, but the body is a single <pre> formatted like a
   scene NFO: small block-glyph header, three aphorism lines, dot
   separator, then two contact lines. Pre-wrap so over-long aphorisms
   don't push the panel wider than its sibling widgets on mobile. */
.sysop {
  margin: 0.8em 1em 1.2em;
  background: #fff;
  border: 2px solid #000;
  box-shadow: 4px 4px 0 #000;
  font-family: vtFont, "Courier New", monospace;
  display: flex;
  flex-direction: column;
}
.sysop__bar {
  background: #fff;
  color: #000;
  border-bottom: 2px solid #000;
  font-size: 0.85em;
  line-height: 1.6em;
  letter-spacing: 0.06em;
  white-space: nowrap;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.5em;
  padding: 0 0.5em;
}
.sysop__bar::before,
.sysop__bar::after {
  content: "";
  flex: 1;
  min-width: 0;
  height: 0.45em;
  background: repeating-linear-gradient(
    to bottom,
    #000 0 1px,
    transparent 1px 3px
  );
}
.sysop__nfo {
  margin: 0;
  padding: 0.8em 0.9em 0.6em;
  font-family: inherit;
  font-size: 0.85em;
  line-height: 1.25;
  white-space: pre-wrap;
  word-break: break-word;
  letter-spacing: 0.02em;
}
.sysop__nfo a,
.sysop__nfo a:visited {
  color: inherit;
  text-decoration: underline;
}
.sysop__nfo a:hover,
.sysop__nfo a:focus-visible {
  background: #000;
  color: #fff;
  text-decoration: none;
  outline: none;
}

/* community notice on top of the home stack — a black strip in the
   PortalScript letterhead's colours (the Portalis mark is pale, it needs
   the dark). full width, flush to the top, the widgets start under it. */
.endow {
  display: flex;
  align-items: stretch;
  background: #000;
  color: #fff;
  border-bottom: 2px solid #000;
  box-shadow: 0 4px 0 rgba(0, 0, 0, 0.35);
  margin-bottom: 0.4em;
}
.endow__in,
.endow__in:visited {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.6em;
  padding: 0.35em 0.8em;
  color: inherit;
  text-decoration: none;
}
.endow__in:hover,
.endow__in:focus-visible { background: #111; outline: none; }
.endow__in:hover b { text-decoration: underline; }
.endow__in img { width: 1.7em; height: 1.7em; flex: none; }
.endow__txt { min-width: 0; max-width: 760px; }
.endow__txt b {
  display: block;
  font-weight: normal;
  letter-spacing: 0.05em;
  line-height: 1.05;
}
.endow__txt small {
  display: block;
  font-size: 0.7em;
  color: #45f0ff;
  letter-spacing: 0.04em;
  line-height: 1.2;
  margin-top: 0.1em;
}
.endow__x {
  flex: none;
  background: none;
  border: 0;
  border-left: 1px solid #333;
  color: #888;
  font: inherit;
  padding: 0 0.6em;
  cursor: pointer;
}
.endow__x:hover,
.endow__x:focus-visible { background: #fff; color: #000; outline: none; }

@media (max-width: 640px) {
  body { font-size: 18px; }
  body > div { margin: 1em; }
  h1::before,
  h1::after { width: 10%; margin: 0 0.4em; }
  .trending__list { grid-template-columns: repeat(2, 1fr); }
  /* Shrink the NFO further on phones so the dash/dot frame still fits a
     360px viewport without wrapping into a second visual line. */
  .sysop__nfo { font-size: 0.75em; }
  .endow__in { justify-content: flex-start; }
}

/* the club's masthead on the home page: the logo (club.js) in black ink on the green. the
   cursor head blinks at a terminal's rate; reduced motion keeps it lit */
.masthead {
  width: min(820px, calc(100% - 2em));
  margin: 1.2em auto 0.4em;
}
.masthead__logo { margin: 0; color: #000; line-height: 0; }
.masthead__logo svg { display: block; width: min(460px, 100%); height: auto; }
.masthead__logo span { font-size: 1.4rem; line-height: 1.2; }
.club-cur { opacity: 0; animation: club-blink 1.06s steps(1) infinite; }
@keyframes club-blink { 50% { opacity: 1; } }
@media (prefers-reduced-motion: reduce) { .club-cur { animation: none; } }
