/*
 * THE PAPER, AND WHAT SITS ON IT. The tokens every other sheet reads, the
 * reset, the header, and the three columns a night is laid out in.
 *
 * Five sheets rather than one, because it was 1,874 lines with a single
 * section heading in it and no way to find anything. index.html names them in
 * the order they cascade, which is also the order they are read in.
 */

:root {
  --bg: #e7e3da;          /* paper the plan is drawn on */
  --figbg: #f3eee1;       /* and the beige a drawing of it is shown on */
  --panel: #fbf9f5;
  --line: #d2ccbf;
  /*
   * THE TABLE THE ROWS ARE LAID ON: a tray cut into the page, where --panel is
   * a card laid on top of it. The two are the same grammar -- one inset, one
   * hairline, one corner -- saying which of the two kinds of thing this is.
   * --plate is the nameplate riding at the head of a row, which has to be
   * opaque: it sits still while the row scrolls underneath it.
   */
  --tray: #ded8cb;
  --trayline: #c8c1af;
  --plate: #f0ece2;
  --plateMine: #f7f4ec;
  --ink: #23262c;
  --dim: #77726a;
  --wall: #23262c;
  --accent: #1f6f9c;
  --gold: #9a6d10;
  /* the museums, wherever a colour stands for a side -- see .bdot.museum */
  --museum: #1979a9;
  /*
   * HOW BIG A CARD IS ON A TRAIL, and everything the slots derive from it. A
   * trail card was half size, which is small for the thing the whole game is
   * read from -- and there is room, because the board column is wider than any
   * row usually laid in it. Change --pile and the slots, the piles, the fan and
   * the reserved row height all follow.
   */
  --pile: .64;                                  /* of the 63 x 86 a card is */
  --lay: 6px;                                   /* each card below the last */
  --nlay: 15px;                                 /* on the slot about to be played */
  --fan: 34px;                                  /* fanned apart by the pointer */
  /*
   * The card box and the height a row reserves. These are worked out on the
   * ROW, not here, because a custom property resolves where it is declared --
   * so a row that wants smaller cards can say --pile and have the rest follow.
   * --rowh is the exception and resolves HERE on purpose, so the space a row
   * reserves is the full size whatever the row itself is drawn at -- the board
   * would move under an opened ribbon otherwise.
   *
   * A CARD STARTS AT THE TOP OF ITS SLOT. There used to be a gap above it for
   * the slot number; the numbers are gone, and the gap went with them -- it
   * was the one thing keeping the first card of a row off the line the side
   * column starts on. What is reserved below is the deepest a pile ever goes:
   * the slot about to be played, carrying a museum card, one special over it
   * and the space the burglar's own card drops into.
   */
  --traypad: 6px;
  --rowh: calc(86px * var(--pile) + var(--nlay) * 2.5 + 4px
               + var(--traypad) * 2 + 2px);
  /*
   * AND HOW TALL A RIBBON IS -- a row nobody at this screen acts on, drawn at a
   * third the size. Worked out the same way from the sizes the ribbon itself
   * sets, so the one place a card's size is written down is still the only one.
   */
  --ribbonh: calc(86px * .38 + 6px * 2.5 + 5px * 2 + 2px);
}
* { box-sizing: border-box; }
html, body { height: 100%; }
/* A phone turned on its side inflates the type to "help", which on a board
   drawn to fit the window pushes half of it off the bottom. */
html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; }
body {
  margin: 0; background: var(--bg); color: var(--ink); overflow: hidden;
  display: flex; flex-direction: column;
  /* a drag that reaches the top of the page is not a pull-to-refresh */
  overscroll-behavior-y: contain;
  font: 14px/1.45 ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
}
/*
 * ROUND CORNERS, NOTCHES AND THE BAR AT THE BOTTOM. The page is laid out under
 * all of them -- viewport-fit=cover, which is what lets the board use the full
 * width of a phone -- so everything with an edge keeps clear of them itself.
 * env() is 0 on a screen that has none, so this is one set of numbers.
 */
