/* /play — task H13. Loaded after /style.css, which it does not modify.
 *
 * Two jobs here. The first is the play page's own furniture: the status line,
 * the key card, the action builder, the report, the tally bars. The second is
 * the light theme (part 1 §8.1: "a light mode behind a toggle"), which
 * style.css leaves to this task, and a handful of token corrections the
 * contrast rule of §8.4 forces — chiefly `--rule`, which at #2b2b3d is 1.35:1
 * against the ground and so cannot carry a UI border at the required 3:1.
 *
 * Every pair a page element actually uses is asserted by
 * `hesper/tests/contrast_check.py`, in both themes. If you change a colour
 * here, run it.
 */

:root {
  /* A border must read at 3:1 (§8.4). style.css's --rule is 1.35:1 on the
     ground; this is the same hue, lifted until it passes. */
  --rule: #6a6a8c;
  /* The status line's three levels. Never colour alone: the level's own word
     is in the text as well (part 6 §4.3). */
  --level-ok: #f2ece1;
  --level-amber: #ffb454;
  --level-red: #ffa0a0;
  /* The tally bars of §7.1a. */
  --bar-track: #1e1e2d;
  --bar-fill: #ffd479;
  --bar-against: #7367b5;
  /* The map's marks (design §4.1). Dark first; the light theme lifts the
     selection so it reads on pale tiles. */
  --select: #ffd479;
  --select-inner: #0f1120;
  --marker-other: #9a8fd6;
}

[data-theme="light"] {
  --ground: #f7f5ef;
  --ink: #1a1726;
  --dusk: #463a72;
  --amber: #8a4f00;
  --rule: #77738a;
  --zebra-a: #efece1;
  --zebra-b: #e4e0d2;
  --level-ok: #1a1726;
  --level-amber: #7a3d00;
  --level-red: #9c0d26;
  --bar-track: #e4e0d2;
  --bar-fill: #a8621a;
  --bar-against: #241d38;
  --select: #b86a00;
  --select-inner: #f7f5ef;
  --marker-other: #463a72;
}

/* The theme toggle sits in a bar of its own so it is reachable by Tab first. */

.topbar {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  align-items: center;
  justify-content: space-between;
  border-bottom: 1px solid var(--rule);
  padding: 0.5rem 1.25rem;
}
.topbar nav a { margin-right: 1rem; }

/* The status line ------------------------------------------------------ */

#status-line {
  border: 1px solid var(--rule);
  background: var(--zebra-a);
  padding: 0.5rem 0.85rem;
  margin: 0 0 1rem;
  font-size: 1rem;
  overflow-wrap: anywhere;
}
#status-line .item { white-space: nowrap; }
#status-line .sep { color: var(--dusk); padding: 0 0.35rem; }
#status-line .level-ok { color: var(--level-ok); }
#status-line .level-amber { color: var(--level-amber); }
#status-line .level-red { color: var(--level-red); }
/* The level's word is in the text for a terminal, a screen reader and a
   printer; `.mark` is the same word again, visible, so that a sighted reader
   who cannot tell the two ambers apart still reads which is which. */
#status-line .mark { color: inherit; }

/* Never `display: none`: a screen reader must reach it. */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* Sections ------------------------------------------------------------- */

.panel {
  border: 1px solid var(--rule);
  padding: 0.75rem 1rem 1rem;
  margin: 0 0 1.25rem;
}
.panel > h2 { margin-top: 0; }

.row { display: flex; flex-wrap: wrap; gap: 0.5rem; align-items: flex-end; }
.row > * { margin: 0; }

label { display: block; color: var(--dusk); }
label .req { color: var(--amber); }

input, select, textarea {
  font: inherit;
  color: var(--ink);
  background: var(--zebra-a);
  border: 1px solid var(--rule);
  border-radius: 2px;
  padding: 0.3rem 0.45rem;
  max-width: 100%;
}
textarea { width: 100%; min-height: 5rem; }

