/* 300 Baud — the machine's own layer.
 *
 * Surfaces, ink, type scale and the studio footer come from the shared
 * logical-art.css. This file only adds what a modem panel needs.
 *
 * On the accent: the shared shell's rule is that a machine's accent has to be
 * earned by sampling the hardware, and one that cannot cite its accent uses
 * the neutral. The roster carries #f0a500 for this machine marked provisional,
 * with a note to sample a real Hayes Smartmodem status LED first. That has not
 * been done, so --la-instrument is left at the neutral until it has. An
 * invented amber would be a brand colour pretending to be evidence.
 */

body {
  margin: 0;
  background: var(--la-page);
  color: var(--la-ink);
  font-family: var(--la-font-ui);
  font-size: var(--la-text-base);
  line-height: var(--la-leading-body);
  -webkit-text-size-adjust: 100%;
}

.modem {
  max-width: var(--la-measure);
  margin: 0 auto;
  padding: var(--la-space-5) var(--la-space-4) var(--la-space-4);
}

.hero {
  margin-bottom: var(--la-space-5);
}

.eyebrow {
  margin: 0 0 var(--la-space-2);
  font-family: var(--la-font-mono);
  font-size: var(--la-text-xs);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--la-ink-faint);
}

h1 {
  margin: 0 0 var(--la-space-3);
  font-family: var(--la-font-display);
  font-size: var(--la-text-2xl, 2rem);
  line-height: var(--la-leading-tight);
  letter-spacing: -0.01em;
}

h2 {
  margin: 0 0 var(--la-space-2);
  font-size: var(--la-text-lg);
  line-height: var(--la-leading-tight);
}

.lede {
  margin: 0 0 var(--la-space-3);
  color: var(--la-ink-dim);
}

.panel {
  margin-bottom: var(--la-space-4);
  padding: var(--la-space-4);
  background: var(--la-card);
  border: 1px solid var(--la-hairline);
  border-radius: var(--la-radius);
}

.prose p {
  margin: 0 0 var(--la-space-3);
  color: var(--la-ink-dim);
}

.prose p:last-child {
  margin-bottom: 0;
}

.note {
  margin: 0 0 var(--la-space-3);
  font-size: var(--la-text-sm);
  color: var(--la-ink-faint);
}

/* ---- Controls ------------------------------------------------------------ */

.controls {
  display: flex;
  flex-wrap: wrap;
  gap: var(--la-space-3);
  margin-bottom: var(--la-space-3);
}

.field {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  flex: 1 1 20rem;
  min-width: 0;
}

.field-narrow {
  flex: 1 1 14rem;
}

.field > span {
  font-size: var(--la-text-xs);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--la-ink-faint);
}

input[type="text"],
select {
  width: 100%;
  padding: 0.6rem 0.7rem;
  background: var(--la-sunken);
  color: var(--la-ink);
  border: 1px solid var(--la-hairline-strong);
  border-radius: var(--la-radius-sm);
  font-family: var(--la-font-mono);
  font-size: var(--la-text-sm);
}

.buttons {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--la-space-3);
  margin-bottom: var(--la-space-3);
}

.btn {
  padding: 0.6rem 1.1rem;
  border-radius: var(--la-radius-sm);
  border: 1px solid var(--la-hairline-strong);
  background: var(--la-raised);
  color: var(--la-ink);
  font: inherit;
  font-size: var(--la-text-sm);
  cursor: pointer;
  transition: background var(--la-transition), border-color var(--la-transition);
}

.btn-primary {
  background: var(--la-instrument-solid);
  border-color: transparent;
  color: #fff;
}

.btn:hover {
  border-color: var(--la-instrument);
}

.toggle {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  font-size: var(--la-text-sm);
  color: var(--la-ink-dim);
}

/* ---- Scope --------------------------------------------------------------- */