header {
  flex: 0 0 auto; display: flex; align-items: center; gap: 16px; flex-wrap: wrap;
  padding: 7px 16px; border-bottom: 1px solid var(--line); background: var(--panel);
  padding-left: max(16px, env(safe-area-inset-left));
  padding-right: max(16px, env(safe-area-inset-right));
  padding-top: max(7px, env(safe-area-inset-top));
}
header h1 { font-size: 15px; margin: 0; font-weight: 600; letter-spacing: .02em; }
header .who { color: var(--accent); font-weight: 600; }
header .facts { color: var(--dim); font-size: 13px; }
/*
 * The two reference screens sit together and the new night sits apart behind a
 * hairline: they are the same kind of thing as each other and not the same kind
 * of thing as it. `margin-left: auto` on each button in turn -- which is what
 * this was -- shares the free space out BETWEEN them instead, so the three
 * drifted across the header at whatever spacing the window happened to give.
 */
header .hbtns { margin-left: auto; display: flex; align-items: center; gap: 7px; }
header .hbtns .hsep { width: 1px; height: 17px; background: var(--line); margin: 0 3px; }
header .hbtns button {
  font-size: 12.5px; line-height: 1.15; padding: 6px 13px; border-radius: 7px;
  color: #4c473f; background: #fdfbf7; border-color: #cfc7b6;
}
header .hbtns button:hover {
  background: #fff; border-color: var(--accent); color: var(--accent);
}

/* board on the left, one ordered column of panels on the right */
main {
  flex: 1 1 auto; min-height: 0; display: flex; gap: 16px; padding: 12px 16px;
  padding-left: max(16px, env(safe-area-inset-left));
  padding-right: max(16px, env(safe-area-inset-right));
  padding-bottom: max(12px, env(safe-area-inset-bottom));
}
#board { flex: 1 1 auto; min-width: 0; min-height: 0; display: flex; flex-direction: column; gap: 6px; }
#mapWrap { flex: 1 1 auto; min-height: 0; display: flex; gap: 8px; align-items: stretch; }
#mapHost { flex: 1 1 auto; min-height: 0; }
/*
 * BESIDE THE BUILDING: the joker's floors, and nothing else. Where a card GOES
 * is in the side column beside the hand it comes from -- both sides drop on a
 * pile and it is the same move, so it is drawn in the same place for both.
 */
#pick {
  flex: 0 0 auto; width: 132px; display: flex; flex-direction: column;
  justify-content: center; gap: 8px; padding: 4px 0;
}
#pick:empty { display: none; }
/*
 * THE TRAILS SIT WHERE THEY SIT AT THE TABLE. Your own row is below the
 * board, in front of your chair, running left to right as you laid it. The
 * rows you are only reading -- the other burglar's, or both of them if you
 * are a guard -- are above it, across the table.
 *
 * A row gets the whole width here, which the side column could not give it: a
 * trail can reach sixteen slots, and a wrapped trail is not a row any more.
 * It scrolls sideways rather than folding.
 */
/*
 * A ROW KEEPS ITS HEIGHT WHATEVER IS STANDING IN IT. A pile is as tall as the
 * cards on it, so a strip that hugged its contents lifted and dropped the
 * whole board every time a card was laid. The row is given the room for the
 * deepest pile the rules allow -- four cards on a played slot, three on the
 * one about to be played, since a burglar spends at most one special a turn
 * -- and keeps it whether or not anything is standing there.
 */
#trailsFar .trail, #trailsNear .trail { height: var(--rowh); }
#trailsFar .trail.ribbon, #trailsNear .trail.ribbon { height: var(--ribbonh); }
/*
 * NO PADDING ABOVE OR BELOW. A row already reserves the height of the deepest
 * pile it can hold, and every pixel of strip on top of that is board taken away
 * twice over -- once at the top of the screen and once at the bottom. It also
 * puts the first card of the top row on the same line the side column starts on,
 * which is where the eye expects the content to begin.
 *
 * NO PADDING AT THE SIDES EITHER: a tray is the width of the column it is in, so
 * it lines up with the building above it and with the panels beside it. The name
 * is the first thing IN the row -- see trails.css -- where the slots used to
 * centre themselves in the column while it sat out in the margin.
 */
