/* =====================================================================
   quiet — the premises.

   two colours and a ground. the ground is near-black, the ink is a cold
   dim grey-blue, and the accent is a lit fluorescent blue-white that only
   ever means one thing: the light on four, and by extension the claim
   itself. it is used sparingly and at full strength, never tinted down
   into a third neutral.
   ===================================================================== */

:root{
  --paper:#06080b;                       /* the ground */
  --ink:#a8bccd;                         /* the record. cold, dim, readable */
  --dim:#69808f;                         /* captions, furniture, the rail */
  --lit:#6fd9ff;                         /* the accent. emitted, never printed */
  --hair:rgba(168,188,205,.17);
  --mono:"Courier New", Courier, ui-monospace, monospace;
  /* the figures need a face that actually ships the block elements at full
     cell height. Courier New has no ░▒▓ of its own, so the browser
     substitutes per-glyph from a fallback with different metrics and the
     drawing comes apart into horizontal stripes. Consolas and Cascadia
     both draw them properly and are on every Windows machine. */
  --figure:"Cascadia Mono", Consolas, "DejaVu Sans Mono", Menlo, "Courier New", monospace;
}

*{box-sizing:border-box}
/* html carries the ground too: while the boot hides <body>, the viewport
   shows the html background, and unstyled that is white — a worse flash
   than the one being fixed. */
html{-webkit-text-size-adjust:100%;scroll-behavior:smooth;background:var(--paper)}
@media (prefers-reduced-motion:reduce){html{scroll-behavior:auto}}
body{
  margin:0;
  background:var(--paper);
  color:var(--ink);
  font:15px/1.62 var(--mono);
  overflow-x:hidden;
  -webkit-font-smoothing:antialiased;
  -moz-osx-font-smoothing:grayscale;
}

/* grain and a vignette, both fixed, both over an otherwise plain document,
   neither ever becoming the layout. on a dark ground the grain has to
   SCREEN — multiply against near-black is invisible. the vignette does the
   real work: it pulls the page edges down into the black so the text reads
   as lit from somewhere rather than printed on something. */
body::before{
  content:"";position:fixed;inset:0;z-index:9998;pointer-events:none;
  opacity:.15;mix-blend-mode:screen;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='200' height='200'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='200' height='200' filter='url(%23n)' opacity='.55'/%3E%3C/svg%3E");
}
body::after{
  content:"";position:fixed;inset:0;z-index:9997;pointer-events:none;
  background:radial-gradient(125% 88% at 50% 34%, transparent 28%, rgba(0,0,0,.55) 76%, rgba(0,0,0,.9) 100%);
}

a{color:var(--ink);text-underline-offset:3px;text-decoration-thickness:1px}
a:hover{background:var(--lit);color:var(--paper);text-decoration:none}
::selection{background:var(--lit);color:var(--paper)}

/* ---------- the title strip ------------------------------------------ */
/* top of the page once, click to copy, then never mentioned again. */
.ca{border-bottom:1px solid var(--hair);background:var(--paper);font-size:11px;position:relative;z-index:2}
.ca .in{max-width:1000px;margin:0 auto;padding:7px 20px;display:flex;gap:12px;align-items:center}
.ca button{font:inherit;font-size:11px;background:none;border:0;padding:0;color:var(--ink);cursor:pointer;word-break:break-all;text-align:left}
.ca button:hover{color:var(--lit)}
.ca .lab{color:var(--dim);white-space:nowrap;letter-spacing:.14em}
.ca .xl{
  margin-left:auto;flex:none;text-decoration:none;
  background:var(--lit);color:var(--paper);
  padding:1px 9px;letter-spacing:.2em;text-transform:uppercase;font-size:10px;
}
.ca .xl:hover{background:var(--paper);color:var(--lit);box-shadow:inset 0 0 0 1px var(--lit)}

/* ---------- shell ---------------------------------------------------- */

.wrap{max-width:1000px;margin:0 auto;padding:0 20px 104px}   /* clears the crawlbar */

.head{padding:22px 0 16px;border-bottom:1px solid var(--hair)}

/* the wordmark is a character grid, not type. clean bold Courier reads as
   a document header, which is the opposite of the brief. */