/* The door's own fields. H78 added the invitation box beside the reservation
   one; both are a touch target on a phone, so the whole form is held to the
   44 px of §8.1 rather than the invitation box alone being taller than the
   field next to it. Colours and focus come from the shared rules above and
   from style.css, which every other field on this page uses too. */
#register-form input, #register-form select { min-height: 44px; }
#reg-invite, #reg-reservation { width: 16rem; }

fieldset { border: 1px solid var(--rule); border-radius: 2px; margin: 0 0 1rem; }
legend { color: var(--dusk); padding: 0 0.4rem; }

pre, code {
  font-family: inherit;
  background: var(--zebra-a);
  border: 1px solid var(--rule);
  color: var(--ink);
}
pre {
  font-size: 0.875rem;
  padding: 0.6rem 0.75rem;
  overflow-x: auto;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  margin: 0 0 0.75rem;
}
code { padding: 0 0.25em; border-radius: 2px; }
pre code { border: 0; padding: 0; background: none; }

.key-value { overflow-wrap: anywhere; }

.warn {
  border-left: 3px solid var(--level-amber);
  padding-left: 0.75rem;
  color: var(--ink);
}

.error { color: var(--level-red); }
.error::before { content: "Refused: "; }

#log { margin: 0; }
#log p { margin: 0 0 0.35rem; }

.progress {
  border: 1px solid var(--rule);
  background: var(--bar-track);
  height: 0.9rem;
  width: 100%;
  max-width: 30rem;
  margin: 0.35rem 0;
}
.progress > span { display: block; width: 0; height: 100%; background: var(--bar-fill); }

/* The landing grid: a small map section, one button a tile ------------- */

#land-grid {
  display: grid;
  gap: 1px;
  margin: 0.5rem 0;
  overflow-x: auto;
}
#land-grid button {
  padding: 0;
  width: 1.35rem;
  height: 1.35rem;
  min-width: 0;
  font-size: 0.7rem;
  line-height: 1.35rem;
  text-align: center;
  border: 1px solid var(--rule);
  background: var(--zebra-b);
  color: var(--ink);
}
#land-grid button[disabled] { color: var(--dusk); cursor: not-allowed; }
#land-grid button[aria-pressed="true"] { background: var(--amber); color: var(--ground); }

/* The tally of §7.1a --------------------------------------------------- */

.tally { margin: 0 0 1rem; }
.tally h3 { margin: 0 0 0.35rem; }
.tally .kind { margin: 0 0 0.9rem; }
.tally .kind-label { display: block; }
.tally .bar {
  display: flex;
  border: 1px solid var(--rule);
  background: var(--bar-track);
  height: 1rem;
  margin: 0.25rem 0;
  max-width: 34rem;
}
.tally .bar .for { background: var(--bar-fill); }
.tally .bar .against { background: var(--bar-against); }
.tally .majority { color: var(--dusk); }
.tally .verdict { color: var(--ink); }
.tally .carried { color: var(--ink); }

/* The world: the map is the hero, the panel is beside it ---------------- */

/* One column below about 900 px, in source order: map, then the task, then
   the report last (§3). Above it, the map is the hero and the task column is
   320–360 px beside it, with the report under the map. */
.play-world {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1.5rem;
  margin: 0 0 1.5rem;
}
@media (min-width: 900px) {
  .play-world {
    /* clamp(20rem, 24vw, 22.5rem) is 320 px to 360 px at a 16 px root — the
       width §3 asks for, and narrower than the 384–480 px this column used
       to take from the map. */
    grid-template-columns: minmax(0, 1fr) clamp(20rem, 24vw, 22.5rem);
    grid-template-areas: "map task" "report task";
    align-items: start;
  }
  .play-map-column { grid-area: map; }
  #tile-panel { grid-area: task; }
  #report-panel { grid-area: report; }
  /* Sticky, and no scroll area of its own: §3 asks for one page scroll, and
     a panel that scrolls inside itself hid both the plan and Send from
     anyone who had scrolled the page instead. */
  #tile-panel { position: sticky; top: 1rem; align-self: start; }
}