#trailsFar, #trailsNear {
  flex: 0 0 auto; overflow: visible; padding: 0;
  display: flex; flex-direction: column; align-items: stretch;
  /* how far the deepest pile the rules allow travels when it is fanned open --
     declared here so that it is inherited, and so a row with no fan to make room
     for can say so for itself; see below, and .trail.ribbon in trails.css */
  --fanroom: calc((var(--fan) - var(--lay)) * 4);
}
#trailsFar:empty, #trailsNear:empty { display: none; }
/* one row a burglar, stacked -- a guard acts on two of them and neither is
   theirs, so they get the same width rather than half of it each. Either strip
   can hold the pair: a guard's two sit below the board, beside their hand. */
#trailsFar .trail + .trail, #trailsNear .trail + .trail { margin-top: 5px; }
/*
 * A ROW RUNS, IT DOES NOT FOLD -- seventeen piles wrapped into a block is not a
 * row any more -- SO THE CARDS SCROLL WHEN THE COLUMN RUNS OUT. Before this they
 * simply kept going: on a 950px desk a guard's rows ran a hundred pixels past
 * the building and out under the panel beside it.
 *
 * AND IT IS THE CARDS THAT SCROLL, not the row. The plate stays at the head of
 * the row and the tray keeps all four of its edges, so what moves is the one
 * part of a row that is longer than the column it is in -- and each row moves on
 * its own, which is the point: a strip that scrolled carried a guard's two rows
 * together, and moved a row nobody was reading.
 *
 * A SLOT IS A CARD WIDE AND WILL NOT BE SQUEEZED. The row is a nowrap flex line,
 * so once it is wider than the tray every slot took its share of the shortfall:
 * a twelve-slot row came out with the cards narrower than the cards, overlapping
 * each other, and the arrows between them gone. Scrolling is the answer to a row
 * too long for its column; shrinking is not.
 */
#trailsFar .slots, #trailsNear .slots {
  flex-wrap: nowrap; min-width: 0; overflow-x: auto; overflow-y: hidden;
}
#trailsFar .slot, #trailsNear .slot { flex: none; }
/*
 * AND A FAN STILL HAS TO LEAVE IT. A box that scrolls on one axis cannot be
 * `visible` on the other, so the cards are clipped top and bottom -- and a pile
 * fanned open by the pointer is exactly that.
 *
 * A scroller clips at its PADDING box, so the room is padding: as much as the
 * deepest fan travels, on the side it travels, and pulled straight back off
 * again as a negative margin. The cards end up exactly where they sat, with a
 * band of nothing on one side that a fanned card may be drawn in. (`overflow-y:
 * clip` with a clip margin is what this wants and cannot have: clip on one axis
 * beside a scrolling one computes to hidden, margin and all.)
 *
 * EACH STRIP HAS ITS ROOM WHERE ITS OWN CARDS GO: the near row fans upward and
 * the far row downward, each away from the edge of the window nearest it.
 */
#trailsNear .slots { padding-top: var(--fanroom); margin-top: calc(-1 * var(--fanroom)); }
#trailsFar .slots { padding-bottom: var(--fanroom); margin-bottom: calc(-1 * var(--fanroom)); }
/*
 * AND THE ROW DRAWS NO BAR OF ITS OWN. A browser puts the sideways bar at the
 * bottom edge of what scrolls, and what scrolls is the cards AND the band: on a
 * row above the building that is a bar a hundred pixels below the cards it
 * belongs to, floating over the plan -- which is where both rows sit while a
 * computer is playing, so it was two of them. It could not be taken hold of
 * either: the band must not answer the pointer, and a bar nobody can drag is
 * worse than no bar at all.
 *
 * So a row is scrolled the ways a row is scrolled -- a wheel over the cards (see
 * rowWheel in actions.js), a trackpad, a finger -- and what says there is more of
 * it is the card cut off at the edge of the tray, the same thing a hand of cards
 * says when it runs past the edge of the table.
 */
