/* =============================================================================
 * The Great Hall — the public, read-only window onto kingdom chat.
 *
 * The document itself is assembled by the serverless function (see "THE GREAT
 * HALL, IN PUBLIC" in api/index.ts); this file and hall.js are the two static
 * assets it links. Splitting them out rather than inlining is deliberate: the
 * page is polled and re-rendered often enough that its HTML wants a short edge
 * cache, while the stylesheet and the script never change between visits and
 * should be cached hard by the browser. Inlining them would re-download the
 * whole design every thirty seconds for no benefit.
 *
 * NO EXTERNAL REQUESTS. No font CDN, no icon set, no background fetched from
 * anywhere. Every colour here comes from a variable site.css and forum.css
 * already define, every glyph is text, and the one piece of decoration (the
 * live dot) is drawn with a border-radius and a keyframe. That is not
 * minimalism for its own sake — the site's CSP forbids third-party origins and
 * the game ships an offline mode, so an asset from another host is not a
 * slower page, it is a broken one.
 *
 * Vanilla CSS, no build step: this file is served exactly as written.
 * ========================================================================== */

/* ── The status bar ────────────────────────────────────────────────────────
 * "Listening to the realm" has to be VISIBLE and it has to be honest. A live
 * page that gives no sign of being live is indistinguishable from a screenshot,
 * and a page that claims to be live while its poller is dead is worse than
 * either — so hall.js drives this same strip through three states (listening,
 * paused, and lost-the-thread) and the colours below are how each reads at a
 * glance without needing the words.
 */
.hall-bar {
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
  margin: 18px 0 10px;
}
/* THE `hidden` ATTRIBUTE NEEDS HELP HERE, and it is the kind of bug that only
   shows up in the render nobody looks at. The server ships the pause button
   with `hidden` so that a reader without JavaScript is never offered a control
   that cannot work — but site.css gives `.btn` an explicit
   `display: inline-block`, and an author stylesheet beats the user agent's
   `[hidden] { display: none }`. So the button appeared, dead, on exactly the
   page it was hidden for. This puts it back. */
.hall-toggle[hidden] { display: none; }

.hall-status {
  display: inline-flex; align-items: center; gap: 9px; margin: 0;
  font-size: 13.5px; color: var(--muted);
}
.hall-dot {
  width: 9px; height: 9px; border-radius: 50%; flex: 0 0 auto;
  background: #6fd48a; box-shadow: 0 0 0 0 rgba(111, 212, 138, 0.55);
  animation: hall-pulse 2.4s ease-out infinite;
}
/* PAUSED IS NOT AN ERROR. A reader who stopped the feed on purpose should see
   a calm, deliberate state — steady gold, no pulse — not the same alarm colour
   the page uses when it has genuinely lost contact. */
.hall-bar.is-paused .hall-dot { background: var(--gold-dim); animation: none; box-shadow: none; }
.hall-bar.is-stalled .hall-dot { background: #c9736b; animation: none; box-shadow: none; }
@keyframes hall-pulse {
  0%   { box-shadow: 0 0 0 0 rgba(111, 212, 138, 0.5); }
  70%  { box-shadow: 0 0 0 7px rgba(111, 212, 138, 0); }
  100% { box-shadow: 0 0 0 0 rgba(111, 212, 138, 0); }
}
/* Someone who has asked their system for less motion has asked for less of
   THIS: a dot that throbs forever at the top of a page is exactly the kind of
   perpetual animation the preference exists to stop. The state still reads —
   the colour carries it on its own. */
@media (prefers-reduced-motion: reduce) {
  .hall-dot { animation: none; }
}

/* ── The feed ──────────────────────────────────────────────────────────────
 * A scroll box rather than an ever-growing page, and the reason is autoscroll:
 * the feed follows the newest line, and a page that scrolls ITSELF while you
 * are reading the paragraph below it is hostile. Keeping the movement inside a
 * bounded box means the newest line is always in view and the rest of the page
 * stays exactly where the reader left it.
 *
 * 62vh, not a pixel height: on a phone this is most of the screen and on a
 * desktop it is a comfortable panel, and neither needs a breakpoint to say so.
 */
.hall-feed {
  list-style: none; margin: 0; padding: 8px 0;
  max-height: 62vh; overflow-y: auto; overscroll-behavior: contain;
  background: linear-gradient(180deg, rgba(20, 27, 40, 0.55), rgba(12, 16, 23, 0.5));
  border: 1px solid var(--line); border-radius: 12px;
}
/* The keyboard has to be able to reach a scrollable region, and a region that
   can be focused must SHOW that it is. Both halves matter: hall.js gives the
   list tabindex="0" so it is reachable at all, and this is what makes the
   focus visible when it lands. */
.hall-feed:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }

/* TWO CELLS, NOT ONE FLOW. The clock sits in its own fixed column and the
   words in the other, so a long remark wraps under ITSELF rather than back
   under the timestamp — which is what an inline layout does, and it makes a
   busy hall read as a ragged block instead of as a transcript. Grid rather
   than float or a hanging indent because it is the only one of the three that
   stays correct when the clock's text changes width, which it does the moment
   hall.js rewrites UTC into the reader's own locale. */
