/* The front page, over the town. Ashmere is the ground, a still that the page's script replaces with the town itself, its residents walking. Over it stands the storyboard's frame
   F1a, in its own tokens and rules (.claude/handoff/2026-11-05 scratchpad, storyboard-test/_blob/985ce9c0c7042bc83f4389107944e259.css, the sheet the frames load): on the left the sentence, the next sitting, last night and the way round the town, on
   the right tonight's seats with the name, the one choice and the button. Below that the rest of the page stands in cards, with the town on both margins and between them. Laid over system.css (the owner, 4 and 5 November 2026: the town as the ground,
   the life the page had lost, and the frame's words). The two pages a mail's link opens share this file, in one narrow column with no town.
   The colours are that sheet's two sets, whichever the visitor's system asks for, as the sheet does; no frame shows a switch (the owner, 5 November 2026, of the light theme: "i think its better we build it once andf for all"). */

/* The veil is the page's own colour laid over the town: --veil-under over all of it, --veil-words again where the words lie (below, at the ground). */
:root {
  --bg: #efebe3; --panel: #f7f4ee; --sunk: #e2dccf; --ink: #1b1713; --muted: #4f4740; --edge: #1b1713; --focus: #1b1713; --place: #d8c3a0;
  --lit: #ffd76a; --flame: #ffb43c; --chosen: #ffeda2; --on-lit: #1b1713; --blind: #8a6a4c; --pane-dark: #2a211a; --park: #a9b38c;
  --term-bg: #1b1713; --term-fg: #efebe3; --term-dim: #c9bba8;
  --veil: 239 235 227; --veil-under: .2; --veil-words: .525;
}
@media (prefers-color-scheme: dark) {
  :root {
    --bg: #34271d; --panel: #3e2f23; --sunk: #2a1f17; --ink: #efebe3; --muted: #c9bba8; --edge: #c9bba8; --focus: #ffd76a; --place: #5a4632;
    --blind: #a27a56; --pane-dark: #140e0a; --park: #4d5236;
    --veil: 20 14 10;
  }
}
html { background: var(--sunk); }
.front-page {
  --gh: 100vh;
  background: var(--bg);
  min-height: 100vh;
}
@supports (height: 100lvh) { .front-page { --gh: 100lvh; } }
.front-page :focus-visible { outline: 3px solid var(--focus); outline-offset: 2px; }
.front-page a:hover { background: var(--chosen); color: var(--on-lit); text-decoration-color: var(--on-lit); }
.front-page h1, .front-page h2, .front-page h3, .front-page h4, .front-page p, .front-page fieldset, .front-page figure { margin: 0; }
.front-page h1, .front-page h2, .front-page h3, .front-page h4 { text-wrap: balance; font-weight: 400; }

/* ----- the frame's type ----- */
.px16, .px24, .px32 { font-family: "Silkscreen", "Geist Mono", ui-monospace, monospace; font-weight: 400; -webkit-font-smoothing: none; }
.px16 { font-size: 16px; line-height: 24px; }
.px24 { font-size: 24px; line-height: 32px; }
.px32 { font-size: 32px; line-height: 40px; }
@media (max-width: 640px) { .px32 { font-size: 24px; line-height: 32px; } }
.front-page time, .front-page code { font-family: "Geist Mono", ui-monospace, "SF Mono", Menlo, Consolas, monospace; font-variant-numeric: tabular-nums; }
.lead { font-size: 20px; line-height: 1.5; max-width: 60ch; text-wrap: pretty; }
.small, .last { font-size: 14px; line-height: 1.5; }
.front-page .l-sentence { font: 600 clamp(22px, 3.2vw, 34px)/1.22 "Geist", ui-sans-serif, system-ui, sans-serif; text-wrap: balance; max-width: 24em; }
.nw { white-space: nowrap; }
.wrap { max-width: 1120px; margin: 0 auto; padding-left: max(16px, env(safe-area-inset-left, 0px)); padding-right: max(16px, env(safe-area-inset-right, 0px)); }
.stack { display: grid; gap: 16px; align-content: start; min-width: 0; }
.stack.tight { gap: 12px; }
.muted { color: var(--muted); }
.prose { max-width: 66ch; text-wrap: pretty; }
.front-page [hidden] { display: none !important; }
/* the frames' two shapes, a phone's and anything wider; each element keeps its own display inside its range */
@media (min-width: 641px) { .front-page .narrow-only { display: none !important; } }
@media (max-width: 640px) { .front-page .wide-only { display: none !important; } }