#scope {
  display: block;
  width: 100%;
  height: auto;
  background: var(--la-sunken);
  border: 1px solid var(--la-hairline);
  border-radius: var(--la-radius-sm);
}

/* ---- Received ------------------------------------------------------------ */

.received {
  min-height: 4.5rem;
  margin: 0 0 var(--la-space-3);
  padding: var(--la-space-3);
  background: var(--la-sunken);
  border: 1px solid var(--la-hairline);
  border-radius: var(--la-radius-sm);
  font-family: var(--la-font-mono);
  font-size: var(--la-text-sm);
  white-space: pre-wrap;
  word-break: break-word;
  overflow-x: auto;
}

.readout {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
  gap: var(--la-space-3);
  margin: 0;
}

.readout dt {
  font-size: var(--la-text-xs);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--la-ink-faint);
}

.readout dd {
  margin: 0.2rem 0 0;
  font-family: var(--la-font-mono);
  font-size: var(--la-text-sm);
  color: var(--la-ink);
}

/* ---- Footer -------------------------------------------------------------- */

.foot {
  max-width: var(--la-measure);
  margin: 0 auto;
  padding: 0 var(--la-space-4) var(--la-space-5);
}

@media (prefers-reduced-motion: reduce) {
  .btn {
    transition: none;
  }
}

/* ---- The terminal --------------------------------------------------------
   80 columns, always fitting the width available, never scrolling sideways.
   The font size is set from JS because the exact advance width of a monospace
   glyph varies between the faces in the stack, so guessing a ch-to-em ratio
   in CSS gets it wrong for somebody. The clamp here is only a sane starting
   point before that runs. */

.crt {
  position: relative;
  margin-bottom: var(--la-space-3);
  padding: var(--la-space-3);
  background: #000;
  border: 1px solid var(--la-hairline-strong);
  border-radius: var(--la-radius-sm);
  overflow: hidden;
  cursor: text;
}

.crt:focus,
.crt:focus-within {
  outline: 2px solid var(--la-instrument);
  outline-offset: 2px;
}

/* The terminal's own face.
 *
 * Everything else on the page can take whatever monospace the device offers,
 * but the screen cannot. A BBS draws its frames out of CP437 box-drawing
 * characters, and those only join into continuous rules if the glyph is as
 * tall as the line box. Fonts differ on that: several common fallbacks draw a
 * vertical bar noticeably shorter than a full line, and the frame comes out as
 * a dashed line with a nick at every row boundary. Setting line-height to 1 is
 * necessary but not sufficient, which is why that fix alone did not hold.
 *
 * So the face is not left to chance. This is DejaVu Sans Mono subset to
 * exactly the 222 glyphs the terminal can draw (ASCII plus the CP437 high
 * range) and nothing else, which is why it is under nine kilobytes. Its
 * vertical bar measures 1.188 em against a 1 em row, so it laps into the row
 * below rather than falling short, and the rules join.
 *
 * font-display is block rather than swap on purpose: swapping mid-render would
 * show a screenful of broken frames first and then repair it, which is worse
 * than a moment of nothing.
 */
@font-face {
  font-family: "CP437";
  src: url("/fonts/cp437.woff2") format("woff2");
  font-display: block;
  font-weight: 400;
  font-style: normal;
}

.terminal {
  font-family: "CP437", var(--la-font-mono);
  font-size: clamp(0.42rem, 2.1vw, 0.82rem);
  /* Exactly one, because box-drawing characters only join up when the line
     box is the character cell. Any leading at all and every vertical rule in
     a BBS screen comes out as a dashed line. A DOS text screen had none. */
  line-height: 1;
  white-space: pre;
  width: 80ch;
  max-width: 80ch;
  min-height: 24em;
  color: #aaa;
  background: #000;
}

.terminal .trow {
  height: 1em;
}

/* The cursor is a cell, not a caret, because that is what a terminal had. */
.terminal .cur {
  background: #aaa;
  color: #000;
}