/* `#map` in style.css carries an id, so this rule needs one too. */
#map.play-map {
  height: 62vh;
  min-height: 20rem;
  position: relative;
  border: 1px solid var(--rule);
  border-radius: 4px;
  background: var(--ground);
}
@media (max-width: 899px) { #map.play-map { height: 46vh; } }

.map-links { margin: 0.5rem 0 0.25rem; }
button.linkish {
  background: none;
  border: 0;
  padding: 0.35rem 0;
  margin-right: 1.25rem;
  color: var(--amber);
  text-decoration: underline;
  text-underline-offset: 2px;
  min-height: 44px;
}
button.linkish:hover { border: 0; }

/* "Open plan" belongs to the phone's summary view and to nothing else: on a
   wide screen the plan is already on the same screen. */
@media (min-width: 601px) { #open-plan-row { display: none; } }

/* The nearby tiles (§4): the map is not the only way to choose a place ---- */

table.nearby {
  border-collapse: collapse;
  margin: 0.5rem 0 0.75rem;
  width: 100%;
}
table.nearby caption {
  text-align: left;
  color: var(--dusk);
  padding: 0 0 0.25rem;
}
table.nearby th {
  text-align: left;
  font-weight: normal;
  color: var(--dusk);
  padding: 0.1rem 0.75rem 0.1rem 0;
  white-space: nowrap;
}
table.nearby td { padding: 0.1rem 0; }
button.nearby-pick {
  min-height: 44px;
  min-width: 6rem;
  padding: 0.2rem 0.6rem;
  background: var(--zebra-a);
  border: 1px solid var(--rule);
  color: var(--ink);
}
/* Chosen: an outline, and the word "chosen" beside it — colour alone never
   carries a state (§3). */
button.nearby-pick[aria-current="true"] {
  border: 2px solid var(--select);
  font-weight: bold;
}

/* Carrying, one line an item with its own bulk (H93) -------------------- */

ul.carry-list {
  list-style: none;
  margin: 0;
  padding: 0;
}
ul.carry-list li { margin: 0 0 0.15rem; }

/* The tile panel -------------------------------------------------------- */

#tile-panel { margin: 0; }
#tile-panel h2 { font-size: 1.125rem; margin: 0 0 0.25rem; }
#tile-sub { margin: 0 0 0.75rem; color: var(--dusk); }
#tile-facts p { margin: 0 0 0.25rem; }
#tile-facts { margin: 0 0 1rem; }

.section-heading {
  font-size: 0.8125rem;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--dusk);
  border-top: 1px solid var(--rule);
  padding-top: 0.75rem;
  margin: 1rem 0 0.5rem;
}

#tile-actions { display: flex; flex-direction: column; gap: 0.5rem; }
#tile-actions .act {
  display: block;
  width: 100%;
  text-align: left;
  padding: 0.65rem 0.85rem;
  border-radius: 2px;
  min-height: 44px;
}
#tile-actions .act .line { display: flex; justify-content: space-between; gap: 0.75rem; }
#tile-actions .act .cost {
  font-size: 0.875rem;
  font-weight: 500;
  font-variant-numeric: tabular-nums;
}
#tile-actions .act .reason {
  display: block;
  font-size: 0.875rem;
  color: var(--dusk);
}
#tile-actions .act[disabled] { color: var(--dusk); cursor: not-allowed; }
#tile-actions .fields { display: flex; flex-wrap: wrap; gap: 0.5rem; align-items: flex-end; }
#tile-actions .fields label { font-size: 0.875rem; }
/* 44 px targets, on the inputs as well as the buttons: the quantity box
   beside a pick-up or a put-down is as much a touch target as the row
   under it, and it was 37 px tall. */
