/* The splash and game-over screens, and the field guide bolted to the splash.
   Guide rows are generated from the features that register a `guide`, so the
   only thing this file cares about is how a row is laid out. */
.overlay {
  position: fixed;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  /* safe centering + scroll: on a short screen nothing ends up unreachable
     above the fold, which plain `center` would do */
  justify-content: safe center;
  overflow-y: auto;
  gap: 1.35rem;
  text-align: center;
  padding: 2rem;
  background: radial-gradient(ellipse at center, rgba(7,3,15,0.35), rgba(7,3,15,0.78));
  /* Deliberately no backdrop-filter here: an element that has one becomes a
     backdrop root, and the rack below would then be frosting this gradient
     instead of the field behind it. The panels do the glass, the splash does
     the shade. */
}
.overlay[hidden] { display: none; }
/* The splash is not a stack that scrolls, it is a screen with two things
   floating over one. The deck takes the whole screen; the mark and the
   instruction hang above it, at the top and at the bottom, where neither can
   be scrolled away from on a laptop or a phone or the television in the
   corner. PRESS ENTER stays findable, which was the point of the dock the day
   it was built and still is.

   They were rows before this, and a row is opaque by construction: the deck
   stopped dead at a hard edge under the title, with a strip of shade above it
   doing no work. A panel cut in half by an edge reads as broken. A panel
   running on underneath something you can see through reads as a panel with
   more of it, and that is the true statement of the two.

   So neither of them hides what is behind it. The mark carries a plate exactly
   its own size and no bigger; the dock is a bar you can read the foot of a
   panel through. What holds the deck off them is padding rather than layout —
   src/ui/splash.js measures both and writes the two lengths onto this element,
   so nothing on the deck ever starts life underneath either. The defaults are
   what a browser that somehow never ran that file would need, and they are
   close enough that nobody would notice.

   `:not([hidden])` rather than a plain class, so the rule that hides an
   overlay while a game is running still wins without needing to shout. */
.splash:not([hidden]) {
  display: block;
  padding: 0;
  overflow: hidden;              /* the deck scrolls; the screen does not */
}
/* The mark, floating. It is the biggest thing on the screen and the least
   useful once you are three panels down, so it folds as you read — the scale
   comes off the scroll position, and `top center` is what keeps it hugging the
   ceiling as it goes rather than drifting up out of the room.

   `pointer-events: none` because it is a picture of a name: a wheel rolled
   over it belongs to the deck underneath, and so does a cursor. */
.splash > .logo {
  position: absolute;
  top: 1.2rem;
  left: 50%;
  transform: translateX(-50%) scale(var(--mark, 1));
  transform-origin: top center;
  pointer-events: none;
  z-index: 2;
}
/* The deck: the field on the left, the people on the right, the book across
   the foot of both. Two columns rather than one long stack, because reading
   what is out there and deciding whose seat to take is one decision and it is
   made in one glance. */
.deck {
  height: 100%;
  width: min(84rem, 96vw);
  margin: 0 auto;
  display: grid;
  grid-template-columns: minmax(0, 1.5fr) minmax(0, 1fr);
  align-content: start;
  /* a panel is as tall as what is in it. Without this the shortest one in a
     column grows to fill its row and reads as a panel with something missing */
  align-items: start;
  gap: 0.85rem;
  overflow-y: auto;
  overscroll-behavior: contain;
  /* the room the mark and the dock are standing in, measured by
     src/ui/splash.js, plus a little air so the first panel is not touching the
     plate and the last is not touching the rule */
  padding: calc(var(--head, 7.5rem) + 0.8rem) 0 calc(var(--foot, 5.5rem) + 0.5rem);
  scrollbar-width: thin;
  scrollbar-color: rgba(160, 75, 255, 0.5) transparent;
}
.brief { grid-column: 1; grid-row: 1 / span 3; }
.pilot { grid-column: 2; grid-row: 1; }
.lobby { grid-column: 2; grid-row: 2; }
.board { grid-column: 2; grid-row: 3; }
.book  { grid-column: 1 / -1; grid-row: 4; }
.about { grid-column: 1 / -1; grid-row: 5; }
/* The dock. Never scrolls, never moves, and the dashed rule along the top of
   it is still where the reading stops and the pressing starts.
   See-through on purpose, and across the whole foot of the screen rather than
   the width of the deck: the reading runs on underneath it, darkest down at
   the instruction and nearly gone up at the rule, so what is behind is a panel
   you can still half read rather than a strip of night. */