.crt:focus .terminal .cur,
.crt:focus-within .terminal .cur {
  animation: blink 1.06s steps(1, end) infinite;
}

@keyframes blink {
  0%, 50% { background: #aaa; color: #000; }
  50.01%, 100% { background: transparent; color: inherit; }
}

@media (prefers-reduced-motion: reduce) {
  .crt:focus .terminal .cur,
  .crt:focus-within .terminal .cur {
    animation: none;
  }
}

/* The real input, invisible but present, so a phone opens its keyboard.
   box-sizing matters here: without it the input measured wider than the box
   it sits in and made the terminal report horizontal overflow even though
   the overflow was clipped and nothing looked wrong. */
.keyboard {
  position: absolute;
  inset: 0;
  box-sizing: border-box;
  width: 100%;
  height: 100%;
  max-width: 100%;
  padding: 0;
  border: 0;
  background: transparent;
  color: transparent;
  caret-color: transparent;
  font-size: 16px; /* under 16px, iOS zooms the page on focus */
  opacity: 0;
  cursor: text;
}

.hint kbd {
  padding: 0.1em 0.35em;
  background: var(--la-sunken);
  border: 1px solid var(--la-hairline);
  border-radius: 0.25rem;
  font-family: var(--la-font-mono);
  font-size: 0.9em;
}

/* ---- The rack ------------------------------------------------------------ */

.rack {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--la-space-3);
  margin-bottom: var(--la-space-3);
}

.lamp {
  padding: 0.3rem 0.6rem;
  border: 1px solid var(--la-hairline-strong);
  border-radius: var(--la-radius-sm);
  font-family: var(--la-font-mono);
  font-size: var(--la-text-xs);
  letter-spacing: 0.06em;
  color: var(--la-ink-faint);
}

.lamp[data-on="true"] {
  color: var(--la-page);
  background: var(--la-instrument);
  border-color: transparent;
}

.btn:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}

/* ---- The directory ------------------------------------------------------- */

.directory {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr));
  gap: var(--la-space-3);
  margin-bottom: var(--la-space-3);
}

.directory .btn {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  align-items: flex-start;
  text-align: left;
}

.directory .btn span {
  font-family: var(--la-font-mono);
  font-size: var(--la-text-xs);
  color: var(--la-ink-faint);
}

/* ---- Transfer ------------------------------------------------------------ */

.transfer {
  display: flex;
  align-items: center;
  gap: var(--la-space-3);
  font-size: var(--la-text-sm);
  color: var(--la-ink-dim);
}

.transfer progress {
  flex: 1 1 auto;
  min-width: 8rem;
}

code {
  padding: 0.1em 0.35em;
  background: var(--la-sunken);
  border: 1px solid var(--la-hairline);
  border-radius: 0.25rem;
  font-family: var(--la-font-mono);
  font-size: 0.9em;
}

/* Questions, glossary and sources are styled by the shared shell now, as
   .la-faq / .la-glossary / .la-sources. Only the link colour is local. */

a {
  color: var(--la-ink);
  text-decoration: underline;
  text-underline-offset: 0.18em;
}

a:hover {
  color: var(--la-instrument);
}

/* ---- Tables in the notebook ---------------------------------------------- */

.table-scroll {
  overflow-x: auto;
  margin-bottom: var(--la-space-3);
}

.table-scroll table {
  border-collapse: collapse;
  font-family: var(--la-font-mono);
  font-size: var(--la-text-sm);
}

.table-scroll th,
.table-scroll td {
  padding: 0.35rem 0.9rem 0.35rem 0;
  text-align: left;
  border-bottom: 1px solid var(--la-hairline);
  color: var(--la-ink-dim);
}