#tile-actions .fields input { width: 6rem; min-height: 44px; }

/* What can be built here: a list with a picture, never a slug to type ---- */

.build-list {
  border: 1px solid var(--rule);
  border-radius: 2px;
  padding: 0.5rem 0.65rem;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}
.build-row { display: flex; gap: 0.6rem; align-items: flex-start; }
.build-row .sprite {
  width: 24px;
  height: 24px;
  flex: none;
  image-rendering: pixelated;
  margin-top: 0.2rem;
}
.build-row .build-body { display: flex; flex-direction: column; gap: 0.2rem; flex: 1; }
.build-row .purpose { font-size: 0.875rem; }
.build-row .price { font-size: 0.875rem; color: var(--dusk); }
.build-row .reason { font-size: 0.875rem; color: var(--dusk); }
.build-row.off strong, .build-row.off .purpose { color: var(--dusk); }
.build-row button[disabled] { color: var(--dusk); cursor: not-allowed; }
.build-row button { text-align: left; min-height: 44px; }

/* This turn: the queue and the unsent rows in one list ------------------- */

/* One <ol> a round, inside a plain div, so the numbers never skip. */
#panel-batch { margin: 0 0 0.5rem; }
#panel-batch .batch-group { margin: 0; padding-left: 1.5rem; }
#panel-batch li.queued .what { color: var(--dusk); }
#panel-batch .queued-mark {
  font-size: 0.875rem;
  color: var(--dusk);
  margin-right: 0.4rem;
}
/* Where the world had to cut the plan into a second round. Most plans are one
   round and this never appears; when it does it is a divider, not a row. */
#panel-batch .round-head {
  margin: 0.4rem 0 0.25rem;
  font-size: 0.875rem;
  color: var(--dusk);
}
#panel-batch .after {
  display: block;
  font-size: 0.875rem;
  color: var(--dusk);
}
/* The server's own sentence for a refusal, kept beside the row it refused. */
#panel-batch .refused {
  display: block;
  font-size: 0.875rem;
  color: var(--level-red);
}
#panel-batch li { margin: 0 0 0.25rem; }
/* The row's remove control was 26x31 px. It is the only way to take a
   draft row back, so it gets a full target like everything else. */
#panel-batch button {
  padding: 0.1rem 0.45rem;
  margin-left: 0.5rem;
  min-width: 44px;
  min-height: 44px;
}
#panel-total { white-space: pre-line; }
#panel-total.at-budget { color: var(--level-red); }
#panel-total.near-budget { color: var(--level-amber); }

button.primary {
  background: var(--amber);
  color: var(--ground);
  border-color: var(--amber);
  padding: 0.65rem 0.85rem;
  width: 100%;
  min-height: 44px;
}

/* A Send with nothing to send must not look like a Send that will do
   something. The other three disabled controls on the page grey their text;
   Send is filled when it is live, so its disabled state drops the fill too,
   or a dead button would still read as the brightest thing on the screen
   (the human pressed one). --dusk on --zebra-a is a checked pair. */
#panel-send[disabled] {
  background: var(--zebra-a);
  color: var(--dusk);
  border-color: var(--rule);
  cursor: not-allowed;
}

/* Send is the only filled control on this page (review F, item 7): a filled
   button is a promise that something will be sent to the world, and only one
   button on /play does that. Everything else that wants to be noticed — the
   walkthrough's Next, the top bar's door to the page you are already on — is
   drawn as a line instead. */
button.outlined {
  background: var(--zebra-a);
  color: var(--amber);
  border-color: var(--amber);
  font-weight: 700;
  min-height: 44px;
  padding: 0.5rem 0.85rem;
}

@media (prefers-reduced-motion: reduce) {
  * { animation: none !important; transition: none !important; }
}

/* ---- the inline Send confirm (D10) --------------------------------- */
/* No new colours: the existing tokens only, so the contrast script has
   nothing new to check. */