.hall-line {
  display: grid; grid-template-columns: 108px minmax(0, 1fr); column-gap: 10px;
  padding: 7px 16px; font-size: 14.5px; line-height: 1.55;
  border-left: 3px solid transparent;
}
.hall-line + .hall-line { border-top: 1px solid rgba(227, 193, 104, 0.06); }
/* DELIBERATELY NOT white-space: nowrap. The server writes a full UTC stamp
   ("8 Aug, 19:32 UTC") because the document is cached and shared, and the
   reader's script shortens it to their own locale ("19:32") once it runs. With
   nowrap, the long server form overflows the column and collides with the
   speaker's name for exactly the readers who have no script to fix it — which
   is the one audience this page promised to serve properly. Wrapping to a
   second short line is the graceful version of that. */
.hall-when {
  font-variant-numeric: tabular-nums; font-size: 11.5px; color: var(--muted);
  padding-top: 3px;
}
.hall-body { min-width: 0; }
.hall-who { font-weight: 700; color: var(--gold-bright); }
.hall-who::after { content: ":"; color: var(--muted); font-weight: 400; }
/* overflow-wrap:anywhere, not word-break: a chat line is a place someone can
   paste a 300-character unbroken string, and without this one row would push
   the whole feed into a horizontal scrollbar. */
.hall-said { color: var(--text); overflow-wrap: anywhere; margin-left: 6px; }
/* .hall-who is followed by the RESIDENT tag on Resident lines, so the colon
   would land between the name and its label. Suppress it there and let the
   space after the tag do the separating. */
.hall-line.is-resident .hall-who::after { content: ""; }
.hall-line .tag.resident + .hall-said { margin-left: 8px; }

/* A Resident's line is tinted, faintly. The tag is the statement of fact; this
   is what makes the ratio of people to characters legible at a glance while
   scrolling, without shouting. Deliberately weaker than the board's own
   treatment: a whole page of them should still read as a conversation. */
.hall-line.is-resident { border-left-color: rgba(150, 170, 200, 0.28); }
.hall-line.hall-quiet { color: var(--muted); font-style: italic; }

/* A line that arrived while you were watching gets one gentle sweep, so the
   page's liveness is something you SEE rather than something you are told.
   Once, then never again — a permanent highlight would turn into a stripe. */
@keyframes hall-arrive {
  from { background: rgba(227, 193, 104, 0.13); }
  to   { background: transparent; }
}
.hall-line.is-new { animation: hall-arrive 2.2s ease-out 1; }
@media (prefers-reduced-motion: reduce) {
  .hall-line.is-new { animation: none; }
}

/* ── The rest of the page ──────────────────────────────────────────────── */
.hall-honesty { margin-top: 16px; }
.hall-honesty .tag.resident { margin-left: 2px; margin-right: 2px; }
.hall-cta {
  margin: 30px 0 10px; padding: 22px; border-radius: 14px;
  border: 1px solid var(--line);
  background: linear-gradient(180deg, rgba(227, 193, 104, 0.07), rgba(20, 27, 40, 0.35));
}
.hall-cta h2 { margin: 0 0 6px; font-family: var(--display); color: var(--gold); font-size: 24px; }
.hall-cta p { margin: 0 0 12px; }
.hall-cta p:last-child { margin-bottom: 0; display: flex; gap: 10px; flex-wrap: wrap; }

/* ── TOUCH TARGETS ─────────────────────────────────────────────────────────
 *
 * The house rule, applied to this page's own controls: Apple's minimum
 * tappable area is 44x44pt, which is roughly the contact patch of an adult
 * fingertip, and below it a missed tap is not the user's fault. site.css gives
 * .btn a 38px box and .btn.small less than that, which is fine for a mouse and
 * not fine for a thumb.
 *
 * KEYED TO THE INPUT, NOT THE VIEWPORT — the same reasoning the game's
 * styles.css sets out at the end of the file. `pointer: coarse` asks the real
 * question ("is a finger driving this?") where a width breakpoint asks a proxy
 * that is wrong at both ends: a large tablet is a finger and a narrow desktop
 * window is a mouse. The desktop layout is therefore left exactly as it is.
 *
 * The pause toggle is the control that matters most here. It is the one thing
 * on the page that a reader NEEDS to hit — it is how you stop the feed moving
 * under your eyes mid-sentence — and a control you cannot reliably hit reads
 * as a broken page rather than as a mis-tap.
 */
@media (pointer: coarse) {
  .hall-toggle,
  .hall-cta .btn { min-height: 44px; display: inline-flex; align-items: center; }
  /* A finger scrolling a bounded box needs the rows to be separable; 7px of
     padding puts two lines within a thumb-width of each other. */
  .hall-line { padding-top: 9px; padding-bottom: 9px; }
  /* The timestamp column costs 108px that a phone would rather spend on words,
     so on a touch device the grid collapses to one column and the clock takes
     its own row above the line instead of competing with it. */
  .hall-line { grid-template-columns: minmax(0, 1fr); row-gap: 1px; }
  .hall-when { padding-top: 0; }
  .hall-said { margin-left: 4px; }
}