.table-scroll th {
  color: var(--la-ink-faint);
  font-weight: 600;
  font-size: var(--la-text-xs);
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

/* SD and RD, the lamps that flickered as data moved. */
.lamp-tiny {
  padding: 0.3rem 0.5rem;
  min-width: 2.6rem;
  text-align: center;
}

/* The form exists only to give a soft keyboard a reason to offer a return
   key. It must not take up any space of its own. */
.keyform {
  position: absolute;
  inset: 0;
  margin: 0;
  overflow: hidden;
}

/* Line 25, which belonged to the terminal program rather than to the board.
   Inverse video, the way every DOS comms program drew it. */
.statusline {
  font-family: var(--la-font-mono);
  font-size: inherit;
  line-height: 1;
  white-space: pre;
  width: 80ch;
  max-width: 80ch;
  margin-top: 0.4em;
  color: #000;
  background: #aaa;
}

/* Available to a screen reader, absent from the page. */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* ---- The modem itself -----------------------------------------------------
   A Hayes Smartmodem was a flat dark box with a row of lamps along the front:
   HS, AA, CD, OH, RD, SD, TR, MR. The lamps were red, because through the
   early eighties a red gallium-arsenide-phosphide LED was what an indicator
   lamp WAS; green and yellow were newer and more expensive, and blue did not
   arrive in a usable form until the nineties.

   That red is used here for the lamps only, not as the machine's accent. The
   shell's rule is that an accent has to be earned by sampling the hardware,
   and reasoning from what LEDs of the period were is not the same as taking a
   value off a photograph of a real unit. The page chrome stays neutral until
   somebody does that. */

.modem-panel {
  margin-bottom: var(--la-space-3);
}

.panel-face {
  display: flex;
  align-items: center;
  gap: var(--la-space-4);
  flex-wrap: wrap;
  padding: var(--la-space-3) var(--la-space-4);
  background: linear-gradient(180deg, #17191b 0%, #0e1011 100%);
  border: 1px solid var(--la-hairline-strong);
  border-radius: var(--la-radius-sm);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05);
}

.panel-brand {
  margin: 0;
  font-family: var(--la-font-mono);
  font-size: var(--la-text-xs);
  letter-spacing: 0.22em;
  color: var(--la-ink-dim);
  line-height: 1.5;
}

.panel-brand span {
  display: block;
  font-size: 0.82em;
  letter-spacing: 0.16em;
  color: var(--la-ink-faint);
}

.lamps {
  display: flex;
  gap: clamp(0.7rem, 3.2vw, 1.5rem);
  list-style: none;
  margin: 0;
  padding: 0;
}

.lamps li {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.35rem;
}

.led {
  width: 0.62rem;
  height: 0.62rem;
  border-radius: 50%;
  background: #3a1512;
  box-shadow: inset 0 0 2px rgba(0, 0, 0, 0.9);
  transition: background 60ms linear, box-shadow 60ms linear;
}

.led[data-on="true"] {
  background: #ff4436;
  box-shadow: 0 0 6px rgba(255, 68, 54, 0.75), inset 0 0 2px rgba(255, 200, 190, 0.6);
}

.led-label {
  font-family: var(--la-font-mono);
  font-size: 0.62rem;
  letter-spacing: 0.06em;
  color: var(--la-ink-faint);
}

.panel-key {
  margin-top: var(--la-space-2);
  font-size: var(--la-text-sm);
}

.panel-key summary {
  color: var(--la-ink-faint);
  cursor: pointer;
}

.panel-key summary:hover {
  color: var(--la-instrument);
}

.panel-key dl {
  margin-top: var(--la-space-2);
}

@media (prefers-reduced-motion: reduce) {
  .led { transition: none; }
}

/* ---- Diagrams -------------------------------------------------------------
   Inline SVG so there is nothing to load and nothing for a strict CSP to
   refuse. Everything is drawn in currentColor or the shell's own tokens, so
   the figures follow the page rather than carrying their own palette. */

.figure {
  margin: 0 0 var(--la-space-4);
  padding: var(--la-space-3);
  background: var(--la-sunken);
  border: 1px solid var(--la-hairline);
  border-radius: var(--la-radius-sm);
  overflow-x: auto;
}

.dia {
  display: block;
  width: 100%;
  min-width: 30rem;
  height: auto;
  color: var(--la-ink-dim);
  font-family: var(--la-font-mono);
  font-size: 11px;
}

.dia text { fill: var(--la-ink-dim); }
.dia .dia-dim { fill: var(--la-ink-faint); }
.dia .dia-note { fill: var(--la-ink); }
.dia .dia-tick text { fill: var(--la-ink-faint); }

.dia .dia-axis line { stroke: var(--la-hairline-strong); stroke-width: 1; }
.dia .dia-axis text { fill: var(--la-ink-faint); }

.dia .dia-wave {
  fill: none;
  stroke: var(--la-instrument);
  stroke-width: 2;
  stroke-linejoin: round;
}

.dia .dia-bar rect { fill: var(--la-raised); stroke: var(--la-hairline-strong); }
.dia .dia-bar .dia-bar-quiet { fill: var(--la-page); }
.dia .dia-bar .dia-bar-live { fill: var(--la-instrument-solid); }

.dia .dia-mark { stroke: var(--la-instrument); stroke-width: 2; }

.dia .dia-tone line { stroke: var(--la-instrument); stroke-width: 2; }
.dia .dia-tone text { fill: var(--la-ink); }

.dia .dia-field rect,
.dia .dia-field polygon { fill: var(--la-raised); stroke: var(--la-hairline-strong); }
.dia .dia-field .dia-field-wide { fill: var(--la-page); }
.dia .dia-field text { fill: var(--la-ink); text-anchor: middle; }

.dia .dia-msg line { stroke: var(--la-instrument); stroke-width: 1.5; }
.dia .dia-msg text { fill: var(--la-ink-dim); }

/* ---------------------------------------------------------------------------
   The speed ladder.

   The table is arithmetic and the player is partly a reconstruction, so the
   two are visually separated: the honesty note sits directly under the picker
   rather than in a footnote somebody can miss.
   --------------------------------------------------------------------------- */

.ladder-scroll {
  overflow-x: auto;
  margin-bottom: var(--la-space-4);
}

.ladder-scroll:focus-visible {
  outline: 2px solid var(--la-instrument);
  outline-offset: 2px;
}

.ladder-table {
  width: 100%;
  min-width: 26rem;
  border-collapse: collapse;
  font-variant-numeric: tabular-nums;
}

.ladder-table th,
.ladder-table td {
  padding: var(--la-space-2) var(--la-space-2);
  border-bottom: 1px solid var(--la-hairline);
  text-align: right;
}

.ladder-table thead th {
  color: var(--la-ink-faint);
  font-weight: 400;
  white-space: nowrap;
}

.ladder-table tbody th,
.ladder-table thead th:first-child { text-align: left; }
.ladder-table tbody th { font-weight: 600; color: var(--la-ink); }

.ladder-picker {
  display: flex;
  flex-wrap: wrap;
  gap: var(--la-space-2);
  margin-bottom: var(--la-space-3);
}

.ladder-picker button,
.ladder-controls button {
  font: inherit;
  font-family: var(--la-font-mono);
  color: var(--la-ink);
  background: var(--la-raised);
  border: 1px solid var(--la-hairline-strong);
  border-radius: var(--la-radius-sm);
  padding: 0.55rem 0.9rem;
  cursor: pointer;
  /* WCAG 2.5.8 wants a comfortable target on a coarse pointer. */
  min-height: 44px;
}

.ladder-picker button[aria-pressed="true"] {
  background: var(--la-sunken);
  border-color: var(--la-instrument);
  color: var(--la-ink);
}

.ladder-picker button:focus-visible,
.ladder-controls button:focus-visible {
  outline: 2px solid var(--la-instrument);
  outline-offset: 2px;
}

.ladder-detail { margin-top: var(--la-space-3); }

.ladder-note { margin: 0 0 var(--la-space-2); color: var(--la-ink-dim); }

.ladder-honesty {
  margin: 0 0 var(--la-space-3);
  padding: var(--la-space-2) var(--la-space-3);
  background: var(--la-sunken);
  border-left: 2px solid var(--la-hairline-strong);
  color: var(--la-ink-faint);
  font-size: 0.92em;
}

.ladder-controls {
  display: flex;
  flex-wrap: wrap;
  gap: var(--la-space-2);
  margin-bottom: var(--la-space-3);
}

.ladder-phases {
  margin: 0 0 var(--la-space-3);
  padding-left: 1.4rem;
  color: var(--la-ink-faint);
  font-family: var(--la-font-mono);
  font-size: 0.86em;
  line-height: 1.7;
}

.ladder-phases li[data-active="true"] {
  color: var(--la-ink);
}

.ladder-demo {
  /* Deliberately NOT the .terminal class. That class pins the width to 80ch,
     which is right for an eighty-column screen and wrong for a preview: it
     forced this box to 514px inside a 292px column and made the whole page
     scroll sideways on a phone. It only wants the face, not the geometry. */
  font-family: "CP437", var(--la-font-mono);
  max-width: 100%;
  margin: 0;
  padding: var(--la-space-3);
  min-height: 13em;
  background: #000;
  color: #aaaaaa;
  border: 1px solid var(--la-hairline-strong);
  border-radius: var(--la-radius-sm);
  font-size: clamp(0.6rem, 2.4vw, 0.8rem);
  line-height: 1.25;
  white-space: pre;
  overflow-x: auto;
}

/* Build-time ANSI art: the real renderer's output, frozen into the page.
   Same face as the terminal and the same leading rule, because box drawing
   only joins under both. */
.ansi-art {
  margin: 0 0 var(--la-space-4);
  padding: var(--la-space-3);
  background: #000;
  border: 1px solid var(--la-hairline-strong);
  border-radius: var(--la-radius-sm);
  font-family: "CP437", var(--la-font-mono);
  font-size: clamp(0.5rem, 1.9vw, 0.78rem);
  line-height: 1;
  white-space: pre;
  overflow-x: auto;
  max-width: 100%;
}

/* The picture converter. */
.converter { margin-top: var(--la-space-3); }
.converter[data-over="true"] { outline: 2px dashed var(--la-instrument); outline-offset: 6px; }

.conv-controls {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--la-space-3);
  margin-bottom: var(--la-space-3);
}

