/* The railway's skin (10 Nov 2026). Jordan: "give it its own feel and design like you did with the gunsmith", "we
   need the railway to genuinely be mind blowing and stand out", and of the first try (a black book with card-ticket
   tabs): "the folders give off the same feel. Instead of manila folders and stuff, it should be more like ... what a
   trainyard would use". The engine's stylesheets are shared with the sister sites and draw a bound ledger with
   manila folder tabs; this file, loaded after them all, turns that into the railway's own things:

     - the papers are a sheaf of train-order FLIMSIES (pale green, with a yellow and a pink one under it) held on an
       oak YARD CLIPBOARD by a nickel spring clip (not a book);
     - the tabs are CARD TICKETS tucked under the head of the board, three either side of the clip. The clip and the
       tickets are photographs of real ones (ChatGPT cut-outs in assets/sprites/). A first try drew enamel station
       signs on a rod in CSS; Jordan: "so cliche and low quality and out of place and like a website ... this is
       supposed to feel like a realistic immersive in character thing". So: real objects, lying where they would;
     - cards and slips are ticket stock;
     - the board lies in the clear leather of the agent's own desk (scene.js, plates.json), with the lamp, the
       telegraph and the lantern down its left side and the cap, the punch and the watch at its right.

   It changes looks and where the board lies, nothing else: every id, class and size a script measures stays in the
   engine's files, so the page turns, the phone layout and the checks are untouched. Rooms' own stylesheets load
   AFTER this file, so anything that must beat them is written with `:root` in front. */

:root {
  --font-deco: 'Bevan', 'Rockwell', Georgia, serif;                 /* the company's name, a form's title */
  --font-stencil: 'Oswald', 'Arial Narrow', sans-serif;             /* headings: timetable gothic */
  --font-stamp: 'Stardos Stencil', 'Special Elite', monospace;      /* rubber stamps stay rubber stamps */

  --gilt: #ecd08a;
  --signal: #a3221a;        /* signal red: the open sign, the lantern */
  --enamel: #15243c;        /* station-sign blue */
  --enamel-hi: #233a5f;
  --enamel-white: #f3f0e6;
  --flimsy: #c9d2b6;        /* train-order green, in a low light */
  --flimsy-yellow: #d8c98a;
  --flimsy-pink: #d3aa9f;
  --card-ink: #1d1914;

  /* Ticket stock where the engine has manila. */
  --manila: #c9b48a;
  --manila-2: #b9a276;
  --manila-edge: #6a5327;
}
html[data-theme='light'] {
  --flimsy: #e2e9cf;
  --flimsy-yellow: #efe1a2;
  --flimsy-pink: #ecc6ba;
  --manila: #e0cda4;
  --manila-2: #d0bb8e;
  --manila-edge: #84693a;
}

/* ---- the yard clipboard --------------------------------------------------------------------------- */

/* Where the board lies. The desk (plates.json) is seen from the agent's chair: pigeonholes across the back (the top
   quarter), and down the left fifth the lamp, the telegraph and the lantern; the cap, the punch and the watch keep to
   the right seventh. The board lies on the clear leather between them. On a smaller window the paper keeps its width
   first (about 1060px): the board slides over the cap and the watch, and only then over the lamp's side, because the
   lamp and the lantern are the two things on this desk that are worked by hand. */
@media (min-width: 901px) {
  .ledger-stage {
    padding-top: clamp(162px, 20vh, 224px);
    padding-bottom: 40px;
    /* never less than the board's own edge (26px) and a little desk, so the board is never cut by the screen */
    padding-left: clamp(38px, calc(100vw - 1090px), 20vw);
    padding-right: clamp(38px, calc(80vw - 1060px), 14vw);
  }
  .ledger { justify-self: center; margin-left: 0; transform: rotate(-0.3deg); }
}