/*
 * AND A TARGET RING IS DRAWN INSIDE A SLOT, NOT AROUND IT. An outline sits
 * outside the box it is on, and these boxes are in a scroller that clips top and
 * bottom -- so the ring saying where a card may be dropped lost its bottom edge
 * to the rim, which reads as a slot drawn wrong rather than as a target. Inside,
 * nothing can cut it. The ring itself is [data-drop].ok in cards.css; only where
 * it is drawn is decided here, because only here is it clipped.
 */
#trailsFar .slots [data-drop], #trailsNear .slots [data-drop] { outline-offset: -2px; }
#trailsFar .slots, #trailsNear .slots { scrollbar-width: none; }
#trailsFar .slots::-webkit-scrollbar,
#trailsNear .slots::-webkit-scrollbar { display: none; }
/* The rule that used to run under the far strip is gone with the flat rows: a
   tray has an edge of its own, and a hairline above it was a second one saying
   the same thing. The gap between the strips and the building is #board's. */
/*
 * Your own row is at the bottom of the screen, so its piles fan UPWARD: the
 * card the pointer is on stays where it is and the ones beneath it rise out
 * from under it, into the board rather than off the end of the window.
 */
/*
 * WHICH CARD STAYS PUT IS THE TOP ONE, and which layer that is depends on how
 * deep the pile is -- so each depth anchors its own. Raising a fixed layer
 * instead lifted a one-card pile bodily off the row and fanned nothing, which
 * is not a fan, it is a jump. The card under the pointer never moves; the ones
 * beneath it come out from under it, 28px apart, the same spacing the far row
 * fans downward with.
 */
/*
 * TWO WAYS OF ASKING FOR THE SAME FAN. A pointer resting on the pile is one,
 * and it is written where it belongs -- behind (hover: hover), since nothing
 * rests on a touchscreen and a rule that assumes it is a rule a tablet simply
 * does not have. `.fanned` is the other: the tap that asks for it instead.
 */
/* --scale is the fraction of a full slot the cell is drawn at (see trails.css):
   a fanned pile opens at the size its cards are, so a turn thrown away does not
   spring back to slot size under the pointer and out over its neighbours. */
#trailsNear .slot:not(.next).fanned .card {
  transform: translateY(calc((var(--lay) * var(--n, 0)
                              - var(--fan) * (var(--n, 0) - var(--k, 0))) * var(--scale)))
             scale(calc(var(--pile) * var(--scale)));
}
@media (hover: hover) {
  #trailsNear .slot:not(.next):hover .card {
    transform: translateY(calc((var(--lay) * var(--n, 0)
                                - var(--fan) * (var(--n, 0) - var(--k, 0))) * var(--scale)))
               scale(calc(var(--pile) * var(--scale)));
  }
}
#mapHost svg { width: 100%; height: 100%; display: block; }
/*
 * AS WIDE AS THE HAND IT HOLDS, which is five cards across with their gaps and
 * the panel's own padding either side. It was 392px, which is that plus a
 * finger's worth of nothing -- fine on a laptop and a third of a tablet held on
 * its side, where every pixel of it came off the building. Written as the sum
 * it is, so a card that changes size takes the column with it.
 */
#side {
  flex: 0 0 calc(63px * 5 + 6px * 4 + 24px);
  min-height: 0; overflow-y: auto;
  display: flex; flex-direction: column; gap: 10px;
}
/*
 * Panels keep their natural height and the column scrolls. Without this they
 * are flex items with the default flex-shrink: 1, so a tall hand or a long
 * trail squashes every box and its content spills over the next one.
 */
#side > * { flex: 0 0 auto; }

.box {
  background: var(--panel); border: 1px solid var(--line); border-radius: 8px;
  padding: 9px 11px; box-shadow: 0 1px 2px rgba(60, 50, 30, .06);
}
.box h2 {
  margin: 0 0 7px; font-size: 10px; letter-spacing: .09em; text-transform: uppercase;
  color: var(--dim); font-weight: 600;
  display: flex; align-items: center; gap: 7px;
}
/*
 * THE TABLE, DRAWN RATHER THAN COUNTED OUT. Two halves side by side, each with
 * the deck its side draws from over the heap its side throws at -- the same two
 * shapes the rulebook uses, at the size a panel has room for.
 *
 * --tile is how big a card is here, and everything else follows it, so the two
 * stacks cannot drift apart when one is changed.
 */