/* ----- the bar, laid over the ground ----- */
.top { position: absolute; inset: 0 0 auto; z-index: 3; display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 4px 24px; padding-block: 14px; }
.brand { display: inline-flex; align-items: center; gap: 12px; text-decoration: none; color: inherit; min-height: 44px; }
.front-page .brand:hover { background: none; color: inherit; }
.mk { display: grid; grid-template-columns: repeat(4, 10px); grid-auto-rows: 10px; gap: 2px; flex: none; }
.mk i { display: block; border: 2px solid var(--edge); background: var(--pane-dark); }
.mk i.on { background: var(--lit); }

/* the shared bar, on the two pages a mail's link opens */
.front-page .bar { position: absolute; inset: 0 0 auto; z-index: 3; max-width: 1120px; margin-inline: auto; padding-inline: 16px; }
.front-page .bar a:hover { background: none; color: var(--ink); }

/* ----- the ground: as tall as the window, held in view behind the whole page; it holds still from the first scroll (ground.js) ----- */
.front-page .front { display: block; position: relative; max-width: none; padding: 0; }
.ground { position: sticky; top: 0; z-index: 0; height: var(--gh); margin-bottom: calc(-1 * var(--gh)); overflow: hidden; background: var(--sunk); }
.ground picture, .ground img, .ground iframe { position: absolute; inset: 0; display: block; width: 100%; height: 100%; border: 0; }
.ground img { object-fit: cover; }
.ground iframe { opacity: 0; pointer-events: none; transition: opacity .7s linear; }
.ground iframe.on { opacity: 1; }
/* Two veils, which together stand thick enough under the words for more than 4.5 to 1 on anything the town can show, and thin where only the panel lies over it: .62 and .2, on both sides. The frames' sheet has .72 and .3 on paper, over a town painted far brighter than this one; on this town that figure reads as fog, in my stills of 5 November. The second goes once the first screen's words have left the window, so both margins below it read the same. */
.ground::before, .ground::after { content: ""; position: absolute; inset: 0; z-index: 1; pointer-events: none; }
.ground::before { background: rgb(var(--veil) / var(--veil-under)); }
.ground::after { background: linear-gradient(90deg, rgb(var(--veil) / var(--veil-words)) 0, rgb(var(--veil) / var(--veil-words)) 54%, rgb(var(--veil) / 0) 100%); transition: opacity .4s linear; }
.ground.past::after { opacity: 0; }
.top-mark { position: absolute; top: 0; left: 0; width: 1px; height: 8px; pointer-events: none; }
@media (prefers-reduced-motion: reduce) { .ground iframe, .ground::after { transition: none; } }

/* ----- what stands on it: frame F1a ----- */
.arrive { position: relative; z-index: 1; display: grid; column-gap: 40px; row-gap: 24px; grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr); grid-template-rows: auto 1fr; align-items: start; min-height: var(--gh); padding-block: 96px 56px; }
.arrive > * { min-width: 0; }
.says { gap: 24px; padding-block: 24px 0; }
.panel { background: var(--panel); border: 2px solid var(--edge); padding: 24px; }
.arrive > .panel { grid-column: 2; grid-row: 1 / span 2; }
.then { gap: 24px; padding-block: 0 24px; grid-column: 1; grid-row: 2; }
@media (max-width: 900px) {
  .arrive { grid-template-columns: minmax(0, 1fr); grid-template-rows: none; row-gap: 28px; padding-block: 88px 40px; }
  .says { gap: 20px; padding-block: 8px 0; }
  .arrive > .panel, .then { grid-column: auto; grid-row: auto; }
  .then { gap: 20px; padding-block: 0 8px; }
  .ground::after { background: rgb(var(--veil) / var(--veil-words)); }
}
@media (max-width: 640px) { .panel { padding: 16px; } }

.clock { display: grid; gap: 2px; }
.clock-big { font: 500 28px/1.2 "Geist Mono", ui-monospace, Menlo, monospace; font-variant-numeric: tabular-nums; }
.last .mono, .small .mono { font-variant-numeric: tabular-nums; }