.splash .dock {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 2;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.5rem;
  padding: 0.8rem 1.5rem 1rem;
  border-top: 1px dashed rgba(154, 134, 189, 0.3);
  background: linear-gradient(to top, rgba(7, 3, 15, 0.8), rgba(7, 3, 15, 0.32));
}
/* A little frost, so that what is showing through reads as behind the bar
   rather than printed on it — and so the instruction has something to sit on
   whatever colour of panel happens to be sliding past underneath. Scoped to a
   visible splash for the reason the rack is, further down this file: a
   backdrop-filter on a hidden element still costs the compositor. */
@supports ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .splash:not([hidden]) .dock {
    -webkit-backdrop-filter: blur(10px) saturate(1.3);
    backdrop-filter: blur(10px) saturate(1.3);
  }
}
.overlay h1 {
  font-size: clamp(2rem, 7.5vw, 4.2rem);
  font-weight: 600;
  letter-spacing: 0.4em;
  margin-right: -0.4em; /* recenter after tracking */
  text-wrap: balance;
  background: linear-gradient(100deg,
    #ff3ec8, #ffb020, #b6ff3d, #21f3ff, #a04bff, #ff3ec8);
  background-size: 300% 100%;
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  filter: drop-shadow(0 0 16px rgba(255,62,200,0.5));
  animation: slide 6s linear infinite;
}
@keyframes slide {
  from { background-position: 0% 50%; }
  to { background-position: 300% 50%; }
}
/* In the dock: the two keys nobody thinks to mention, above the one thing you
   came here to press. Nothing down here is a panel, on purpose. */
.overlay .controls {
  color: var(--dim);
  font-size: 0.8rem;
  line-height: 1.9;
  letter-spacing: 0.12em;
}
.overlay .controls b {
  color: var(--cyan);
  font-weight: 500;
  text-shadow: 0 0 8px currentColor;
}
/* The loudest thing on the screen, and the last — everything above it is
   reading, this is the instruction. The four lines at the top are for the one
   on the splash that is a real button now: a button brings a font, a border
   and a background of its own, and none of them are wanted. */
.overlay .prompt {
  -webkit-appearance: none;
  appearance: none;
  font: inherit;
  background: none;
  border: 0;
  padding: 0;
  font-size: 1.05rem;
  letter-spacing: 0.32em;
  margin-right: -0.32em;
  color: var(--lime);
  text-shadow: 0 0 12px currentColor, 0 0 34px rgba(182, 255, 61, 0.4);
  animation: blink 1.2s step-end infinite;
}
/* And on the splash it says so under a hand. Nothing else on that screen
   starts a flight any more — the deck is somewhere you read, scroll and click
   about in, and a room where every stray press launches a wave is not a room
   anybody can read in. So the one place that does starts wearing a hand,
   answers a press, and carries enough hem around the words to be found with a
   thumb. The hem grows the dock, and src/ui/splash.js measures the dock every
   time it changes, so the deck holds itself off the new one on its own. */
.splash .prompt {
  cursor: pointer;
  padding: 0.35rem 0.9rem;
  -webkit-user-select: none;
  user-select: none;
  -webkit-tap-highlight-color: transparent;
}
.splash .prompt:hover, .splash .prompt:focus-visible { color: #eaffb8; }
.splash .prompt:active { transform: translateY(1px); }
.overlay .final {
  font-size: 1.1rem;
  letter-spacing: 0.15em;
  line-height: 2.1;
  font-variant-numeric: tabular-nums;
  color: var(--amber);
  text-shadow: 0 0 12px currentColor;
}
.overlay .final .best { color: var(--dim); text-shadow: none; }

/* The rack: six instruments bolted to the splash, sharing a chassis — plate,
   corner brackets, one header shape. What tells them apart is `--accent`, and
   each panel keeps the colour it already wore: magenta for the guide, cyan for
   the pilot, amber for the seats, which is also the colour of the seat that is
   still open. Then lime for the board, because that is the colour this cabinet
   says yes in, and violet for the book, because the book has been violet since
   it was one line of text. The label on the machine took the last quarter of
   the wheel with nobody in it, which is the mint between lime and cyan. Six
   hues evenly around, and the rack drifts through the spectrum in step, so
   whatever hue they are at they are still that far apart. */
.brief, .pilot, .lobby, .board, .book, .about {
  position: relative;
  padding: 1.1rem 1.3rem 1.2rem;
  background: rgba(12, 5, 24, 0.66);
  border: 1px solid var(--accent-soft);
  /* the last two are the material rather than the colour: a lit top edge and a
     shaded bottom one is what tells the eye this is a pane with thickness and
     not a rectangle of paint */
  box-shadow: 0 0 26px rgba(160, 75, 255, 0.28),
              inset 0 0 34px var(--accent-glow),
              inset 0 1px 0 rgba(255, 255, 255, 0.16),
              inset 0 -1px 0 rgba(0, 0, 0, 0.35);
  text-align: left;
  animation: cycle 9s linear infinite;
}
/* The rack, as glass. Thinning the plate is only safe once we know the frost
   is there to hold the text up, so the whole trade lives behind @supports and
   a browser without it keeps the solid plate it always had.
   `:not([hidden])` is the load-bearing part, not a tidiness: the splash is
   display:none while a game is running, but a backdrop-filter that merely
   sits on a hidden element still exists in the layer tree, and the compositor
   can keep the canvas promoted for it long after the splash has gone. Scoped
   this way the property is not applied at all during play, and the frame
   belongs to the game. */
@supports ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .overlay:not([hidden]) .brief,
  .overlay:not([hidden]) .pilot,
  .overlay:not([hidden]) .lobby,
  .overlay:not([hidden]) .board,
  .overlay:not([hidden]) .book,
  .overlay:not([hidden]) .about {
    background:
      linear-gradient(148deg,
        rgba(255, 255, 255, 0.15),
        rgba(255, 255, 255, 0.035) 40%,
        rgba(255, 255, 255, 0) 70%),
      rgba(12, 5, 24, 0.34);
    /* brightness is doing the same job the gradient is: the field behind is
       nearly black, and glass that is not lifted off it is just a dark
       rectangle with a lit edge */
    -webkit-backdrop-filter: blur(18px) saturate(1.8) brightness(1.45);
    backdrop-filter: blur(18px) saturate(1.8) brightness(1.45);
  }
}
.brief { --accent: var(--magenta); --accent-soft: rgba(255, 62, 200, 0.38); --accent-glow: rgba(255, 62, 200, 0.05); }
.pilot { --accent: var(--cyan);    --accent-soft: rgba(33, 243, 255, 0.38); --accent-glow: rgba(33, 243, 255, 0.06); }
.lobby { --accent: var(--amber);   --accent-soft: rgba(255, 176, 32, 0.38); --accent-glow: rgba(255, 176, 32, 0.05); }
.board { --accent: var(--lime);    --accent-soft: rgba(182, 255, 61, 0.36); --accent-glow: rgba(182, 255, 61, 0.05); }
.book  { --accent: var(--violet);  --accent-soft: rgba(160, 75, 255, 0.42); --accent-glow: rgba(160, 75, 255, 0.07); }
.about { --accent: var(--mint);    --accent-soft: rgba(61, 255, 176, 0.36); --accent-glow: rgba(61, 255, 176, 0.05); }

/* the bracketed corners are the family mark — same shape on all six, so the
   rack reads as one rack before the colours say which panel is which */
.brief::before, .brief::after,
.pilot::before, .pilot::after,
.lobby::before, .lobby::after,
.board::before, .board::after,
.book::before, .book::after,
.about::before, .about::after {
  content: "";
  position: absolute;
  width: 13px;
  height: 13px;
  border: 1px solid var(--accent);
}
.brief::before, .pilot::before, .lobby::before,
.board::before, .book::before, .about::before {
  top: -1px; left: -1px;
  border-right: none;
  border-bottom: none;
}
.brief::after, .pilot::after, .lobby::after,
.board::after, .book::after, .about::after {
  bottom: -1px; right: -1px;
  border-left: none;
  border-top: none;
}
/* one header shape for all six: the panel's own glyph, the label, a rule
   under it. The glyph replaced a lit square, which said "this is a panel" —
   true, and the pilot could see that. A glyph says what kind. */
.brief h2, .pilot h2, .lobby h2, .board h2, .book h2, .about h2 {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  font-size: 0.6rem;
  font-weight: 500;
  letter-spacing: 0.34em;
  color: var(--accent);
  text-shadow: 0 0 10px currentColor;
  margin-bottom: 0.85rem;
  padding-bottom: 0.6rem;
  border-bottom: 1px dashed var(--accent-soft);
}
.brief h2 .ic, .pilot h2 .ic, .lobby h2 .ic,
.board h2 .ic, .book h2 .ic, .about h2 .ic {
  width: 0.95rem;
  height: 0.95rem;
}
/* The glyphs the panels are signposted with — one box, one weight, and the
   colour of whatever they were dropped into, so they drift with the spectrum
   like the rest of the rack. See src/ui/icons.js. */
.ic {
  flex: none;
  width: 1em;
  height: 1em;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.7;
  stroke-linecap: round;
  stroke-linejoin: round;
  vertical-align: -0.14em;
  filter: drop-shadow(0 0 4px currentColor);
}
/* Three bands: what is out there, what is in your hands, what you read. The
   panel used to be one run of sixteen rows in guide order, which meant the
   bomb sat between two rocks and nothing on the screen said that one of them
   was yours. src/ui/fieldguide.js decides who is in which; this only has to
   put a line between them.

   The header is deliberately quieter than the panel's own h2 and louder than a
   row's name — it is a shelf label, and a shelf label that competes with the
   sign over the shop has gone wrong. The note beside it is the sentence that
   makes the three bands one sentence when you read them down the panel. */
.brief .band + .band { margin-top: 1.05rem; }
.brief .band h3 {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 0 0.6rem;
  font-size: 0.56rem;
  font-weight: 500;
  letter-spacing: 0.3em;
  color: var(--accent);
  margin-bottom: 0.6rem;
  padding-bottom: 0.35rem;
  border-bottom: 1px solid var(--accent-soft);
}
.brief .band h3 span {
  letter-spacing: 0.08em;
  text-transform: none;
  color: var(--dim);
  font-size: 0.62rem;
}

/* As many columns as the panel is wide enough to hold, and it decides that
   itself: two hand-set columns were right while the guide was a narrow strip
   down the middle of the screen, and on half a splash it is three without
   anybody editing this line.
   Still multi-column rather than a grid of cells, and the reason is visible
   the moment you try the other one: the grapple takes four lines to explain
   and the asteroid takes two, so a row of grid cells is as tall as the worst
   case and the panel fills up with holes. Columns flow, so entries pack. The
   divider between them comes free, which was the other reason. */
.brief ul {
  list-style: none;
  columns: 15rem;
  column-gap: 1.6rem;
  column-rule: 1px dashed rgba(160, 75, 255, 0.3);
}
.brief li {
  display: grid;
  grid-template-columns: 2.1rem 1fr;
  align-items: center;
  column-gap: 0.85rem;
  /* padding, not margin: a column break eats the margin and keeps the padding */
  padding-bottom: 0.65rem;
  break-inside: avoid;
  animation: rise 0.5s cubic-bezier(0.2, 0.8, 0.3, 1) both;
  animation-delay: calc(var(--i) * 80ms + 150ms);
}
.brief .icon svg {
  display: block;
  filter: drop-shadow(0 0 5px currentColor);
  transition: filter 0.14s ease;
}
/* The rows answer a cursor out loud now (src/ui/clicks.js), and a row that
   makes a noise without doing anything reads as a fault in the sound rather
   than a feature of the panel. The acknowledgement is deliberately the
   smallest one available: `rise` finishes on `transform: none` and holds it,
   so anything that moved the row would fight the animation and lose. */
.brief li:hover .icon svg { filter: drop-shadow(0 0 10px currentColor); }
.brief li:hover .name { color: var(--accent); }
.brief .name {
  font-size: 0.73rem;
  letter-spacing: 0.18em;
  color: var(--ink);
}
.brief .pts {
  color: var(--amber);
  letter-spacing: 0.08em;
  font-variant-numeric: tabular-nums;
  margin-left: 0.5rem;
  font-size: 0.68rem;
}
.brief .desc {
  font-size: 0.69rem;
  line-height: 1.5;
  color: var(--dim);
  margin-top: 0.15rem;
}
@keyframes rise {
  from { opacity: 0; transform: translateY(8px); }
  to { opacity: 1; transform: none; }
}
/* Below the width where two columns of panel stop being two columns and start
   being two columns of four words, the deck is one column and the order on the
   page is the order you need it in: who is flying, then the seats, then the
   field, then the board, then the book, then what the whole thing is. A phone
   is choosing a pilot, not studying the ecology. */
@media (max-width: 64rem) {
  .deck {
    grid-template-columns: minmax(0, 1fr);
    width: min(34rem, 96vw);
  }
  .brief, .pilot, .lobby, .board, .book, .about { grid-column: 1; grid-row: auto; }
  .pilot { order: 1; }
  .lobby { order: 2; }
  .brief { order: 3; }
  .board { order: 4; }
  .book  { order: 5; }
  .about { order: 6; }
}
/* A short screen gets a tighter rack — smaller title, less padding, panels
   closer together. It does not get less to read. That trade was made when the
   splash was one column that had to fit above the fold or PRESS ENTER went
   missing; the dock holds PRESS ENTER now whatever happens up here, and the
   deck scrolls, so a laptop keeps the field guide it is entitled to. */
@media (max-height: 940px) {
  .splash > .logo { top: 0.7rem; }
  .overlay h1 { font-size: clamp(1.7rem, 5.2vw, 2.6rem); }
  .overlay .controls { line-height: 1.6; }
  .splash .dock { padding: 0.6rem 1.25rem 0.75rem; }
  .deck { gap: 0.6rem; }
  .brief, .pilot, .lobby, .board, .book, .about { padding: 0.85rem 1rem; }
  .brief h2, .pilot h2, .lobby h2, .board h2, .book h2, .about h2 {
    margin-bottom: 0.6rem;
    padding-bottom: 0.45rem;
  }
  .brief li { padding-bottom: 0.45rem; }
  .brief .band + .band { margin-top: 0.75rem; }
}
/* The sound toggle is nailed to the bottom right corner of the screen and has
   been since before there was a dock down there. On a narrow one the
   instruction runs straight underneath it, so the dock gets a deeper hem —
   moving somebody's button because your panel arrived is the wrong way round. */
@media (max-width: 30rem) {
  .splash .dock { padding-bottom: 3.1rem; }
  .overlay .prompt { font-size: 0.92rem; letter-spacing: 0.22em; margin-right: -0.22em; }
}
@media (prefers-reduced-motion: reduce) {
  .overlay .prompt, .overlay h1, .brief li,
  .brief, .pilot, .lobby, .board, .book, .about { animation: none; }
}