/* The file input itself is unstylable across browsers, so the label is the
   button and the input is hidden inside it. Keeping the input in the label
   rather than removing it from the flow is what preserves keyboard access. */
.conv-file { position: relative; overflow: hidden; cursor: pointer; }
.conv-file input {
  position: absolute;
  inset: 0;
  opacity: 0;
  cursor: pointer;
}
.conv-file:focus-within { outline: 2px solid var(--la-instrument); outline-offset: 2px; }

.conv-screen { min-height: 12em; }

/* Hero illustrations. Drawings rather than photographs, and captioned as such,
   because a page that keeps promising its claims are checkable should not put
   a generated picture next to them without saying what it is. */
.hero-figure {
  margin: var(--la-space-3) 0 var(--la-space-4);
}

.hero-figure img {
  display: block;
  width: 100%;
  height: auto;
  border: 1px solid var(--la-hairline);
  border-radius: var(--la-radius-sm);
}

.hero-figure figcaption {
  margin-top: var(--la-space-2);
  font-size: var(--la-text-xs);
  color: var(--la-ink-faint);
}

.conv-exports { align-items: baseline; }
.conv-label {
  font-size: var(--la-text-xs);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--la-ink-faint);
}
.conv-controls button:disabled { opacity: 0.45; cursor: not-allowed; }