#send-confirm {
  border: 1px solid var(--rule);
  background: var(--zebra-a);
  border-left: 3px solid var(--amber);
  padding: 0.6rem 0.8rem;
  margin: 0 0 0.8rem;
}
#send-confirm p { margin: 0 0 0.5rem; }
#send-confirm p:last-child { margin: 0; }

/* The panel's own feedback line: what the log at the top of the page used
   to be, now beside the thing it talks about. */
.panel-feedback {
  margin-top: 0.8rem;
  border-top: 1px solid var(--rule);
  padding-top: 0.5rem;
  color: var(--dusk);
}
.panel-feedback p { margin: 0 0 0.3rem; }

/* ---- the report, in collapsed sections (H41) ------------------------ */
.report-section {
  border-top: 1px solid var(--rule);
  padding: 0.35rem 0;
}
.report-section > summary {
  cursor: pointer;
  color: var(--ink);
  padding: 0.15rem 0;
}
.report-section[open] > summary { color: var(--amber); }

/* ---- the walkthrough (design §7) ------------------------------------ */
.tour {
  position: fixed;
  right: 1rem;
  bottom: 1rem;
  z-index: 1000;
  max-width: 22rem;
  padding: 0.8rem 1rem;
  border: 1px solid var(--rule);
  border-left: 3px solid var(--amber);
  background: var(--zebra-a);
}
.tour .tour-title { margin: 0 0 0.2rem; font-size: 1rem; }
.tour p { margin: 0 0 0.5rem; }
.tour-target { outline: 2px solid var(--amber); outline-offset: 2px; }

/* The head of the play page: the lede and the status strip. On a wide screen
   they are two paragraphs, one under the other, as they always were. The
   phone's two-column arrangement is in the ≤600 px block below. The old
   `.page-tools` line is gone: the console link is in the footer and the theme
   is in the top bar, on every page (session 24, item 20). */

/* What you know is in the ground (H48) ------------------------------------
 *
 * Deposit marks are drawn only here, on /play, only for the signed citizen,
 * from `GET /api/knowledge`. Part 9 §2 says what the mark is — a notch in the
 * tile's corner — but not how "I know clay is here" differs from "I know clay
 * is here and how much": the decision taken with H48 is **outline for the kind,
 * filled for the kind and the quantity**. The colour is `--marker-other`, the
 * map's neutral mark colour, already in the contrast table; amber stays
 * reserved for *yours*.
 */
.hesper-deposit {
  background: transparent;
  border: 2px solid var(--marker-other);
  border-radius: 2px;
  box-sizing: border-box;
  transform: rotate(45deg);
  pointer-events: none;
}
.hesper-deposit.is-qty { background: var(--marker-other); }
.map-legend .swatch-deposit {
  background: transparent;
  border: 2px solid var(--marker-other);
  border-radius: 2px;
  transform: rotate(45deg);
}

/* Farmable soil (H57) is not a stock and never wears the filled "quantity
   known" mark: a number on it would say it is running out. Its mark is its
   own — an outlined square, upright rather than turned, with a dot in the
   middle, the seed in the field — drawn in the same neutral mark colour so no
   new colour enters the contrast table. */
.hesper-deposit.is-farmed {
  background: transparent;
  border: 2px solid var(--marker-other);
  border-radius: 1px;
  /* No `position` and no `transform` here: Leaflet positions every icon
     absolutely with an inline translate3d. A `position: relative` on this
     two-class rule outranked `.leaflet-marker-icon`, put each farmed mark
     back into normal flow, and stacked all of them into one column
     (Round 27). The ::after dot centres because the icon is positioned by
     Leaflet already. */
}
.hesper-deposit.is-farmed::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: 2px;
  height: 2px;
  margin: -1px 0 0 -1px;
  background: var(--marker-other);
}
.map-legend .swatch-farmed {
  background:
    radial-gradient(circle at 50% 50%,
                    var(--marker-other) 0 1.2px, transparent 1.2px);
  border: 2px solid var(--marker-other);
  border-radius: 1px;
}