.tableau {
  --tile: .42;                                  /* of the 63 x 86 a card is */
  --tilew: calc(63px * var(--tile));
  --tileh: calc(86px * var(--tile));
  /*
   * WHOSE IT IS DOWN THE SIDE, WHAT IT IS ALONG THE TOP, and the four cells are
   * the piles. Every label is written once, and each side's row holds the deck
   * it draws from beside the pile it throws on.
   */
  display: grid; grid-template-columns: auto 1fr 1fr;
  justify-items: center; align-items: center;
  /* no wider than what is standing in it, and centred in the panel: stretched
     to the panel's width the two piles drifted to opposite ends of it and the
     first sat against the labels */
  width: fit-content; margin: 0 auto;
  column-gap: 16px; row-gap: 9px;
}
/* ...and the side of the matrix stands clear of the first column of it */
.tableau .pwho { padding-right: 12px; }
.tableau .pwho, .tableau .pwhat {
  font-size: 10px; letter-spacing: .07em; text-transform: uppercase;
  color: var(--dim); font-weight: 600;
}
/* the side of the matrix reads as a column of labels, so it is ranged left */
.tableau .pwho { justify-self: start; }


/*
 * The count, standing on the top card where a dealer's eye goes -- and the top
 * card of both piles is at the same height, so the four counts read across the
 * matrix as a row of numbers rather than as four numbers at four heights.
 */
.tableau .pnum {
  position: absolute; left: 0; right: 0; z-index: 30; pointer-events: none;
  text-align: center; line-height: 1;
  top: calc(var(--tileh) / 2 - 6px);
  font-size: 13px; font-weight: 700; font-variant-numeric: tabular-nums;
  color: #40372a; text-shadow: 0 1px 0 rgba(255, 255, 255, .9);
}
.tableau .card {
  position: absolute; left: 0; top: 0; transform-origin: top left;
  cursor: default;
}
/* the count stands where the emblem does, so the emblem gives way to it */
.tableau .card .cemblem { opacity: .3; }
/*
 * A DECK IS SQUARED UP, because somebody has to take the top card off it: every
 * back offset by the same two pixels and turned not at all. The TOP card sits
 * at 0,0 and the deck grows down and right from it, so the number standing on
 * it does not move as the deck runs down -- and --k, the layers standing, is
 * how deep the box has to be to hold them.
 */
.tableau .pdeck {
  position: relative;
  /* the box is the DEEPEST a deck goes, not the depth of this one: the shelf
     does not move as the deck runs down, and neither does anything under it */
  width: calc(var(--tilew) + 16px); height: calc(var(--tileh) + 16px);
}
.tableau .pdeck .pnum { right: auto; width: var(--tilew); }
/* a deck that has run out is the space it stood in, and the nought standing in it */
.tableau .pdeck.bare::before {
  content: ''; position: absolute; left: 0; top: 0;
  width: var(--tilew); height: var(--tileh);
  border: 1.5px dashed #cbc2ae; border-radius: 6px;
}
/* counted from the top of the deck: the last card laid is the one on top */
.tableau .pdeck .card { transform: translate(var(--o, 0px), var(--o, 0px)) scale(var(--tile)); }
.tableau .pdeck .card:nth-last-child(2) { --o: 2px; }
.tableau .pdeck .card:nth-last-child(3) { --o: 4px; }
.tableau .pdeck .card:nth-last-child(4) { --o: 6px; }
.tableau .pdeck .card:nth-last-child(5) { --o: 8px; }
.tableau .pdeck .card:nth-last-child(6) { --o: 10px; }
.tableau .pdeck .card:nth-last-child(7) { --o: 12px; }
.tableau .pdeck .card:nth-last-child(8) { --o: 14px; }
/*
 * ...AND NOBODY SQUARES UP A HEAP THEY ARE NEVER GOING TO READ AGAIN. Each card
 * carries the angle and the drift it landed at -- worked out from its place in
 * the pile, so the card thrown last turn is still where it was.
 *
 * The box is a fixed size whatever is in it: an empty spot is still the spot.
 */