/* The board: a slab of oak, worn pale at the edges, a little larger than the paper. */
.ledger-cover {
  border-radius: 12px;
  background:
    linear-gradient(180deg, rgba(255, 230, 190, 0.16), transparent 9%, transparent 82%, rgba(0, 0, 0, 0.34)),
    linear-gradient(90deg, rgba(0, 0, 0, 0.28), transparent 3%, transparent 97%, rgba(0, 0, 0, 0.3)),
    var(--img-desk-wood, none),
    linear-gradient(170deg, #7a4f2b, #4a2e17 70%);
  background-size: auto, auto, 780px 390px, auto;
  background-blend-mode: normal, normal, soft-light, normal;
  box-shadow: 0 34px 70px rgba(0, 0, 0, 0.75), 0 6px 14px rgba(0, 0, 0, 0.6), inset 0 0 0 1px rgba(0, 0, 0, 0.6), inset 0 2px 0 rgba(255, 225, 180, 0.18), inset 0 -3px 0 rgba(0, 0, 0, 0.35);
}
.ledger-cover::before, .ledger-cover::after { display: none; }
@media (min-width: 641px) { .ledger-cover { inset: -30px -24px -24px -24px; } }
@media (min-width: 901px) { .ledger-cover { inset: -62px -26px -26px -26px; } }
@media (max-width: 640px) { .ledger-cover { inset: -8px -5px -9px -5px; border-radius: 7px; } }

/* The sheaf under the top sheet: a yellow flimsy and a pink one, not quite square with it. */
.ledger-block {
  inset: 4px -6px -8px 4px;
  border-radius: 2px;
  background: var(--flimsy-yellow);
  background-image: var(--img-paper, none);
  background-size: 700px;
  background-blend-mode: multiply;
  box-shadow: 4px 5px 0 -1px var(--flimsy-pink), 0 3px 8px rgba(0, 0, 0, 0.5);
  transform: rotate(0.45deg);
}
@media (max-width: 640px) { .ledger-block { inset: 2px -2px -3px 2px; box-shadow: 0 2px 5px rgba(0, 0, 0, 0.4); } }

/* The top sheet: a train-order flimsy, plain pale green, no ledger rules. */
.lpage .sheet {
  --m: clamp(26px, 3.4vw, 54px);
  border-radius: 2px;
  background-color: var(--flimsy);
  background-image:
    linear-gradient(170deg, rgba(255, 255, 245, 0.2), transparent 35%, transparent 70%, rgba(60, 80, 40, 0.1)),
    var(--img-paper, none);
  background-size: auto, 700px 700px;
  background-blend-mode: normal, multiply;
  box-shadow: 0 0 0 0.5px rgba(50, 60, 40, 0.4), 0 2px 3px rgba(0, 0, 0, 0.35);
}
.lface.back { background-color: var(--flimsy); }
/* A sheet on a clipboard is hinged along its head, under the clip: it is lifted and folded back over the top, never
   turned sideways (ledger.js `show`). Its back shows as it comes over (the engine's back face is turned for a
   sideways turn; rotateX(180deg) turns it for this one), and the shade falls from the head down. */
.lpage { transform-origin: 50% 0; }
.lface.back { transform: rotateX(180deg); box-shadow: inset 0 30px 40px rgba(0, 0, 0, 0.16); }
.lshade { background: linear-gradient(180deg, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0.12) 60%, transparent); }

/* The spring clip at the head of the board: a photograph of a real one (assets/sprites/clip.webp, a ChatGPT
   cut-out), its jaw on the sheaf and its wire handle standing clear of the board's edge. It carries no lettering; the
   company's name is at the head of the papers themselves. */
.ledger-band {
  left: 50%;
  right: auto;
  top: -76px;
  width: 256px;
  min-width: 0;
  height: 86px;
  padding: 0;
  transform: translateX(-50%);
  border-radius: 0;
  background: url('/assets/sprites/clip.webp?v=e7e9bcbe19') center / 100% 100% no-repeat;
  box-shadow: none;
  filter: drop-shadow(0 5px 5px rgba(0, 0, 0, 0.55));
  font-size: 0;
  color: transparent;
  text-shadow: none;
}
.ledger-band > *, .ledger-band::before, .ledger-band::after { display: none; }

/* ---- the tabs: card tickets under the head of the board ------------------------------------------- */

/* Each tab is a real card ticket (assets/sprites/ticket_1..6.webp, photographs cut out of a ChatGPT sheet: buff,
   salmon, green, blue-grey, yellow, white, each with its own wear and its punched hole), with the room's name printed
   on it. They lie on the desk with their lower halves tucked under the head of the board, three either side of the
   clip, none quite square; the open room's ticket is drawn further out and its name is in red. Nothing here is drawn
   in CSS but the lettering. */
