/* THE TERMINAL — a console still running in a building nobody maintains.
 *
 * "The system is still running. Nobody is maintaining it."
 *
 * Ported from Brennan's dystopian theme, which is where this contract came
 * from. Two things came across whole and are the reason it reads as a place
 * rather than a palette: MATERIALS declared once and reused everywhere
 * (concrete, board-form, aggregate, steel, hazard tape, phosphor), and the
 * fact that the room owns its own frame — see templates/rooms/dystopian/.
 *
 * Everything runs off --dystopian-spd, written by room-weather.js from the
 * reader's dial. At Clean Signal the tear is a rumour; at The Oracle Answers
 * Anyway it will not hold still.
 */

[data-room="dystopian"] {
  --dystopian-spd: 6s;          /* room-weather.js overwrites from the dial */
  --dystopian-bar-spd: 3s;

  /* --- materials, not colours. Declared once, reused in every slot. ------ */
  --dy-concrete: linear-gradient(180deg, #141618 0%, #0e1011 58%, #090a0b 100%);
  /* Board-formed: the shutter lines are still in it. */
  --dy-form: repeating-linear-gradient(180deg,
              transparent 0 33px,
              rgba(0, 0, 0, .55) 33px 35px,
              rgba(255, 255, 255, .025) 35px 36px);
  /* Aggregate — the stones in the pour, catching light at four fixed points. */
  --dy-aggregate:
    radial-gradient(circle at 21% 37%, rgba(255,255,255,.035) 0 1.1px, transparent 2px),
    radial-gradient(circle at 67% 19%, rgba(255,255,255,.028) 0 .9px, transparent 1.8px),
    radial-gradient(circle at 44% 78%, rgba(0,0,0,.40)     0 1.3px, transparent 2.2px),
    radial-gradient(circle at 88% 63%, rgba(255,255,255,.022) 0 .8px, transparent 1.6px);
  --dy-steel: linear-gradient(180deg, #26292c 0%, #181b1d 55%, #101213 100%);
  --dy-hazard: repeating-linear-gradient(45deg, #c8a000 0 7px, #151515 7px 14px);
  --dy-bolt: #43484c;
  --dy-phos: #00c437;
}

/* Slot 2 — ground. Concrete, board-formed, with the aggregate showing. */
[data-room="dystopian"] body {
  background-color: var(--syn-void);
  background-image: var(--dy-form), var(--dy-aggregate), var(--dy-concrete);
  background-attachment: fixed;
}

/* Burned into the phosphor. Fixed, behind the reading, never interactive —
   the frame template mounts both; neither takes a pointer event. */
[data-room="dystopian"] .dy-crt,
[data-room="dystopian"] .dy-burn {
  pointer-events: none;
  z-index: -1;
}
[data-room="dystopian"] .dy-crt {
  background-image: repeating-linear-gradient(180deg,
    rgba(0, 0, 0, .28) 0 1px, transparent 1px 3px);
}
/* An interface left on for years leaves its own ghost. Static, not animated:
   burn-in does not move, that is what makes it burn-in. */
[data-room="dystopian"] .dy-burn {
  background-image: radial-gradient(ellipse at 50% 12%, rgba(0, 196, 55, .045), transparent 58%);
}

/* Slot 3 — the rule. A rack rail, bolted through. */
[data-room="dystopian"] hr,
[data-room="dystopian"] .syn-rule {
  border-color: transparent;
  background-image: var(--dy-steel),
    radial-gradient(circle at 6px 50%, var(--dy-bolt) 0 1.6px, transparent 2.4px),
    radial-gradient(circle at calc(100% - 6px) 50%, var(--dy-bolt) 0 1.6px, transparent 2.4px);
}

/* Slot 4 — the masthead is rack steel screwed to the wall. */
[data-room="dystopian"] .syn-header {
  background-color: #0c0d0f;
  background-image: var(--dy-steel);
  box-shadow: inset 0 -1px 0 rgba(0, 196, 55, .22), 0 2px 18px rgba(0, 0, 0, .65);
}
[data-room="dystopian"] .syn-mark,
[data-room="dystopian"] .syn-nav-link {
  font-family: var(--syn-mono);
  letter-spacing: .06em;
  text-transform: uppercase;
}
[data-room="dystopian"] .syn-sigil {
  color: var(--dy-phos);
  text-shadow: 0 0 6px rgba(0, 196, 55, .55);
}

/* The room's own frame furniture (templates/rooms/dystopian/base.html). */
[data-room="dystopian"] .dy-status {
  font-family: var(--syn-mono);
  font-size: var(--t-2xs);
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--dy-phos);
  background: #070809;
  border-bottom: 1px solid var(--syn-border);
}
[data-room="dystopian"] .dy-status-sep,
[data-room="dystopian"] .dy-status-note { color: var(--syn-text-mute); }
[data-room="dystopian"] .dy-status-lamp {
  background: var(--dy-phos);
  box-shadow: 0 0 7px var(--dy-phos);
  border-radius: 50%;
  animation: dy-lamp calc(var(--dystopian-spd) * 0.7) steps(1, end) infinite;
}
[data-room="dystopian"] .dy-status-caret {
  background: var(--dy-phos);
  animation: dy-caret calc(var(--dystopian-spd) * 0.18) steps(1, end) infinite;
}
[data-room="dystopian"] .dy-hazard { background-image: var(--dy-hazard); }
/* The plant line — the machine's own report on itself, at the foot of the
   screen, and the mirror of .dy-status at the head of it. It was set in the
   mono face at --t-2xs in --syn-text-mute and left flush against the viewport
   edge, which read as a caption somebody forgot to style.
   A Hercules card drove one colour at 720x348 through a 9x14 character cell
   and was famous for how SHARP it was: bright phosphor on black, no colour,
   every glyph on the grid. So: the room's own display face (VT323) at a size
   where a bitmap face can show its cell, phosphor rather than grey — this is
   the machine talking, it should not be the faintest thing on the page — and
   the dot bloom a phosphor dot actually has. Centred, on a band with a rule
   top and bottom, in the idiom .dy-readout already uses.
   It stays aria-hidden in the template: set dressing, not information. */
[data-room="dystopian"] .dy-plant-line {
  font-family: var(--syn-display);
  font-size: var(--t-lg);
  line-height: 1.15;
  letter-spacing: .14em;
  word-spacing: .22em;
  text-transform: uppercase;
  text-align: center;
  color: var(--dy-phos);
  /* The bloom: a tight core and a wide halo, the way a phosphor dot spreads
     into the glass rather than the even blur of a drop shadow. */
  text-shadow: 0 0 5px rgba(0, 196, 55, .55), 0 0 18px rgba(0, 196, 55, .22);
  background-color: #060708;
  /* The character cell's own scan, one line on two off, as .dy-readout has. */
  background-image: repeating-linear-gradient(180deg,
    transparent 0 2px, rgba(0, 0, 0, .40) 2px 3px);
  border-top: 1px solid rgba(0, 196, 55, .30);
  border-bottom: 1px solid rgba(0, 196, 55, .30);
  box-shadow: inset 0 0 30px rgba(0, 196, 55, .07);
}

/* Slot 5 — a card is a panel bolted through at the corners. Three sides only:
   the fourth is `border-left: 3px solid var(--p-accent)`, the planet's own
   colour, and `border-color` is a shorthand that would grey it out. */
[data-room="dystopian"] .syn-23-section,
[data-room="dystopian"] .syn-reading,
[data-room="dystopian"] details {
  background-color: #0c0d0f;
  background-image:
    radial-gradient(circle at 11px 11px, var(--dy-bolt) 0 2.2px, #0d0f10 3.2px, transparent 4.4px),
    radial-gradient(circle at calc(100% - 11px) 11px, var(--dy-bolt) 0 2.2px, #0d0f10 3.2px, transparent 4.4px),
    var(--dy-form);
  border-top-color: var(--syn-border);
  border-right-color: var(--syn-border);
  border-bottom-color: var(--syn-border);
}

/* Slot 6 — prose. A terminal renders text; it does not set it. */
[data-room="dystopian"] .syn-passage,
[data-room="dystopian"] .syn-book-reader-body { color: var(--syn-text); }

/* Slot 8 — marks. Phosphor, with the red-green fringe of a misconverged tube. */
[data-room="dystopian"] .syn-sig,
[data-room="dystopian"] .syn-icon {
  color: var(--dy-phos);
  text-shadow: -1px 0 rgba(139, 0, 0, .55), 1px 0 rgba(0, 196, 55, .45);
}

/* Slot 9 — controls. Panel-mounted, and they light when live. */
[data-room="dystopian"] .syn-btn {
  font-family: var(--syn-mono);
  text-transform: uppercase;
  letter-spacing: .08em;
  border-color: var(--syn-border-hi);
  background-image: var(--dy-steel);
}
[data-room="dystopian"] .syn-btn:hover {
  border-color: var(--dy-phos);
  box-shadow: inset 0 0 14px rgba(0, 196, 55, .16), 0 0 10px rgba(0, 196, 55, .2);
}

/* Slot 10 — chips. Hazard tape on anything that was ever dangerous. */
[data-room="dystopian"] .syn-thread-pill:not([class*="--"]),
[data-room="dystopian"] .syn-ref {
  font-family: var(--syn-mono);
  border-color: rgba(200, 160, 0, .45);
  background-color: rgba(200, 160, 0, .07);
}

/* Slot 12 — the loading mark is a scan bar, not a wheel. */
[data-room="dystopian"] .syn-drawing {
  background-image: radial-gradient(ellipse at center, rgba(0, 196, 55, .08), transparent 62%);
}
[data-room="dystopian"] .syn-drawing-arc {
  stroke: var(--dy-phos);
  animation-duration: var(--dystopian-bar-spd);
}

/* Slot 13 — ambient. A tear, and a lamp that is not quite steady.
   Both are mostly OFF: the frame is intact for 96% of the cycle and torn for
   the rest, which is what makes it read as a fault rather than a texture. A
   glitch that is always happening is just a pattern. */
@keyframes dy-tear {
  0%, 96%  { opacity: 0; transform: translate3d(0, 0, 0); }
  97%      { opacity: .5; transform: translate3d(-2px, 1px, 0); }
  98%      { opacity: .4; transform: translate3d(2px, -1px, 0); }
  99%      { opacity: 0;  transform: translate3d(0, 0, 0); }
}
@keyframes dy-lamp  { 0%, 88% { opacity: 1; } 89%, 94% { opacity: .25; } 95% { opacity: 1; } }
@keyframes dy-caret { 0%, 49% { opacity: 1; } 50%, 100% { opacity: 0; } }

[data-room="dystopian"] .dy-crt::after {
  content: "";
  background-image: linear-gradient(180deg,
    transparent, rgba(0, 196, 55, .10) 45%, rgba(139, 0, 0, .08) 55%, transparent);
  animation: dy-tear var(--dystopian-spd) steps(100, end) infinite;
}

/* Rule I as it now stands: a room may set geometry for ITS OWN furniture, and
   must not break the phone. These elements belong to this room and exist
   nowhere else, so nothing else can be moved by them. */
[data-room="dystopian"] .dy-crt,
[data-room="dystopian"] .dy-burn {
  position: fixed;
  inset: 0;
}
[data-room="dystopian"] .dy-crt::after {
  position: absolute;
  inset: 0;
}
[data-room="dystopian"] .dy-status {
  display: flex;
  align-items: center;
  gap: .5em;
  padding: .3rem .9rem;
}
[data-room="dystopian"] .dy-status-lamp { width: .45em; height: .45em; }
[data-room="dystopian"] .dy-status-caret { width: .5em; height: 1em; margin-left: auto; }
[data-room="dystopian"] .dy-hazard { height: 3px; }
/* Full-bleed like the status bar it mirrors, so the page is bracketed by two
   bands of machine output; the padding is what keeps the text off the glass
   edge rather than a max-width, which is how a real status line is drawn. */
[data-room="dystopian"] .dy-plant-line {
  margin: 0;
  padding: .5rem 1.1rem .42rem;
}

/* Slot 14 — reduced motion. The terminal stays ON; it stops failing.
   !important because the state variants above out-specify a bare rule. */
@media (prefers-reduced-motion: reduce) {
  [data-room="dystopian"] .dy-crt::after { animation: none !important; opacity: 0 !important; }
  [data-room="dystopian"] .dy-status-lamp { animation: none !important; opacity: 1 !important; }
  [data-room="dystopian"] .dy-status-caret { animation: none !important; opacity: 1 !important; }
  [data-room="dystopian"] .syn-drawing-arc { animation: none !important; }
}

/* Tear bars, injected and removed by js/room-glitch.js. `screen` so they add
   light across the reading rather than painting over it, and above the weather
   but below nothing else — a tear is on the glass, not in the room. */
.syn-glitch-bar {
  position: fixed;
  left: 0;
  right: 0;
  pointer-events: none;
  z-index: 200;
  mix-blend-mode: screen;
}

/* The rest of what js/room-glitch.js injects: a hazard ring round a control,
   a phosphor bloom, a block cursor, a copy of a label for the sync roll and
   the ghost, corner marks for the radius collapse, and dead pixels.
   Unscoped for the same reason as the tear bar above — the engine belongs to
   any room that declares `glitch: true`, and this is the only sheet that
   does. Every one is FIXED: damage to a tube is on the glass, not in the
   document, so none of it can reflow the page or take a pointer. The rest of
   each node — where it is, how big, what colour — is written inline by the
   engine from the target's own rect and the room's own inks. */
.dy-fx {
  position: fixed;
  pointer-events: none;
  z-index: 200;
}
/* The room's real hazard tape, cut to a ring by a clip-path the engine
   computes: a border on the control itself would be a reflow. */
.dy-fx-tape {
  background-image: var(--dy-hazard);
  opacity: .2;
}
/* These two swell and die rather than snapping, which is what makes them read
   as phosphor and not as a border being toggled. */
.dy-fx-glow,
.dy-fx-copy { transition: opacity .18s linear; }
.dy-fx-copy {
  white-space: nowrap;
  overflow: hidden;
}
.dy-fx-caret { animation: dy-caret .5s steps(1, end) infinite; }
.dy-fx-dot { border-radius: 50%; }

@media (prefers-reduced-motion: reduce) {
  /* Belt and braces: the engine returns early under reduced motion and never
     injects any of this, so this rule should be unreachable. Rule VI does not
     take "unreachable" for an answer, and neither should anyone reading it. */
  .dy-fx-caret { animation: none !important; opacity: 1 !important; }
}

/* THE OWNED PAGE — templates/rooms/dystopian/oracle/horoscope.html.
   The horoscope as a system readout. These classes exist in no other theme
   and nowhere in the site sheet, so they are the Terminal's own furniture and
   may be laid out freely (Rule I is ownership). */
[data-room="dystopian"] .dy-readout {
  font-family: var(--syn-mono);
  font-size: var(--t-sm);
  line-height: 1.55;
  color: var(--syn-text);
  background: #070809;
  background-image: repeating-linear-gradient(180deg, transparent 0 2px, rgba(0, 0, 0, .18) 2px 3px);
  border-top: 1px solid var(--syn-border);
  border-bottom: 1px solid var(--syn-border);
  box-shadow: inset 0 0 40px rgba(0, 196, 55, .06);
  padding: .9rem 1.1rem;
  margin: 0 0 1.4rem;
  display: grid;
  gap: .25rem;
}
[data-room="dystopian"] .dy-readout-line {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: .4em 1.2em;
}
[data-room="dystopian"] .dy-readout-key {
  color: var(--dy-phos);
  letter-spacing: .16em;
  font-size: var(--t-2xs);
  min-width: 5.5em;
  text-shadow: 0 0 5px rgba(0, 196, 55, .45);
}
[data-room="dystopian"] .dy-readout-val { color: var(--syn-text); }
[data-room="dystopian"] .dy-readout-dim { color: var(--syn-text-mute); }
[data-room="dystopian"] .dy-readout-line--log .dy-readout-val { color: var(--syn-text-dim); }
[data-room="dystopian"] .dy-readout-line--prompt { margin-top: .3rem; }
[data-room="dystopian"] .dy-readout-caret {
  display: inline-block;
  width: .55em;
  height: 1em;
  margin-left: .25em;
  background: var(--dy-phos);
  animation: dy-caret calc(var(--dystopian-spd) * 0.18) steps(1, end) infinite;
}

/* The week as a seven-slot buffer: the house strip, box-drawn.

   THE BUFFER IS THE SCREEN'S WIDTH, not the house's. It was max-width 560px
   — the house's own measure, carried in rather than chosen — while the
   readout band above it and every reading below it run the screen's full
   648px. A console prints every line from the same column; a strip inset
   44px inside that column is not a narrower object, it is the same object
   in the wrong place.

   And the rule is drawn TO the buffer. The box characters are a fixed
   count, so they were only ever right at one window: 44 of them measure
   450px, which left a quarter of a 560px buffer with no rule under it on a
   desk and overflowed a phone. The corners are now their own characters at
   the two ends and the run between them is clipped to whatever is left, so
   the box closes at every width. .dy-buffer, .dy-buffer-rule and
   .dy-buffer-run exist in no other room and nowhere in the site sheet, so
   they are the Terminal's own furniture and may be laid out freely (Rule I
   is ownership). */
[data-room="dystopian"] .dy-buffer { margin: 0 auto 1.4rem; max-width: 100%; }
[data-room="dystopian"] .dy-buffer-rule {
  font-family: var(--syn-mono);
  font-size: var(--t-2xs);
  color: var(--syn-text-mute);
  white-space: pre;
  overflow: hidden;
  line-height: 1;
  display: flex;
}
[data-room="dystopian"] .dy-buffer-run {
  flex: 1 1 0;
  min-width: 0;
  overflow: hidden;
}

/* ======================================================================
   ONE SCREEN, ONE MEASURE — the only place Rule I lets a room move the
   site's own furniture, and the reason the rule has that exception.

   Everything this machine prints starts at the same column. The readout at
   the head of the page and the seven readings under it both run the
   screen's full 648px; the house draws the hour panel, the week, the
   correspondences, the card of the day, the season line and the page's
   whole foot at a max-width of 560px, so each of them came out inset 44px
   on both sides. Two margins on one screen.

   The brief for this repair recorded the Terminal's column as 451→974 and
   its blocks as WIDER than it. That figure is not a column: it is the text
   inside .syn-horo-hour's own 1.1rem padding and 1px border (560 − 2×18.6
   = 523), which is what a probe hunting for the first paragraph on the page
   finds when a room has replaced the head with a readout that contains no
   paragraph at all. The Terminal's column is 389→1037, the screen, and its
   blocks are narrower than it exactly as in every other room — measured,
   not assumed.

   These blocks KEEP their padding. This room leaves the house's panels as
   panels — a console shows a bordered field, and nothing here takes their
   border, fill or radius away — so the padding is the field's own and is
   still what holds the text off its edge.

   600px is where it starts to matter and is therefore where it is fixed:
   the screen is wider than 560px only above 592px of viewport.
   ====================================================================== */
@media (min-width: 600px) {
  [data-room="dystopian"] .syn-horo-hour,
  [data-room="dystopian"] .syn-harmony,
  [data-room="dystopian"] .syn-week,
  [data-room="dystopian"] .syn-corr,
  [data-room="dystopian"] .syn-yours,
  [data-room="dystopian"] .syn-season-line,
  [data-room="dystopian"] .syn-wheelyear,
  [data-room="dystopian"] .syn-letter,
  [data-room="dystopian"] .syn-horo-chartlink {
    max-width: 100%;
    margin-left: 0;
    margin-right: 0;
  }
}

@media (prefers-reduced-motion: reduce) {
  [data-room="dystopian"] .dy-readout-caret { animation: none !important; opacity: 1 !important; }
}