.tableau .pheap {
  position: relative;
  /* the same height as a deck, and the top card at the same height in it: two
     counts on two different lines is two piles that cannot be read across */
  width: calc(var(--tilew) + 26px); height: calc(var(--tileh) + 16px);
  border-radius: 8px;
}
.tableau .pheap .card {
  left: 13px; top: 0;
  transform: translate(var(--dx, 0), var(--dy, 0)) rotate(var(--rot, 0deg))
    scale(var(--tile));
  box-shadow: 0 2px 6px rgba(60, 50, 30, .22);
}
/* an empty spot is still a spot: the pile is where it is before anything is on it */
.tableau .pheap.bare {
  border: 1.5px dashed #cbc2ae; background: rgba(140, 110, 60, .04);
}
/*
 * WHERE A CARD GOES, said by the pile rather than by a box beside it -- and said
 * BEFORE one is picked up, because the caption under the table names a pile and
 * two bare spots side by side cannot say which of them it meant.
 *
 * Only one is ever yours: a burglar may throw on the burglars' pile and a guard
 * on the guards', so the ring is the side of the table you are sitting at.
 */
.tableau .pheap[data-drop] {
  border: 1.5px dashed #c0a882; background: rgba(140, 110, 60, .08);
}
/* under the card, and only the one it would land on if let go now */
body.dragging .tableau .pheap[data-drop].ok {
  border-color: #a8834a; background: rgba(140, 110, 60, .16);
}
body.dragging .tableau .pheap[data-drop].over {
  border-style: solid; border-color: #7d5f2c; background: rgba(140, 110, 60, .3);
}
/*
 * A BURGLAR'S MARK, wherever a burglar is named: their colour off the board with
 * the number of their chair in it. It was three all-but-identical discs -- one
 * on the row, one in this panel, one on the tally at the reveal -- and the
 * number would have had to be written into each of them. It is one object now,
 * and each of the three says only where it sits.
 *
 * THE NUMBER IS WHY IT GREW, from 11px to 15. A digit inside a dot small enough
 * to read as punctuation is a smudge; this is the smallest a 9.5px figure is
 * legible in. The ring is what keeps it a mark rather than a bullet: the two
 * route colours are chosen to be seen on a dark plan, and both are pale enough
 * to vanish into a panel without it.
 */
.bdot {
  width: 15px; height: 15px; border-radius: 50%; box-sizing: border-box;
  flex: none; outline: 1.5px solid rgba(12, 13, 16, .75);
  display: inline-flex; align-items: center; justify-content: center;
  font: 700 9.5px/1 ui-sans-serif, system-ui, sans-serif;
  /* the ink is the route's own -- see burglarDot */
}
/*
 * WHAT THE NIGHT WAS WORTH, and it is the whole of a panel now rather than a
 * block folded in under the counters. One line each: the colour their route is
 * drawn in, who they are, what happened to them, and what it came to.
 *
 * THE TINT IS THE OUTCOME AND NOTHING ELSE IS. Three of them -- out with it,
 * out with nothing, caught inside -- and they are the three the reveal screen
 * scores with, so the panel and the screen agree.
 */