/* The ground line, between the tile's facts and what you can do on it. */
#tile-ground p { margin: 0.4rem 0; }
#tile-ground .unknown { color: var(--dusk); }

/* ---- the phone (design §2.2) -------------------------------------------
 *
 * At 375×740 the review of 2026-09-07 measured 406 px of chrome above the
 * map, the map starting at y 447 and Send at y 1851 of a 3353 px page: a
 * first screen with no map and no button on it. §2.2 asks for the map at the
 * top of the screen and the tile panel as a sheet at the bottom. So, in
 * order: the title goes (the top bar already says *Play*), the lede's words
 * go and its `?` stays, the tools line and the `?` share one small line, the
 * status strip becomes one line that scrolls sideways rather than four that
 * stack, and the map takes half the screen at the top. Nothing is deleted:
 * every word that goes is still in the walkthrough or one scroll away.
 *
 * The panel below the map *was* a sheet fixed to the floor of the screen.
 * H93 took that out: §3 rules out an overlay that hides the selected tile and
 * a second scroll area inside the page, so the panel is an ordinary section
 * under the map with Summary / Actions / Details controls in its own flow.
 */
@media (max-width: 600px) {
  /* Every pixel above the map is a pixel of map lost. `#topbar`'s own file is
     not touched; the gap under it is closed from here, on this page only.
     `body` is in the selector because play.css is linked *before* topbar.css
     and `#topbar { margin: 0 0 1.5rem }` there would otherwise win on order —
     which is exactly what it did until session 24, and 24 px of the phone's
     chrome were that one line. */
  body #topbar { margin-bottom: 0.1rem; }
  main > h1 { display: none; }
  .lede .lede-text { display: none; }

  /* One row: the status strip on the left, the `?` on the right, in the
     middle of it. The strip is the wide one because it is the one with
     words in it; the `?` keeps a 44 px target beside it. */
  .play-head {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: center;
    gap: 0.4rem;
    margin: 0 0 0.2rem;
  }
  .play-head .lede {
    grid-column: 2;
    grid-row: 1;
    margin: 0;
    font-size: 0.9rem;
  }
  /* The margin goes only inside the head's grid: `/console` carries the same
     strip as a paragraph of its own and still wants air under it. */
  .play-head #status-line { grid-column: 1; grid-row: 1; margin: 0; }
  .lede button.linkish {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 44px;
    min-height: 44px;
    margin: 0;
  }

  /* All five items stay, and they wrap: a line you have to drag sideways to
     read is a line you do not read (design §2.2). The items themselves do
     not break — `#status-line .item` is still nowrap — so what wraps is the
     gaps between them. */
  #status-line {
    margin: 0 0 0.5rem;
    padding: 0.2rem 0.4rem;
    font-size: 0.8rem;
    line-height: 1.2;
  }
  /* Narrower separators: on 287 px of line, six of them at 0.35 rem a side
     cost most of a line of reading. */
  #status-line .sep { padding: 0 0.2rem; }
  /* The world's date (session 46) is the one item a phone drops, with the
     separator before it: forty more characters wrap the strip to a third
     line and push the map past the first 130 px (design §2.2, and the
     browser check measured 141). The report header carries the same date,
     and the strip's aria-label still says it. */
  #status-line .item-date,
  #status-line .sep:has(+ .item-date) { display: none; }

  /* Half the screen, at the top of it. */
  #map.play-map { height: 50vh; min-height: 0; }
  .play-world { gap: 0.75rem; margin-bottom: 0.75rem; }

  /* Every pixel between the map and the task is a pixel of task pushed off
     the first screen. The two map links share a row, and the ten-item legend
     keeps all ten items — none is dropped, they are the key to the map — at a
     smaller sprite and a tighter line. Nothing here hides anything: the text
     is the same text, and `inner_text` still reads all of it. */
  .map-links {
    display: flex;
    flex-wrap: wrap;
    gap: 0.75rem;
    margin: 0.25rem 0 0;
  }
  .map-links button.linkish { margin-right: 0; }
  .map-legend {
    font-size: 0.8rem;
    line-height: 1.35;
    margin: 0.25rem 0;
  }
  .map-legend .legend-sprite { width: 20px; height: 20px; }
  .hover { margin: 0; }

  /* The task panel, in normal document flow (§3).
     It used to be `position: fixed` on the floor of the screen, 45vh tall,
     scrolling inside itself, with 47vh of padding under the page to keep the
     footer clear. That is the overlay with the nested scroll trap §3 rules
     out: the sheet covered the selected tile, the page had two scrolls that
     fought each other, and at 200 % zoom or with the keyboard open there was
     nothing left of it. It is a section under the map now, and the page has
     one scroll. */
  #tile-panel {
    margin: 0 0 0.75rem;
    border: 1px solid var(--rule);
    border-radius: 4px;
    background: var(--ground);
  }
  #tile-panel .send-row { margin: 0.75rem 0 0.25rem; }
  #tile-panel .send-row button { width: 100%; }
  main { padding: 0.15rem 0.6rem 1.5rem; }

  /* Summary / Actions / Details (§3). Three controls in the flow of the
     panel, each showing one part of it; the selection and every form value
     live in the page's own state and in the DOM, which is not rebuilt when
     the view changes, so nothing typed is lost by switching. */
  .panel-views {
    display: flex;
    gap: 0.4rem;
    margin: 0 0 0.5rem;
  }
  .panel-views button {
    flex: 1 1 0;
    min-height: 44px;
    padding: 0.3rem 0.2rem;
    background: var(--zebra-a);
    border: 1px solid var(--rule);
    color: var(--ink);
  }
  .panel-views button[aria-pressed="true"] {
    background: var(--amber);
    color: var(--ground);
    font-weight: bold;
  }

  /* What each view shows. The tile's heading and its own loading/failure
     line are in all three: a citizen must always be able to see which place
     the panel is about. */
  #tile-panel.view-summary #tile-facts,
  #tile-panel.view-summary #tile-ground,
  #tile-panel.view-summary #tile-nearby,
  #tile-panel.view-summary #do-h,
  #tile-panel.view-summary #tile-actions,
  #tile-panel.view-summary #turn-h,
  #tile-panel.view-summary #panel-batch,
  #tile-panel.view-summary .send-row,
  #tile-panel.view-summary #log,
  #tile-panel.view-actions #tile-facts,
  #tile-panel.view-actions #tile-ground,
  #tile-panel.view-actions #tile-nearby,
  #tile-panel.view-actions #open-plan-row,
  #tile-panel.view-details #do-h,
  #tile-panel.view-details #tile-actions,
  #tile-panel.view-details #turn-h,
  #tile-panel.view-details #panel-batch,
  #tile-panel.view-details #panel-total,
  #tile-panel.view-details .send-row,
  #tile-panel.view-details #open-plan-row { display: none; }

  /* The walkthrough never takes more than the lower half of the screen
     (review F, worst thing 3). */
  .tour {
    left: 0.5rem;
    right: 0.5rem;
    bottom: 0.5rem;
    max-width: none;
    max-height: 50vh;
    overflow-y: auto;
  }
}

/* The top bar's invited-landings line (play.js `paintTopbarDoors`). It is a
   `topbar-who` so that it shrinks and ellipsises at 320 px like the line it
   replaces — topbar.css, session 46: a door never shrinks, the sentence
   beside it does — and it is a link, so it is underlined, in the colour of a
   thing that will happen, and it has the height of a finger. The padding is
   vertical only: any horizontal padding would cost the row width it does not
   have at 320 px. */
#topbar a.topbar-invited {
  color: var(--amber, #ffd479);
  text-decoration: underline;
  padding: 0.7rem 0;
}