.ltab-row { gap: 8px; filter: drop-shadow(0 3px 3px rgba(0, 0, 0, 0.6)); }
.ltab {
  --r: 0deg;
  clip-path: none;
  padding: 0;
  border-radius: 0;
  color: #241c14;
  background: url('/assets/sprites/ticket_1.webp?v=e2cb829d41') top center / 100% auto no-repeat;
  box-shadow: none;
  filter: none;
}
.ltab:nth-child(6n + 2) { background-image: url('/assets/sprites/ticket_2.webp?v=5fa9a3eec2'); }
.ltab:nth-child(6n + 3) { background-image: url('/assets/sprites/ticket_3.webp?v=36eb4a489d'); }
.ltab:nth-child(6n + 4) { background-image: url('/assets/sprites/ticket_4.webp?v=d4bdcc774e'); }
.ltab:nth-child(6n + 5) { background-image: url('/assets/sprites/ticket_5.webp?v=0ef98b0319'); }
.ltab:nth-child(6n + 6) { background-image: url('/assets/sprites/ticket_6.webp?v=f77a2254d8'); }
.ltab span {
  margin: 11px 0 0;
  padding: 0 14% 0 7%; /* clear of the punched hole at the right-hand end */
  background: none;
  box-shadow: none;
  -webkit-text-stroke: 0;
  font-family: var(--font-stencil);
  font-weight: 600;
  font-size: clamp(0.86rem, 1vw, 1.08rem);
  line-height: 1.5;
  letter-spacing: 0.14em;
  text-overflow: clip;
  color: #2b2118;
  opacity: 0.86;
  mix-blend-mode: multiply; /* printed on the card, not laid over it */
}
.ltab:hover { filter: none; }
.ltab.active { box-shadow: none; filter: none; }
.ltab.active span { color: #8a1a14; opacity: 0.92; }
.ltab:focus-visible { outline: 2px dashed var(--gilt); outline-offset: 2px; }
html[data-paper='dark'] .ltab, html[data-paper='dark'] .ltab:hover, html[data-paper='dark'] .ltab.active { filter: brightness(0.8); }

@media (min-width: 901px) {
  /* under the board (z-index), the lower 40px of each ticket hidden by its head */
  .ledger-tabs { z-index: -1; left: 4px; right: 4px; height: 90px; bottom: calc(100% + 34px); }
  .ltab-row { height: 90px; align-items: flex-start; padding: 0; }
  .ltab, .ltab.active {
    display: flex;
    align-items: flex-start;
    justify-content: center;
    height: 90px;
    max-width: 172px;
    transform: translateY(12px) rotate(var(--r));
    transition: transform 0.35s cubic-bezier(.2, .8, .3, 1);
  }
  .ltab:hover { transform: translateY(6px) rotate(var(--r)); }
  .ltab.active, .ltab.active:hover { transform: translateY(-2px) rotate(var(--r)); }
  .ltab:nth-child(1) { --r: -1.3deg; }
  .ltab:nth-child(2) { --r: 0.9deg; }
  .ltab:nth-child(3) { --r: -0.5deg; margin-right: 270px; } /* the clip stands between the third and the fourth */
  .ltab:nth-child(4) { --r: 1.1deg; }
  .ltab:nth-child(5) { --r: -0.8deg; }
  .ltab:nth-child(6) { --r: 0.6deg; }
}

/* A window under 1500px: the board reaches under the name tag in the corner, and the last ticket (Crew) lay beneath
   it, unreadable and unclickable (found 10 Nov 2026). The tag goes to the very top and the board sits a little lower,
   so the tickets come out below the tag. */
@media (min-width: 901px) and (max-width: 1499px) {
  .ledger-stage { padding-top: clamp(198px, 23vh, 240px); }
  .duty-tag { top: 3px; }
}

@media (max-width: 900px) {
  .ltab, .ltab.active {
    clip-path: none;
    display: flex;
    align-items: flex-start;
    justify-content: center;
    min-width: 112px;
    height: 36px;
    padding: 0;
    border-radius: 0;
    background-size: 100% auto;
    background-position: top center;
    background-blend-mode: normal;
    filter: none;
  }
  .ltab span { font-size: 0.74rem; letter-spacing: 0.1em; margin-top: 6px; }
  .ltab:hover, .ltab.active:hover { filter: none; }
}
@media (prefers-reduced-motion: reduce) { .ltab, .ltab.active { transition: none; } }

/* ---- lettering on the pages ---------------------------------------------------------------------- */

/* Headings set like the head of a timetable. */
.sheet-head h1 { font-family: var(--font-stencil); font-weight: 600; letter-spacing: 0.16em; color: #1f1a14; }
.sheet-head { border-bottom: 3px double rgba(30, 25, 20, 0.7); }

/* Rubber stamps and the punch stamp stay rubber stamps. */
:root .bl-stamp, :root .btn.stampish, :root .td-punch { font-family: var(--font-stamp); }

/* The company's name at the head of the Board: a timetable's double rule under it. */
.td-mast .td-name { letter-spacing: 0.01em; }

/* ---- the desk: two lights ------------------------------------------------------------------------ */

/* The oil lamp and the red signal lantern are worked separately (scene.js): `data-oil` is the lamp's own wick,
   `data-lantern` the lantern, and `data-lamp` the room's light, the two added up. So the flame's glow follows the
   lamp alone, the globe's glow the lantern alone, and the lamp's chimney goes dark over the lit photograph while the
   lamp itself is out (a room lit by the lantern must not show a flame in the lamp). */
html { --oil-glow: 0; }
html[data-oil='dim'] { --oil-glow: 0.5; }
html[data-oil='on'] { --oil-glow: 1; }

:root .sc-flame { opacity: var(--oil-glow); }
/* the lit photograph is the lamp's light alone; the lantern has its own (below) */
:root .sc-lit.has-plate { opacity: var(--oil-glow); }
.sc-lampout {
  position: absolute;
  pointer-events: none;
  background-size: 100% 100%;
  background-repeat: no-repeat;
  opacity: calc(1 - var(--oil-glow));
  transition: opacity 0.6s cubic-bezier(.3, .6, .4, 1);
}
.sc-lantern {
  position: absolute;
  pointer-events: none;
  mix-blend-mode: screen;
  opacity: 0;
  transition: opacity 0.6s ease;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(255, 96, 60, 0.85) 0, rgba(235, 40, 24, 0.5) 22%, rgba(190, 22, 12, 0.22) 45%, rgba(160, 16, 8, 0) 70%);
}
/* its light on the desk round it: a wide, faint red wash */
.sc-lantern::after {
  content: '';
  position: absolute;
  inset: -90%;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(255, 70, 40, 0.24) 0, rgba(220, 40, 20, 0.09) 30%, rgba(200, 30, 14, 0) 68%);
}
html[data-lantern='on'] .sc-lantern { opacity: 1; animation: lantern-breathe 5.5s ease-in-out infinite; }
/* a lantern's flame is never quite still: slow and slight (nothing here flickers fast) */
@keyframes lantern-breathe { 0%, 100% { opacity: 1; } 40% { opacity: 0.86; } 70% { opacity: 0.95; } }