.box.result .score { display: flex; flex-direction: column; gap: 3px; }
.box.result .srow {
  display: grid; grid-template-columns: 15px 1fr auto;
  align-items: baseline; gap: 2px 9px;
  padding: 7px 9px 7px 8px; border-radius: 5px;
  border-left: 3px solid transparent;
}
.box.result .srow .smark { align-self: center; }
.box.result .srow .sname { font-size: 12.5px; font-weight: 600; }
/* what happened, under the name and in the panel's own quiet voice */
.box.result .srow .ssaid {
  grid-column: 2; font-size: 11.5px; line-height: 1.35; color: var(--dim);
}
.box.result .srow .spts {
  grid-column: 3; grid-row: 1 / span 2; align-self: center;
  font-size: 17px; font-weight: 700; font-variant-numeric: tabular-nums;
  min-width: 26px; text-align: right;
}
.box.result .srow.exhibit { background: #f2f9f4; border-left-color: #2f8f5b; }
.box.result .srow.exhibit .spts { color: #2f8f5b; }
.box.result .srow.away { background: #f7f4ec; border-left-color: #8a6d1f; }
.box.result .srow.away .spts { color: #8a6d1f; }
.box.result .srow.caught { background: #fbeceb; border-left-color: #b03a30; }
.box.result .srow.caught .spts { color: #b03a30; }
/*
 * THE MUSEUMS' OWN COLOUR, and a square rather than a disc: they are the side
 * that owns the building, not somebody moving through it. It was #b09a70, a tan
 * which measured ΔE 13.7 from parquet -- the closest any two colours on this
 * board came, and 6 to 10 through the three dichromacies, where every other pair
 * the board relies on is held past 20. A steel blue is 16.8 from the nearest
 * thing to it and past 13 through all three.
 */
.box.result .bdot.museum { border-radius: 3px; background: var(--museum); }
button {
  font: inherit; color: var(--ink); background: #fff; border: 1px solid #c3bcac;
  border-radius: 6px; padding: 6px 12px; cursor: pointer;
}
button:hover { background: #f1ede4; border-color: #a79e8b; }
button.primary { background: var(--accent); border-color: var(--accent); color: #fff; font-weight: 600; }
button.primary:hover { background: #2a86ba; }

/*
 * WHAT THE TURN IS WAITING FOR: one line, its own panel, directly above the
 * hand. It is the only thing on the screen that changes every turn, and set
 * as a caption inside the hand box it read as part of the heading.
 */
/*
 * ONE VOICE, AND THE PANEL CARRIES THE STATE. Everything written in here is the
 * same thing -- what the turn is waiting for -- so it is all one size, one
 * weight and one colour, and two lines of it are separated by space alone. It
 * used to arrive in gold bold, grey small or plain depending on which sentence
 * was true, which is the state said with the words.
 *
 * The state is said with the FURNITURE instead: a rail down the side, a wash
 * behind it and the mark in front, all three in one tone. They are the colours
 * the rest of the board already spends -- the accent a burglar's own row wears,
 * the gold the shutters are paid in, the red a lost night is scored in.
 */
.box.turnstate {
  --tone: #8a8478;                      /* a note, and nothing waiting on it */
  --wash: rgba(119, 114, 106, .07);
  font-size: 12.5px; line-height: 1.45; padding: 10px 12px 10px 13px;
  border-left: 3px solid var(--tone);
  background: linear-gradient(90deg, var(--wash), rgba(255, 255, 255, 0) 78%), var(--panel);
}
.box.turnstate.elsewhere { --tone: #8a8478; --wash: rgba(119, 114, 106, .07); }
.box.turnstate.yours { --tone: var(--accent); --wash: rgba(31, 111, 156, .11); }
.box.turnstate.press { --tone: var(--gold); --wash: rgba(154, 109, 16, .11); }
.box.turnstate.bad { --tone: #b03a30; --wash: rgba(176, 58, 48, .10); }
.box.turnstate .stateline { display: flex; align-items: baseline; gap: 9px; }
.box.turnstate .statedot {
  flex: none; width: 8px; height: 8px; border-radius: 50%;
  background: var(--tone); transform: translateY(1px);
}
/* ...and only one of them is a thing happening somewhere else, so only one moves */
.box.turnstate.elsewhere .statedot { animation: pulse 1s ease-in-out infinite; }
@keyframes pulse { 0%, 100% { opacity: .25; } 50% { opacity: 1; } }
@media (prefers-reduced-motion: reduce) {
  .box.turnstate .statedot { animation: none; }
}
/* the second line is the first one's, so it starts where the words do */
.box.turnstate .statesub { margin-top: 8px; padding-left: 17px; }