.btn { font: 500 15px/1.2 "Geist", ui-sans-serif, system-ui, sans-serif; min-height: 44px; padding: 8px 16px; border: 2px solid var(--edge); border-radius: 0; background: transparent; color: var(--ink); cursor: pointer; display: inline-flex; align-items: center; justify-content: center; gap: 8px; text-decoration: none; transition: background-color 120ms cubic-bezier(.23, 1, .32, 1), color 120ms cubic-bezier(.23, 1, .32, 1); }
.front-page .btn:hover { background: var(--chosen); color: var(--on-lit); }
.btn-p { background: var(--ink); color: var(--bg); }
.btn:disabled { opacity: .55; cursor: not-allowed; }
.btn-row { display: flex; flex-wrap: wrap; gap: 12px; }
/* the small replay: the town standing empty (tools/read/still.mjs), then the real page in a frame fading in over it, scaled by reel.js. The button's ::after covers the box, so the whole frame presses through. Once it plays the button goes to the town's lower corner, above the money (--money), since the camera draws in on the speaker in the middle. The two buttons wear the dark fill in both themes, because they stand on the picture and not on the page. */
.reel { --money: 20cqh; position: relative; container-type: size; display: grid; place-items: center; width: 100%; aspect-ratio: 2 / 1; max-height: 70svh; overflow: hidden; border: 2px solid var(--edge); background: var(--park); }
.reel picture { position: absolute; inset: 0; }
.reel img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.reel iframe { position: absolute; z-index: 1; left: 0; top: 0; border: 0; transform-origin: 0 0; pointer-events: none; opacity: 0; transition: opacity .2s; }
.reel iframe.on { opacity: 1; }
.reel-go, .reel-pause { background: var(--term-bg); color: var(--term-fg); border-color: var(--term-fg); }
.reel-go { position: relative; z-index: 2; gap: 10px; transition: translate .4s; }
.reel.on .reel-go { translate: calc(50cqw - 50% - 12px) calc(50cqh - 50% - var(--money) - 12px); }
.reel-go::before { content: ""; width: 0; height: 0; border-block: 7px solid transparent; border-inline-start: 11px solid currentColor; }
.reel-go::after { content: ""; position: absolute; inset: -100vmax; }
.reel-pause { position: absolute; z-index: 3; left: 12px; bottom: calc(var(--money) + 12px); }
.front-page .reel-go:focus-visible, .front-page .reel-pause:focus-visible { outline-color: var(--lit); outline-offset: 0; }
@media (max-width: 640px) and (orientation: portrait) { .reel { --money: 24cqh; width: auto; aspect-ratio: 1 / 1.15; max-height: none; margin-inline: calc(-1 * var(--pad)); border-width: 2px 0; } }
@media (prefers-reduced-motion: reduce) { .reel iframe, .reel-go { transition: none; } }
.then .btn, .top .btn { background: var(--bg); }
/* the brand and the town's pause share the bar's one row, which the words beneath it allow for; on a narrow phone the button's words take two lines rather than the button taking a second row over those words */
@media (max-width: 399px) { .top { column-gap: 12px; } #pause-town { flex: 0 0 84px; padding: 2px 8px; font-size: 14px; line-height: 1.15; text-align: left; } }
@media (prefers-reduced-motion: reduce) { .btn { transition: none; } }

/* ----- the seats: lit windows, shaded windows and the open one ----- */
.seats { display: flex; flex-wrap: wrap; gap: 10px; }
.seat { flex: none; display: block; width: 44px; height: 52px; border: 2px solid var(--edge); border-radius: 0; background: transparent; position: relative; padding: 0; cursor: pointer; }
.seat.lit { background: var(--lit); }
.seat.claimed { background: var(--blind); }
.seat.empty::before { content: ""; position: absolute; top: 0; bottom: 0; left: calc(50% - 1px); width: 2px; background: var(--edge); }
.seat.yours { background: var(--chosen); }
/* the windows say the counted sentence to whoever can see them, so only a screen reader reads it; a failure to count is for everyone */
.counts { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.counts:has(.uncounted) { position: static; width: auto; height: auto; overflow: visible; clip: auto; white-space: normal; font-size: 14px; line-height: 1.5; }

.seat-form { display: grid; gap: 12px; max-width: 460px; }
.seat-form input[type=text], .seat-form input[type=email] { font: 500 16px "Geist Mono", ui-monospace, Menlo, monospace; min-height: 44px; padding: 8px 12px; border: 2px solid var(--edge); background: transparent; color: var(--ink); border-radius: 0; width: 100%; box-sizing: border-box; }
.seat-form fieldset { border: 2px solid var(--edge); padding: 8px 14px 10px; display: grid; gap: 2px; min-width: 0; }
.seat-form legend { padding: 0 6px; }
.opt { display: flex; align-items: center; gap: 10px; min-height: 44px; cursor: pointer; }
.opt input { flex: none; width: 20px; height: 20px; margin: 0; accent-color: var(--ink); }
.own-run { display: none; gap: 8px; }
.claim:has(input[value=own]:checked) .own-run { display: grid; }
.on-loan { display: none; }
.claim:has(input[value=loan]:checked) .on-loan { display: block; }
.cmd { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 12px; background: var(--sunk); padding: 12px 14px; min-width: 0; }
.cmd code { font-size: 16px; overflow-wrap: anywhere; flex: 1 1 200px; min-width: 0; }
.formnote:empty { display: none; }
.mailstep { display: grid; gap: 12px; }
.mailstep[hidden] { display: none; }
.chk { display: flex; gap: 10px; align-items: baseline; cursor: pointer; }
.chk input { flex: none; width: 1.05rem; height: 1.05rem; accent-color: var(--ink); }
.ts:empty { display: none; }

/* ----- the cards over the ground: the storyboard's frames F2 to F7, each section a card in their rules (the same sheet), with the town on both margins and between them (the owner, 5 November 2026) ----- */
.below { --rim: max(8px, env(safe-area-inset-left, 0px), env(safe-area-inset-right, 0px)); --pad: 12px; --gap: 8px; position: relative; z-index: 2; padding-block: 0 var(--rim); }
@media (min-width: 641px) { .below { --rim: max(16px, env(safe-area-inset-left, 0px), env(safe-area-inset-right, 0px)); --pad: 24px; --gap: 24px; } }
/* wide enough that the words inside a card keep the first screen's column, 1,088 px at most */
.below > .wrap { box-sizing: border-box; display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--gap); width: min(1140px, 100% - 2 * var(--rim)); max-width: none; padding: 0; }
.front-page .foot, .front-page .sec, .end { background: var(--bg); border: 2px solid var(--edge); padding-inline: var(--pad); min-width: 0; }
.front-page .foot { display: flex; flex-wrap: wrap; gap: 0 18px; max-width: none; margin: 0; padding-block: 8px; color: var(--ink); }
/* the way round the page, the second time, and the two links under it read as one card */
.front-page .foot.again { border-bottom: 0; margin-bottom: calc(-1 * var(--gap)); }
.foot a, .end a { font-size: 15px; min-height: 44px; display: inline-flex; align-items: center; }
/* The gap between the cards leaves no sliver of the section before in view after a jump: a browser holds its place by the first thing it sees, and a sliver of a section that then fills would push the section the visitor jumped to out of the window (my test of 5 November, 2,040 px). */
.front-page .sec { display: grid; gap: 20px; margin: 0; padding-block: 40px; }
.sec-h { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: baseline; gap: 8px 20px; }
.end { display: flex; flex-wrap: wrap; gap: 0 18px; border-top: 0; padding-block: 0 8px; }
/* a part of a section with the frames' rule above it, where the frame gives it a section of its own */
.ruled { border-top: 2px solid var(--edge); padding-top: 40px; margin-top: 8px; gap: 20px; }
@media (max-width: 640px) { .ruled { padding-top: 28px; } }
.scroll { overflow-x: auto; max-width: 100%; }
@media (max-width: 640px) { .front-page .sec { padding-block: 28px; } }
.log, .cast, .map, .journals, .cites-full { list-style: none; margin: 0; padding: 0; }
.front-page blockquote, .front-page dl, .front-page dd { margin: 0; }
.block { margin: 0; }
.front-page .pause:hover { color: var(--on-lit); }

/* the town with what was just said over it */
.town { position: relative; border: 2px solid var(--edge); overflow: hidden; background: var(--sunk); min-width: 0; }
.town img { display: block; width: 100%; height: auto; aspect-ratio: 16 / 10; object-fit: cover; }
@media (max-width: 640px) { .front-page .town { margin-inline: calc(-1 * var(--pad)); border-width: 2px 0; } }
.bubble { position: absolute; max-width: min(290px, 46%); background: var(--panel); color: var(--ink); border: 2px solid var(--edge); padding: 8px 10px; font-size: 14px; line-height: 1.45; display: grid; gap: 2px; }
.bubble::before, .bubble::after { content: ""; position: absolute; left: 14px; top: 100%; width: 20px; height: 20px; }
.bubble::before { background: var(--edge); clip-path: polygon(0 0, 20px 0, 20px 4px, 16px 4px, 16px 8px, 12px 8px, 12px 12px, 8px 12px, 8px 16px, 4px 16px, 4px 20px, 0 20px); }
.bubble::after { background: var(--panel); clip-path: polygon(2px 0, 18px 0, 18px 2px, 14px 2px, 14px 6px, 10px 6px, 10px 10px, 6px 10px, 6px 14px, 2px 14px); }
.bubble.r::before, .bubble.r::after { left: auto; right: 14px; transform: scaleX(-1); }
.bubble.up::before, .bubble.up::after { top: auto; bottom: 100%; transform: scaleY(-1); }
.bubble.up.r::before, .bubble.up.r::after { transform: scale(-1, -1); }
.bubble.one { left: 58.3%; bottom: 56%; }
.bubble.two { right: 53%; top: 61.5%; }
.bubble .l { display: block; }
.bubble b { font-weight: 400; }
@media (max-width: 800px) { .bubble .l { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 4; overflow: hidden; } }
.bubble .t { font: 500 12px/1.4 "Geist Mono", ui-monospace, Menlo, monospace; color: var(--muted); }
@media (max-width: 640px) { .bubble { display: none; } }

/* the day, by the hour */
.day { position: relative; display: grid; grid-template-columns: repeat(24, minmax(0, 1fr)); grid-template-rows: 52px auto auto; row-gap: 4px; min-width: 720px; padding-top: 28px; }
.day .blk { grid-row: 1; padding: 4px 6px; border: 2px solid var(--edge); margin-right: -2px; font-size: 13px; line-height: 1.25; overflow: hidden; background: var(--panel); color: var(--ink); }
.day .blk.night { background: var(--pane-dark); color: var(--term-fg); }
.day .blk.work { background: var(--place); }
.day .blk.lunch { background: var(--park); }
.day .blk.sit { background: var(--lit); color: var(--on-lit); }
/* a block's words stay readable where the now line crosses them; the last block keeps its right border inside the strip; a job sits on its hour's line */
.day .blk span { position: relative; z-index: 1; background: inherit; }
.day > div.blk:last-of-type { margin-right: 0; }
.day .job { grid-row: 1; align-self: end; justify-self: start; position: relative; width: 10px; height: 10px; margin: 0 0 6px -5px; background: var(--flame); border: 2px solid var(--edge); }
.day .hr, .day .ann { grid-row: 2; justify-self: start; white-space: nowrap; font: 500 12px/1.25 "Geist Mono", ui-monospace, Menlo, monospace; color: var(--muted); }
.day .ann { display: grid; gap: 2px; align-content: start; border-left: 2px solid var(--edge); padding: 2px 0 0 6px; color: var(--ink); }
.day .ann.low { grid-row: 2 / 4; padding-top: 40px; }
.day .ann b { font: 400 13px/1.3 "Geist", ui-sans-serif, system-ui, sans-serif; }
.day .ann b.lit { background: var(--lit); color: var(--on-lit); padding: 0 4px; }
.day .now { position: absolute; top: 22px; height: 62px; width: 4px; margin-left: -2px; background: var(--ink); }
.day .now-t { position: absolute; top: 0; margin-left: -2px; font: 600 12px/1.2 "Geist Mono", ui-monospace, Menlo, monospace; background: var(--ink); color: var(--bg); padding: 3px 6px; white-space: nowrap; }
.day .now-t.late { transform: translateX(-100%); margin-left: 2px; }
.day.compact { min-width: 0; grid-template-rows: 36px auto; }
.day.compact .now { height: 46px; }
/* Between the phone's bar and a width where "lunch at the square" fits in two lines, the words take three, so the bar stands taller and they clear the job marks. The frames show neither width. */
@media (min-width: 641px) and (max-width: 1031px) { .day { grid-template-rows: 76px auto auto; } .day .now { height: 86px; } }

/* the log */
.today { display: grid; gap: 24px; grid-template-columns: 724px minmax(0, 1fr); align-items: start; }
@media (max-width: 1100px) { .today { grid-template-columns: minmax(0, 1fr); } }
/* on a wide screen the town and its totals stay in view while the log scrolls past */
@media (min-width: 1101px) { .today > .side { position: sticky; top: 16px; } }
.log { display: grid; border: 2px solid var(--edge); background: var(--panel); }
.log li { display: grid; gap: 4px; padding: 12px 14px; min-width: 0; }
.log li:nth-child(even) { background: var(--sunk); }
.log .meta { display: flex; flex-wrap: wrap; gap: 2px 12px; font: 500 13px/1.4 "Geist Mono", ui-monospace, Menlo, monospace; color: var(--muted); }
.log .by { font-size: 15px; line-height: 1.4; }
.log .said { font-size: 16px; line-height: 1.5; overflow-wrap: anywhere; }
.log .said a { text-decoration-thickness: 1px; }
.log .cost { font: 400 13px/1.4 "Geist Mono", ui-monospace, Menlo, monospace; color: var(--muted); }
.log-box { max-height: 620px; overflow-y: auto; }
@media (max-width: 640px) { .log-box { max-height: none; overflow: visible; } }

/* the sitting: tonight's two jobs, the ladder and last night's asks */
.sit-top { display: grid; gap: 40px; grid-template-columns: minmax(0, 1.35fr) minmax(0, 1fr); align-items: start; }
.sit-top > * { min-width: 0; }
.sit-top:has(> .panel[hidden]) { grid-template-columns: minmax(0, 1fr); }
@media (max-width: 900px) { .sit-top { grid-template-columns: minmax(0, 1fr); gap: 28px; } }
.sit-left { gap: 24px; }
@media (max-width: 640px) { .sit-left { gap: 20px; } }
.two-jobs { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px; }
@media (max-width: 640px) { .two-jobs { gap: 12px; } }
.tbl { border-collapse: collapse; width: 100%; font-size: 15px; }
.tbl th, .tbl td { padding: 10px; text-align: left; vertical-align: top; }
.tbl thead th { border-bottom: 2px solid var(--edge); font-weight: 600; }
.tbl tbody th { font-weight: 500; }
.tbl .lent { display: block; font-weight: 400; }
.tbl tbody tr:nth-child(even) { background: var(--sunk); }
.tbl tbody tr.won { background: var(--chosen); color: var(--on-lit); }
.tbl tbody tr.won .muted, .tbl tbody tr.won a { color: var(--on-lit); }
.tbl .r { text-align: right; }
.tbl .big { font: 500 20px/1.2 "Geist Mono", ui-monospace, Menlo, monospace; font-variant-numeric: tabular-nums; }
.tbl .sub { display: block; font-weight: 400; }
.tbl .sub:not(.muted) { color: inherit; }
/* a ladder's unranked and loaned rows sit in bodies of their own, ruled off from the ranking */
.tbl tbody + tbody { border-top: 2px solid var(--edge); }
.tbl tr.grp th { font: 500 14px/1.4 "Geist", ui-sans-serif, system-ui, sans-serif; color: var(--muted); padding-block: 14px 4px; }
.tbl-wide { max-width: 760px; }
.front-page .card { border: 2px solid var(--edge); padding: 16px; display: grid; gap: 12px; align-content: start; min-width: 0; background: var(--panel); box-shadow: none; }
.front-page .card.tight { gap: 4px; }
.card-h { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: baseline; gap: 8px; }
.front-page .card-id { font: 500 20px/1.3 "Geist Mono", ui-monospace, Menlo, monospace; }
.cards2 { display: grid; gap: 20px; grid-template-columns: repeat(auto-fit, minmax(min(100%, 380px), 1fr)); }
.kv { display: grid; grid-template-columns: repeat(auto-fit, minmax(92px, 1fr)); gap: 10px 16px; }
.kv div { display: grid; gap: 2px; }
.kv dt { font-size: 13px; color: var(--muted); }
.kv dd { font: 500 18px/1.3 "Geist Mono", ui-monospace, Menlo, monospace; font-variant-numeric: tabular-nums; }
.tag { justify-self: start; font: 500 12px/1.6 "Geist Mono", ui-monospace, Menlo, monospace; border: 2px solid var(--edge); padding: 0 6px; }

/* the residents */
.cast { display: grid; gap: 16px; grid-template-columns: repeat(auto-fill, minmax(min(100%, 200px), 1fr)); }
@media (max-width: 640px) { .cast { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; } }
.cast li { display: grid; min-width: 0; }
.who { display: grid; gap: 8px; align-content: start; border: 2px solid var(--edge); padding: 14px; background: var(--panel); min-width: 0; text-wrap: pretty; }
.who:target { background: var(--chosen); color: var(--on-lit); }
.who:target .muted { color: var(--on-lit); }
.who-h { display: flex; align-items: center; gap: 10px; }
.coat { flex: none; display: block; width: 20px; height: 28px; border: 2px solid var(--edge); }
.front-page .h3 { font: 600 18px/1.35 "Geist", ui-sans-serif, system-ui, sans-serif; }

/* the journals */
.journals { display: grid; gap: 16px; grid-template-columns: repeat(auto-fit, minmax(min(100%, 440px), 1fr)); align-items: start; }
.entry { border: 2px solid var(--edge); padding: 16px; display: grid; gap: 10px; align-content: start; background: var(--panel); min-width: 0; }
.entry-h { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 12px; }
.entry .text { font-size: 18px; line-height: 1.5; max-width: 60ch; text-wrap: pretty; overflow-wrap: anywhere; }
.cites-full { display: grid; gap: 8px; font-size: 15px; line-height: 1.45; overflow-wrap: anywhere; }
.cites-full li { display: grid; gap: 2px; }
.cites-full .when { font: 500 13px/1.4 "Geist Mono", ui-monospace, Menlo, monospace; color: var(--muted); }
.cites-full b { font-weight: 600; }
/* an entry's cites open in place, with no script: a details element whose summary is a 44px control */
.entry details { display: grid; gap: 10px; }
.entry summary { min-height: 44px; display: flex; align-items: center; gap: 10px; cursor: pointer; font-size: 15px; list-style: none; justify-self: start; }
.entry summary::-webkit-details-marker { display: none; }
.entry summary::before { content: "+"; flex: none; display: grid; place-items: center; width: 24px; height: 24px; border: 2px solid var(--edge); font: 500 15px/1 "Geist Mono", ui-monospace, Menlo, monospace; }
.entry details[open] > summary::before { content: "\2212"; }
.entry summary:hover { background: var(--chosen); color: var(--on-lit); }
/* an opened entry takes the whole row on wide screens, and its cites read down two columns */
@media (min-width: 901px) {
  .journals .entry:has(details[open]) { grid-column: 1 / -1; }
  .journals .entry:has(details[open]) .cites-full { display: block; columns: 2; column-gap: 32px; }
  .journals .entry:has(details[open]) .cites-full li { break-inside: avoid; padding-bottom: 12px; }
}

/* the towns */
.map { display: grid; gap: 16px; grid-template-columns: repeat(4, minmax(0, 1fr)); background: var(--park); border: 2px solid var(--edge); padding: 16px; }
@media (max-width: 900px) { .map { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 520px) {
  .map { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; padding: 12px; }
  .map .plot:not(.unbuilt) { grid-column: 1 / -1; }
}
.plot { border: 2px solid var(--edge); background: var(--panel); display: grid; align-content: start; min-width: 0; }
.plot img { display: block; width: 100%; height: auto; aspect-ratio: 6 / 5; object-fit: cover; border-bottom: 2px solid var(--edge); }
.plot .body { padding: 12px; display: grid; gap: 6px; }
.plot .btn { justify-self: start; margin-top: 6px; }
.plot.unbuilt { background: transparent; min-height: 160px; align-content: end; }
.plot.unbuilt .body { background: var(--panel); }
.moon { display: grid; gap: 20px 32px; grid-template-columns: minmax(0, 1fr); align-items: start; }
@media (min-width: 48rem) { .moon { grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr); } }
.moon img { display: block; width: 100%; height: auto; border: 2px solid var(--edge); }
.moontext p { margin: 0 0 12px; max-width: 38rem; }
.front-page .moontext .disclaimer { margin: 0; padding-left: 12px; font-size: .9375rem; color: var(--muted); border-left: 2px solid var(--edge); }

/* ----- the page a mail's link opens: one column, no town ----- */
.front-page .front.narrow { max-width: 40rem; padding: 96px var(--gutter) 64px; }
.front.narrow > * + * { margin-top: 20px; }
.front.narrow .orient { overflow-wrap: anywhere; } /* an address on the stop page can be 250 characters with no place to break */