/* The room by the lantern's light (Jordan, 10 Nov 2026: "Does the lantern give off red light? It should ... give that
   spooky red ambiance"). A third copy of the desk photograph, the lamp-out one, turned to red alone (multiplied by
   red, then brought up) and let in most round the lantern, falling away across the desk, so the things near it stand
   out of the dark in red the way they would. It is the whole of the room's light when the lamp is out, and gives way
   as the lamp comes up. The papers on the board take a red cast from the lantern's side as well. */
html { --red-room: 1; --lx: 7%; --ly: 76%; }
html[data-oil='dim'] { --red-room: 0.55; }
html[data-oil='on'] { --red-room: 0.3; }
:root .sc-red { opacity: 0; filter: none; transition: opacity 0.9s ease; }
:root .sc-red.has-plate {
  background: var(--plate) center / cover no-repeat, #ff2a10;
  background-blend-mode: multiply;
  filter: brightness(2.9) contrast(1.12);
  -webkit-mask-image: radial-gradient(circle 125vmax at var(--lx) var(--ly), #000 0, rgba(0, 0, 0, 0.85) 9%, rgba(0, 0, 0, 0.55) 24%, rgba(0, 0, 0, 0.3) 45%, rgba(0, 0, 0, 0.14) 70%, rgba(0, 0, 0, 0.06) 100%);
  mask-image: radial-gradient(circle 125vmax at var(--lx) var(--ly), #000 0, rgba(0, 0, 0, 0.85) 9%, rgba(0, 0, 0, 0.55) 24%, rgba(0, 0, 0, 0.3) 45%, rgba(0, 0, 0, 0.14) 70%, rgba(0, 0, 0, 0.06) 100%);
}
html[data-lantern='on'] .sc-red.has-plate { opacity: var(--red-room); }
html[data-room='board'] .sc-red { display: none; }

/* The red on the board and its papers. NOT a layer laid over the board: the first try was a `.ledger::after` wash
   (multiply), and in FIREFOX that one pseudo-element upset the order of everything in the board's 3D stack, so that a
   click anywhere on the top or the left of a page landed on the board behind it (.ledger-cover): the tabs under
   Office, Crew's dividers and most buttons were dead, lantern lit or not (Jordan uses Firefox; found 11 Nov 2026 with
   scripts/probe-firefox.mjs; Edge and Chrome never showed it). So each flat thing is tinted on its own, the way the
   engine's dark paperwork is (base.css): the sheet by a filter, the board by a wash inside its own box. Nothing is
   added to `.ledger`. */
html { --red-cast: sepia(calc(0.55 * var(--red-room))) saturate(calc(1 + 0.9 * var(--red-room))) hue-rotate(calc(-28deg * var(--red-room))) brightness(calc(1 - 0.08 * var(--red-room))); }
html[data-lantern='on'] .lpage .sheet { filter: var(--red-cast); }
html[data-lantern='on'][data-paper='dark'] .lpage .sheet { filter: var(--paper-dark) var(--red-cast); }
.ledger-cover { transition: box-shadow 0.9s ease; }
html[data-lantern='on'] .ledger-cover {
  box-shadow: 0 34px 70px rgba(0, 0, 0, 0.75), 0 6px 14px rgba(0, 0, 0, 0.6), inset 0 0 0 1px rgba(0, 0, 0, 0.6), inset 0 2px 0 rgba(255, 225, 180, 0.18), inset 0 -3px 0 rgba(0, 0, 0, 0.35),
    inset 0 0 0 2000px rgba(200, 30, 12, calc(0.26 * var(--red-room)));
}
/* the tickets lie in it too */
html[data-lantern='on'] .ltab { filter: sepia(0.25) saturate(1.5) hue-rotate(-18deg) brightness(calc(1 - 0.14 * var(--red-room))); }
@media (prefers-reduced-motion: reduce) { html[data-lantern='on'] .sc-lantern { animation: none; } }

#scene.hot-N .sc-lantern { filter: brightness(1.35); }
html[data-room='board'] .sc-lantern, html[data-room='board'] .sc-lampout { display: none !important; }
.prop.lantern { border-radius: 40% 40% 30% 30%; }

/* ---- the telegraph tape (wire.js) --------------------------------------------------------------- */

/* A strip of paper tape that runs out from the left edge, where the sounder stands, with the news typed along it. */
#wire-tape {
  position: fixed;
  z-index: 58;
  left: 0;
  bottom: 26px;
  max-width: min(78vw, 860px);
  pointer-events: none;
  transform: translate3d(-104%, 0, 0);
  transition: transform 0.5s cubic-bezier(.2, .75, .25, 1);
  filter: drop-shadow(0 6px 10px rgba(0, 0, 0, 0.5));
}
#wire-tape.out { transform: none; }
.wt-strip {
  display: flex;
  align-items: baseline;
  gap: 14px;
  min-height: 34px;
  padding: 7px 26px 6px 18px;
  background-color: #efe6cd;
  background-image: linear-gradient(180deg, rgba(255, 255, 255, 0.35), rgba(255, 255, 255, 0) 40%, rgba(90, 60, 20, 0.14)), var(--img-paper, none);
  background-size: auto, 500px;
  background-blend-mode: normal, multiply;
  border-top: 1px solid rgba(60, 45, 25, 0.25);
  border-bottom: 1px solid rgba(60, 45, 25, 0.35);
  border-radius: 0 2px 2px 0;
  /* the torn end */
  clip-path: polygon(0 0, calc(100% - 9px) 0, 100% 22%, calc(100% - 6px) 45%, 100% 70%, calc(100% - 8px) 100%, 0 100%);
  transform: rotate(-0.35deg);
}
.wt-head {
  flex: none;
  font-family: var(--font-type);
  font-size: 0.62rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--signal, #8e1f1a);
  white-space: nowrap;
}
.wt-text {
  font-family: var(--font-type);
  font-size: 1.02rem;
  letter-spacing: 0.14em;
  color: #1d1914;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: clip;
}
.wt-end { flex: none; width: 2px; height: 1.05em; align-self: center; background: #1d1914; opacity: 0.55; animation: wt-blink 0.9s steps(2) infinite; }
@keyframes wt-blink { 50% { opacity: 0; } }
@media (max-width: 640px) {
  #wire-tape { bottom: 12px; max-width: 96vw; }
  .wt-strip { flex-wrap: wrap; gap: 2px 10px; padding: 6px 20px 5px 12px; }
  .wt-text { font-size: 0.86rem; letter-spacing: 0.08em; white-space: normal; }
}
@media (prefers-reduced-motion: reduce) { #wire-tape { transition: none; } .wt-end { animation: none; } }