.head .mark{
  font-family:var(--mono);
  font-size:clamp(6px,1.7vw,11px);
  line-height:1;margin:0;white-space:pre;overflow:hidden;
  letter-spacing:0;font-weight:400;
  color:var(--ink);
  text-shadow:0 0 16px rgba(111,217,255,.22);
}
.head .scatter{
  font-size:10px;line-height:1;color:var(--dim);opacity:.45;
  white-space:nowrap;overflow:hidden;margin:0 0 12px;height:1em;
}
.head .sub{font-size:11px;letter-spacing:.3em;color:var(--dim);margin-top:14px}

/* the marks. one ruled line before each stop, heavier where the premises
   is more exposed to the street. */
.noise{
  font-size:10px;line-height:1;color:var(--ink);opacity:.22;
  white-space:nowrap;overflow:hidden;height:1em;margin:0 0 14px;
  user-select:none;pointer-events:none;
}

/* the strip light. one soft bar that fails the way a dying tube does:
   mostly on, occasionally stuttering. it sits over a plain document and
   never becomes the layout. */
#tube{
  position:fixed;left:0;right:0;top:0;height:1px;z-index:9996;pointer-events:none;
  background:linear-gradient(90deg,transparent,rgba(111,217,255,.5),transparent);
  animation:tube 9s ease-in-out infinite;
}
@keyframes tube{
  0%,88%{opacity:.5}
  89%{opacity:.05}
  90%{opacity:.6}
  92%{opacity:.08}
  93%,100%{opacity:.5}
}
@media (prefers-reduced-motion:reduce){#tube{display:none}}

/* ---------- the circuit ---------------------------------------------- */
/* the site is a walk through a building. the rail is a position in it,
   not a menu. */

.route{display:grid;grid-template-columns:158px 1fr;gap:0}

.rail{
  position:sticky;top:0;align-self:start;
  border-right:1px solid var(--hair);
  padding:26px 16px 26px 0;
  font-size:11px;line-height:1.5;
  max-height:100vh;overflow:auto;
}
.rail .cap{letter-spacing:.24em;text-transform:uppercase;color:var(--dim);margin-bottom:12px}
.rail ol{list-style:none;margin:0;padding:0}
.rail li{margin:0 0 1px}
/* marker over label, not beside it. beside it, the long place names wrap
   under the number and the whole column goes ragged. */
.rail a{display:block;text-decoration:none;padding:3px 5px 4px;color:var(--dim)}
.rail a .m{display:block;font-variant-numeric:tabular-nums;font-size:10px;letter-spacing:.12em;color:var(--ink);opacity:.4}
.rail a:hover{background:rgba(111,217,255,.1);color:var(--ink)}
.rail a.on{background:var(--lit);color:var(--paper)}
.rail a.on .m{color:var(--paper);opacity:.75}

.rail .recep{margin-top:14px;padding-top:10px;border-top:1px solid var(--hair);font-size:10px}
.rail .recep .rl{display:block;letter-spacing:.18em;text-transform:uppercase;color:var(--dim);margin-bottom:3px}
.rail .recep .rb{letter-spacing:-.05em;color:var(--ink);opacity:.7}
/* exposure is the one meter on the site and it cuts both ways: too little
   and the occupation is not open, too much and somebody writes a letter.
   so both ends are marked and neither reads as good. */
.rail .recep .rb.hot{color:var(--lit);opacity:1}
.rail .recep .rb.cold{opacity:.34}
.rail .recep .rid{
  display:block;margin-top:6px;font-size:9.5px;letter-spacing:.1em;
  color:var(--dim);opacity:.6;
}

/* the elevation. the circuit as a building, with the lit cell where you
   are. 06 sits outside the box because it is the one stop that is not
   claimed. */
.rail .map{
  margin-top:14px;padding-top:12px;border-top:1px solid var(--hair);
  font-size:10px;line-height:1.45;white-space:pre;color:var(--dim);
  letter-spacing:.02em;user-select:none;opacity:.75;
}
.rail .map span{color:var(--ink);opacity:.55}
.rail .map span.on{background:var(--lit);color:var(--paper);opacity:1}

.rail .end{margin-top:14px;padding-top:10px;border-top:1px solid var(--hair);color:var(--dim)}
.rail .end a{color:var(--dim);padding:2px 4px 2px 0}

.stops{padding:26px 0 0 26px;min-width:0}

.stop{padding:0 0 8px;scroll-margin-top:14px}
.stop + .stop{margin-top:38px;padding-top:34px;border-top:1px solid var(--hair)}
.stop > .mk{
  display:flex;gap:12px;align-items:baseline;flex-wrap:wrap;
  font-size:11px;letter-spacing:.2em;text-transform:uppercase;color:var(--dim);
  margin:0 0 10px;
}
/* the stop number as a chip, so each stop opens with a stamp rather than a
   label */
.stop > .mk .d{
  font-variant-numeric:tabular-nums;background:var(--lit);color:var(--paper);
  padding:1px 7px;letter-spacing:.14em;
}
.stop > h2{font-size:19px;font-weight:700;letter-spacing:-.015em;margin:0 0 16px;color:var(--ink)}

p{margin:0 0 14px;max-width:62ch}
h3{font-size:13.5px;font-weight:700;margin:0 0 8px}

/* the voice: one clause per line, lowercase, no punctuation. the SHAPE is
   the recognisable thing, so a line that wraps is a bug — it reads as two
   clauses and the whole register goes with it. the measure is set to clear
   the longest line in the copy, and the copy is kept under it. */
.say{max-width:74ch;margin:0 0 22px}
.say div{padding:1px 0}
.say div:empty{height:.85em}
.say .beat{font-weight:700;color:#c9dced}
.say em{font-style:normal;color:var(--dim)}

pre.art{
  font-family:var(--figure);font-size:clamp(8px,1.9vw,12px);line-height:1;
  margin:0 0 18px;overflow-x:auto;white-space:pre;color:var(--ink);
}
pre.art::-webkit-scrollbar{height:6px}
pre.art::-webkit-scrollbar-thumb{background:var(--hair)}

/* the premises. the one thing on the page bigger than a paragraph: a
   measured drawing of the building, turning, with the light on four. it
   gets the accent glow because the lit window is the only accent-coloured
   thing in it. */
/* big, because a 58-column drawing at 12px is a thumbnail and this is
   supposed to be the one thing on the page larger than a paragraph.

   every solid cell is a full block and the tone is carried by colour, so
   there is no glow on the element itself — a shadow under the whole model
   just smears it. only the lit window emits, which is the point of it. */
pre.premises{
  font-size:clamp(8px,2.05vw,17px);line-height:1;
  cursor:grab;margin:0 0 6px;user-select:none;touch-action:pan-y;
  /* the block glyph's advance is a shade wider than its ink, so at one
     cell per character the facade comes out finely pinstriped. pulling the
     tracking in by a fraction closes it without breaking the grid, since
     every row loses exactly the same amount. */
  letter-spacing:-.035em;
}
pre.premises span{display:inline}
.pw{color:#111a22}      /* a window with nothing behind it */
.p2{color:#1d2833}      /* the wall the lamp does not reach */
.p3{color:#31434f}
.p4{color:#4d6576}      /* the wall the lamp is on */
.p5{color:#71889a}      /* the roof, catching the sky */
/* the corner only has to break a tie between two walls that happen to
   take the same tone. brighter than the roof it stops being an edge and
   becomes a bar straight down the middle of the building. */
.pe{color:#5e7382}
.pl{color:var(--lit);text-shadow:0 0 12px rgba(111,217,255,.85),0 0 26px rgba(111,217,255,.4)}
pre.premises:active{cursor:grabbing}
@media (max-width:760px){pre.premises{font-size:clamp(6px,2.4vw,11px)}}
.prem-note{
  font-size:10px;letter-spacing:.24em;text-transform:uppercase;
  opacity:.42;margin:0 0 26px;
}

/* the seal is drawn live and is the one thing here you can put a hand on,
   so it gets a bigger target and its own cursor. */
pre.seal{
  font-size:clamp(8px,2vw,14px);
  cursor:crosshair;margin:0 0 6px;
  text-shadow:0 0 10px rgba(111,217,255,.14);
  touch-action:none;
}
.seal-note{
  font-size:10px;letter-spacing:.28em;text-transform:uppercase;
  opacity:.42;margin:0 0 20px;transition:opacity .4s;
}
pre.seal:hover + .seal-note{opacity:0}

hr{border:0;border-top:1px solid var(--hair);margin:24px 0}
hr.d{border:0;border-top:1px solid var(--ink);opacity:.5;margin:30px 0}

table{border-collapse:collapse;width:100%;font-size:12.5px;margin:0 0 20px}
th{text-align:left;font-weight:700;border-bottom:1px solid var(--hair);padding:4px 8px 4px 0;font-size:10.5px;letter-spacing:.18em;text-transform:uppercase;color:var(--dim)}
td{padding:5px 8px 5px 0;border-bottom:1px solid var(--hair);vertical-align:top}
tr:hover td{background:rgba(168,188,205,.05)}
td.num,th.num{font-variant-numeric:tabular-nums;white-space:nowrap}
.wide{overflow-x:auto}

/* records on the circuit are boxed with a header strip, so a table reads
   as a held document rather than as typesetting */
.wide table{border:1px solid var(--hair)}
.wide th{background:rgba(168,188,205,.09);color:var(--ink);border-bottom:1px solid var(--hair);padding:4px 9px}
.wide td{padding:5px 9px;border-bottom:1px solid var(--hair)}
.wide tr:last-child td{border-bottom:0}

/* the one live block. it reports the claim, never the market. */
.claim{border:1px solid var(--hair);margin:0 0 20px;max-width:470px}
.claim .r{display:flex;justify-content:space-between;gap:14px;padding:5px 10px;border-bottom:1px solid var(--hair);font-size:12.5px}
.claim .r:last-child{border-bottom:0}
.claim .r .k{color:var(--dim);letter-spacing:.06em}
.claim .r .v{font-variant-numeric:tabular-nums;font-weight:700;text-align:right;color:var(--lit)}

/* things pushed under the door */
.left-out{border:1px solid var(--hair);padding:0;margin:0 0 18px}
.left-out .row{display:flex;gap:12px;justify-content:space-between;padding:6px 10px;border-bottom:1px solid var(--hair);font-size:12.5px}
.left-out .row:last-child{border-bottom:0}
.left-out .row .what{min-width:0}
.left-out .row .st{white-space:nowrap;font-size:10.5px;letter-spacing:.16em;text-transform:uppercase;color:var(--dim);padding-top:2px}
.left-out .row .st.took{background:var(--lit);color:var(--paper);padding:1px 6px;letter-spacing:.16em}

/* the reason opens under the thing. the reasons are bare text inside the
   <em>, so there is no element child to drive a grid-row animation —
   max-height it is. 9em clears the longest one with room to spare. */
.left-out .row .what em{
  display:block;font-style:normal;max-height:0;overflow:hidden;opacity:0;
  color:var(--dim);font-size:12px;line-height:1.5;
  transition:max-height .3s ease, opacity .25s, padding-top .3s;
}
.left-out .row:hover .what em,
.left-out .row:focus-within .what em{max-height:9em;opacity:1;padding-top:5px}
.left-out .row:hover{background:rgba(168,188,205,.045)}
.hint{font-size:10px;letter-spacing:.24em;text-transform:uppercase;opacity:.42;margin:0 0 8px}
@media (prefers-reduced-motion:reduce){.left-out .row .what em{transition:none}}

.note{font-size:11.5px;color:var(--dim);max-width:60ch}
.hold{display:inline-block;padding:0 5px;background:var(--lit);color:var(--paper);font-size:10.5px;letter-spacing:.16em}

/* while a boot is due, the page itself is invisible; the overlay is the
   only visible thing. visibility (not display) so descendants can opt back
   in — #boot is a child of body and turns itself on. */
html.booting body{visibility:hidden}
html.booting #boot{visibility:visible}

#boot{
  position:fixed;inset:0;z-index:10000;background:var(--paper);
  display:flex;align-items:center;justify-content:center;
  transition:opacity .6s ease;cursor:pointer;
}
#boot.out{opacity:0;pointer-events:none}
#boot pre{
  font-family:var(--mono);font-size:clamp(9px,1.5vw,13px);line-height:1.7;
  color:var(--ink);margin:0;white-space:pre-wrap;max-width:min(74ch,90vw);
  text-shadow:0 0 12px rgba(111,217,255,.18);
}
#boot .skip{
  position:absolute;bottom:18px;right:20px;font-size:10px;
  letter-spacing:.28em;text-transform:uppercase;color:var(--dim);opacity:.5;
}

/* the crawl. a strip along the bottom, repeating the four limbs forever. */
.crawlbar{
  position:fixed;left:0;right:0;bottom:0;z-index:9994;height:24px;
  background:var(--paper);border-top:1px solid var(--hair);overflow:hidden;
}
.crawlbar div{
  display:inline-block;white-space:nowrap;line-height:24px;
  font-size:10px;letter-spacing:.22em;text-transform:uppercase;color:var(--dim);
  animation:crawl 52s linear infinite;
}
@keyframes crawl{from{transform:translateX(0)}to{transform:translateX(-50%)}}
@media (prefers-reduced-motion:reduce){.crawlbar{display:none}}

/* the asides. bottom left, over everything, never in the flow. it must not
   move the page when it arrives or it becomes a layout element. */
#leak{
  position:fixed;left:18px;bottom:40px;z-index:9995;max-width:min(46ch,calc(100vw - 36px));
  font-size:12px;line-height:1.5;color:var(--ink);
  background:var(--paper);border-left:2px solid var(--lit);padding:7px 11px;
  opacity:0;transform:translateY(6px);pointer-events:none;
  transition:opacity .8s ease,transform .8s ease;
}
#leak.on{opacity:.93;transform:translateY(0)}
#leak.still.on{opacity:1}
@media (prefers-reduced-motion:reduce){#leak{display:none}}
@media (max-width:560px){#leak{left:10px;right:10px;bottom:34px;font-size:11.5px}}

footer.den{
  margin-top:44px;padding-top:14px;border-top:1px solid var(--hair);
  font-size:11px;color:var(--dim);display:flex;flex-wrap:wrap;gap:12px;justify-content:space-between;
}
footer.den a{color:var(--dim)}

/* ---------- pages that are not the circuit --------------------------- */
.page{max-width:66ch;padding:26px 0 0}
.page h1{font-size:22px;margin:0 0 6px;color:var(--ink)}
.page .back{font-size:11px;letter-spacing:.2em;text-transform:uppercase;display:inline-block;margin-bottom:22px}
.page h2{font-size:16px;margin:28px 0 8px;color:var(--ink)}
.page ul{max-width:62ch;padding-left:20px}
.page li{margin-bottom:7px}
.page.wide-page{max-width:100%}

/* the day listing. tight rows, tabular, no ornament — it has to read as a
   record rather than a feature, and most of its rows say nothing. */
.listing{border-top:1px solid var(--hair);max-width:640px}
.listing table{font-size:12.5px;margin:0}
.listing th{border-bottom:1px solid var(--hair)}
.listing td{padding:2px 8px 2px 0;border-bottom:0;line-height:1.5}
.listing tbody tr:nth-child(even) td{background:rgba(168,188,205,.035)}
.listing tbody tr:hover td{background:var(--lit);color:var(--paper)}
.listing tbody tr:hover a{color:var(--paper)}
.listing td:last-child{color:var(--dim)}
.listing tbody tr:hover td:last-child{color:var(--paper)}

.entry{border-top:1px solid var(--hair);padding:22px 0 0;margin:26px 0 0;scroll-margin-top:16px}
.entry:target .mk .n{background:var(--lit);color:var(--paper);padding:0 5px}
.entry .mk{font-size:11px;letter-spacing:.2em;text-transform:uppercase;color:var(--dim);display:flex;gap:12px;flex-wrap:wrap;margin-bottom:12px}
.entry .mk .n{color:var(--ink);font-weight:700}

/* a served notice, reproduced. the body is set apart from the annotation
   so the two are never confused for each other. */
.served{
  border:1px solid var(--hair);border-left:2px solid var(--dim);
  padding:12px 14px;margin:0 0 12px;font-size:12.5px;line-height:1.55;
  color:var(--dim);max-width:62ch;
}
.served .h{
  display:block;font-size:10px;letter-spacing:.2em;text-transform:uppercase;
  color:var(--dim);opacity:.7;margin-bottom:7px;
}
.served b{color:var(--ink);font-weight:400}

@media (max-width:760px){
  .route{grid-template-columns:1fr}
  .rail{
    position:static;border-right:0;border-bottom:1px solid var(--hair);
    padding:16px 0;max-height:none;
  }
  .rail ol{display:flex;flex-wrap:wrap;gap:0 2px}
  .rail li{margin:0}
  .rail a{padding:3px 8px 3px 5px}
  .rail a .m{display:inline;margin-right:6px;font-size:inherit}
  .rail .map{display:none}      /* the elevation needs the column width */
  .stops{padding:22px 0 0}
}
@media (max-width:560px){
  body{font-size:14px}
  .wrap{padding:0 14px 60px}
  .ca .in{padding:6px 14px;gap:9px}
  .ca .lab{display:none}
  table{font-size:11.5px}
}
