/* Brand sheet for the whole application.

   Colours and type come from the brandbook and live here as custom properties
   so that no page hard-codes a hex value.

   The fonts are served from this server and from nowhere else. Linking them
   from a font CDN would hand a third party the IP address of every visitor,
   which is exactly what the project promised not to do. Both faces are under
   the SIL Open Font License 1.1; the licence texts sit beside the files in
   web/assets/fonts/, which is what that licence asks for.

   Only the latin and cyrillic cuts are shipped. Latin carries the German
   umlauts, cyrillic carries every word the player reads. */

@font-face {
  /* latin, and with it the German umlauts */
  font-family: "Cormorant Garamond";
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("/assets/fonts/cormorant-garamond-600-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  /* cyrillic: every heading on every page */
  font-family: "Cormorant Garamond";
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("/assets/fonts/cormorant-garamond-600-cyrillic.woff2") format("woff2");
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}

@font-face {
  /* variable weight, one file for both */
  font-family: "Manrope";
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  src: url("/assets/fonts/manrope-var-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  /* cyrillic: the running text */
  font-family: "Manrope";
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  src: url("/assets/fonts/manrope-var-cyrillic.woff2") format("woff2");
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}

:root {
  --nachtblau: #111c33;
  --gold: #c9a227;
  --champagner: #efe7d8;
  --petrol: #0e3b3e;

  --surface: #16233d;
  --surface-soft: #1b2c49;
  --line: #2c3d5e;
  --muted: #a9b4c9;

  /* The fallbacks still matter: they are what shows during the swap, and
     what shows if a font file ever fails to load. */
  --font-display: "Cormorant Garamond", "Georgia", "Times New Roman", serif;
  --font-body: "Manrope", "Segoe UI", system-ui, -apple-system, sans-serif;

  --measure: 34rem;
  --radius: 10px;
  --step: 1rem;
}

*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  /* Anchors and the "read the transcript" toggle scroll, and a fixed header
     would otherwise cut the target in half. */
  scroll-padding-top: 5rem;
}

body {
  margin: 0;
  background: var(--nachtblau);
  color: var(--champagner);
  font-family: var(--font-body);
  font-size: 1.0625rem;
  line-height: 1.65;
  -webkit-text-size-adjust: 100%;
}

h1,
h2,
h3 {
  font-family: var(--font-display);
  font-weight: 600;
  line-height: 1.2;
  margin: 0 0 0.6em;
}

h1 {
  font-size: clamp(2rem, 5vw, 2.75rem);
}

h2 {
  font-size: clamp(1.4rem, 3.5vw, 1.8rem);
  margin-top: 2.2rem;
}

p {
  margin: 0 0 1.1em;
}

a {
  color: var(--gold);
}

/* One visible focus ring everywhere. The whole path has to be walkable
   without a mouse, which is impossible if focus cannot be seen. */
:focus-visible {
  outline: 3px solid var(--gold);
  outline-offset: 2px;
  border-radius: 4px;
}

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 10;
  background: var(--gold);
  color: var(--nachtblau);
  padding: 0.6rem 1rem;
  font-weight: 600;
}

.skip-link:focus {
  left: 0.5rem;
  top: 0.5rem;
}

.page {
  max-width: var(--measure);
  margin: 0 auto;
  padding: 1.5rem 1.25rem 5rem;
}

/* --- header and step trail --- */

/* The vertical lockup, and it is the header of every page: mark above,
   wordmark centred under it, the way the brand book draws the lockup. The
   access line follows on its own row, still centred.
 
   No rule beneath it. A line drawn a few pixels under the wordmark reads as
   part of the mark rather than as a separator; the room it used to give the
   heading is kept as padding, because h1 carries no top margin of its own. */
.masthead {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0;
  text-align: center;
  padding-bottom: 2.5rem;
}

.masthead__brand {
  font-family: var(--font-display);
  font-size: 1.5rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--gold);
  /* On the legal pages the brand is a link home. It should still look like
     the masthead and not like a sentence with a link in it. */
  text-decoration: none;
}

.masthead__access {
  font-size: 0.875rem;
  color: var(--muted);
}

/* --- the mark on the closed door --- */

/* The lotus of the brand, drawn rather than fetched: the geometry is in the
   markup, so there is no image request, nothing to go missing, and nothing
   for the CSP to have an opinion about.

   Everything here is proportional to --mark, which is the only number that
   changes between the two sizes. The rings sit at fixed fractions of it, so
   making the mark smaller cannot leave them stranded at the old radius. */
.brandmark {
  --mark: 96px;
  position: relative;
  width: var(--mark);
  height: var(--mark);
  /* Both ends measured in marks, not in pixels, so the one number above
     carries the whole composition. The lower one clears the outer ring,
     which overhangs the box by 0.417 of a mark: at 0.62 the wordmark
     stands about a fifth of a mark clear of it instead of the four
     pixels it had, where the lotus sat on the word. */
  margin: calc(var(--mark) * 0.5) auto calc(var(--mark) * 0.612);
}

/* The glow, and it is not a soft haze around the mark: in the brand's own
   drawing code it is thirty filled gold circles stacked from the outside in,
   each at 0.10 * (1 - t) ** 1.6, reaching 2.2 lotus radii. Stacked, they
   accumulate to 0.68 at the centre and fall away steeply — a warm core
   behind the flower rather than a wide mist.

   The stops below are that accumulation sampled every tenth of the radius,
   so this is the same curve rather than something that resembles it. The
   numbers come out of make_produktbilder.py, which is what draws the product
   covers, so the door and the shop now show one mark.

   `closest-side` matters: the default extent is the corner, and with it the
   glow would still be alive at the element's edge instead of ending there. */
.brandmark::before {
  content: "";
  position: absolute;
  inset: calc(var(--mark) * -0.358);
  border-radius: 50%;
  background: radial-gradient(
    circle closest-side,
    rgba(201, 162, 39, 0.680) 0%,
    rgba(201, 162, 39, 0.612) 10%,
    rgba(201, 162, 39, 0.502) 20%,
    rgba(201, 162, 39, 0.390) 30%,
    rgba(201, 162, 39, 0.283) 40%,
    rgba(201, 162, 39, 0.189) 50%,
    rgba(201, 162, 39, 0.112) 60%,
    rgba(201, 162, 39, 0.057) 70%,
    rgba(201, 162, 39, 0.021) 80%,
    rgba(201, 162, 39, 0.004) 90%,
    rgba(201, 162, 39, 0.000) 100%
  );
  pointer-events: none;
}

.ring,
.ring2 {
  position: absolute;
  border-radius: 50%;
  border: 1px solid var(--gold);
}

/* 1.42 and 1.72 lotus radii, which with a lotus of 0.39 of the box comes to
   these insets. They moved inward with the glow: the two are one drawing,
   measured against the same radius, and rings left outside the light would
   float in the dark with nothing holding them. */
.ring {
  inset: calc(var(--mark) * -0.054);
  opacity: 0.32;
}

.ring2 {
  inset: calc(var(--mark) * -0.171);
  opacity: 0.14;
}

.lotus {
  position: relative;
  display: block;
  width: 100%;
  height: 100%;
}

@media (max-width: 420px) {
  .brandmark {
    --mark: 80px;
  }
}

.trail {
  margin: 1.25rem 0 2rem;
}

.trail__list {
  display: flex;
  gap: 0.5rem;
  list-style: none;
  margin: 0;
  padding: 0;
  font-size: 0.8125rem;
  flex-wrap: wrap;
}

.trail__item {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  color: var(--muted);
}

.trail__item + .trail__item::before {
  content: "→";
  color: var(--line);
}

.trail__item[aria-current="step"] {
  color: var(--gold);
  font-weight: 600;
}

/* --- blocks --- */

.lead {
  font-size: 1.15rem;
  color: var(--champagner);
}

.note {
  background: var(--surface);
  border-left: 3px solid var(--gold);
  border-radius: 0 var(--radius) var(--radius) 0;
  padding: 0.9rem 1.1rem;
  margin: 0 0 1.5rem;
  color: var(--muted);
  font-size: 0.9375rem;
}

.note--error {
  border-left-color: #d97b6c;
  color: var(--champagner);
}

.card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 1.25rem;
  margin: 0 0 1.25rem;
}

.card__title {
  margin: 0 0 0.35rem;
  font-size: 1.35rem;
}

.card__about {
  color: var(--muted);
  font-size: 0.9375rem;
  margin-bottom: 1rem;
}

.list {
  padding-left: 1.2rem;
  margin: 0 0 1.5rem;
}

.list li {
  margin-bottom: 0.5rem;
}

.list--plain {
  list-style: none;
  padding-left: 0;
}

.sphere__name {
  color: var(--gold);
  font-weight: 600;
}

/* --- media --- */

.media {
  width: 100%;
  border-radius: var(--radius);
  background: #000;
  display: block;
}

.transcript {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 0.75rem 1rem;
  margin: 0 0 1.5rem;
  background: var(--surface);
}

.transcript > summary {
  cursor: pointer;
  font-weight: 600;
  color: var(--gold);
}

.speed {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  flex-wrap: wrap;
  margin-top: 0.9rem;
  font-size: 0.9375rem;
}

.speed__slider {
  flex: 1 1 11rem;
  min-width: 9rem;
  accent-color: var(--gold);
}

.speed__value {
  font-variant-numeric: tabular-nums;
  color: var(--gold);
  min-width: 3.2rem;
}

.mantra__text {
  font-family: var(--font-display);
  font-size: 1.3rem;
  line-height: 1.5;
  letter-spacing: 0.02em;
  color: var(--champagner);
  margin: 0;
}

/* --- form --- */

fieldset {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 1rem 1.15rem;
  margin: 0 0 1.5rem;
}

legend {
  font-family: var(--font-display);
  font-size: 1.25rem;
  padding: 0 0.4rem;
}

.check {
  display: flex;
  gap: 0.7rem;
  align-items: flex-start;
  margin-bottom: 0.75rem;
  cursor: pointer;
}

.check input {
  margin-top: 0.35rem;
  width: 1.15rem;
  height: 1.15rem;
  accent-color: var(--gold);
  flex: none;
}

.field {
  margin-bottom: 1.25rem;
}

.field__label {
  display: block;
  font-weight: 600;
  margin-bottom: 0.4rem;
}

.field__hint {
  color: var(--muted);
  font-size: 0.875rem;
  margin: 0.4rem 0 0;
}

textarea,
input[type="text"],
input[type="email"] {
  width: 100%;
  font: inherit;
  color: var(--champagner);
  background: var(--surface-soft);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 0.7rem 0.85rem;
}

textarea {
  min-height: 6.5rem;
  resize: vertical;
}

/* --- buttons --- */

.button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  /* 44px minimum touch target, the same floor the board uses. */
  min-height: 2.75rem;
  padding: 0.65rem 1.4rem;
  border: 1px solid var(--gold);
  border-radius: var(--radius);
  background: var(--gold);
  color: var(--nachtblau);
  font: inherit;
  font-weight: 600;
  cursor: pointer;
  text-decoration: none;
}

.button:hover {
  filter: brightness(1.08);
}

.button--quiet {
  background: transparent;
  color: var(--gold);
}

.button[disabled] {
  opacity: 0.45;
  cursor: not-allowed;
}

.actions {
  display: flex;
  gap: 0.75rem;
  align-items: center;
  flex-wrap: wrap;
  margin-top: 2rem;
}

.hidden {
  display: none !important;
}

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* --- the board ------------------------------------------------------- */

/* The board wants room the reading pages do not. */
.page--wide {
  max-width: 52rem;
}

.board {
  position: relative;
  /* Alex's picture is square, and the cell layer is positioned in per cent
     of it. Fixing the ratio here keeps the two aligned at every width, with
     no measuring in script. */
  aspect-ratio: 1 / 1;
  width: 100%;
  margin: 1rem 0 1.5rem;
  border-radius: var(--radius);
  overflow: hidden;
  /* The board takes the gestures, not the page: a player magnifying the
     board should not have to zoom back out of the text to read where they
     are. The page is still scrolled by touching anywhere else — the header
     above, the controls below. */
  touch-action: none;
  /* Without this a mouse drag selects the page instead of panning: the board
     fills with the selection colour and stops answering the pointer. */
  user-select: none;
  -webkit-user-select: none;
}

.board img {
  /* A dragged image becomes a drag-and-drop payload, which cancels the pan
     half way through and leaves a ghost picture under the cursor. */
  -webkit-user-drag: none;
  user-drag: none;
}

.board--zoomed {
  cursor: grab;
}

.board__stage {
  position: absolute;
  inset: 0;
  transform-origin: 0 0;
  /* No transition: a magnified board must track the fingers exactly, and a
     smoothed transform lags behind them. */
}

.board__image,
.board__cells,
.board__paths {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}

.board__image {
  display: block;
  object-fit: contain;
}

/* Snakes and arrows are drawn here, and only after the player asks to move
   on. Until then it is an empty layer that must not swallow a click. */
.board__paths {
  pointer-events: none;
}

.cell {
  position: absolute;
  padding: 0;
  margin: 0;
  border: 0;
  background: transparent;
  border-radius: 4%;
  /* The artwork is the cell; nothing is drawn on top of it unless the state
     of the game has something to say. */
  cursor: default;
}

.cell:disabled {
  /* A cell not yet walked on is part of the picture and nothing more: no
     pointer, no focus stop, no hint that there is something to miss. */
  pointer-events: none;
}

.cell--open {
  cursor: pointer;
}

.cell--open:hover,
.cell--open:focus-visible {
  box-shadow: inset 0 0 0 0.35vw var(--gold);
}

.cell--here {
  box-shadow: inset 0 0 0 0.45vw var(--champagner);
}

.cell--here.cell--open:hover,
.cell--here.cell--open:focus-visible {
  box-shadow: inset 0 0 0 0.45vw var(--gold);
}

/* --- the cell card ---------------------------------------------------- */

.sheet {
  width: min(34rem, calc(100vw - 2rem));
  max-height: calc(100vh - 3rem);
  padding: 0;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--champagner);
  overflow: auto;
}

.sheet::backdrop {
  background: rgb(6 11 22 / 0.78);
}

.sheet__body {
  padding: 1.5rem 1.35rem 2rem;
}

.sheet__level {
  margin: 0 0 0.25rem;
  font-size: 0.75rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--gold);
}

.sheet__title {
  margin: 0 0 1rem;
  font-size: 1.5rem;
}

.sheet__image {
  display: block;
  width: 100%;
  height: auto;
  border-radius: var(--radius);
  margin-bottom: 1.25rem;
  background: var(--surface-soft);
}

.sheet h3 {
  font-size: 1.1rem;
  margin-top: 1.5rem;
  /* Gold, so a heading is found by the eye before it is read: these blocks
     are long and the player is looking for one of them, not reading through. */
  color: var(--gold);
}

.sheet details {
  margin-bottom: 1rem;
}

.sheet summary {
  cursor: pointer;
  font-weight: 600;
  color: var(--gold);
}

/* The one line from the source's heading. It sits between the title and the
   picture because that is what it is: the shortest way to say what the cell
   is, before the reader looks at anything else. */
.sheet__idea {
  margin: -0.6rem 0 1.1rem;
  color: var(--gold);
  font-family: var(--font-display);
  font-size: 1.2rem;
  line-height: 1.35;
}

/* Two buttons of equal weight, one above the other: "Читать всё" opens the
   working material, "Закрыть" leaves. Neither outranks the other, so they
   look the same and sit in a column rather than competing across a row. */
.actions--stacked {
  flex-direction: column;
  align-items: stretch;
}

/* --- the zoom controls ------------------------------------------------ */

.zoom {
  display: flex;
  gap: 0.5rem;
  align-items: center;
  flex-wrap: wrap;
  margin-bottom: 0.5rem;
}

.zoom .button {
  padding: 0.55rem 0.9rem;
  font-size: 0.9375rem;
}

.zoom__level {
  /* Always on its own line, so it never splits the pair of buttons that
     belong together. */
  flex-basis: 100%;
  font-variant-numeric: tabular-nums;
  color: var(--muted);
  font-size: 0.875rem;
}

/* --- the history of moves --------------------------------------------- */

/* Narrow first: on a phone the column is a sheet on the bottom edge, closed
   until it is asked for. The board is why the player is here, and it is
   cramped enough at this width without a list taking half the screen. */
.history {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 5;
  display: flex;
  flex-direction: column;
  max-height: 70vh;
  background: var(--surface);
  border-top: 1px solid var(--line);
  padding: 0.5rem 1rem;
  /* Phones with a home bar draw over the bottom edge of the page. */
  padding-bottom: calc(0.5rem + env(safe-area-inset-bottom, 0px));
}

/* Room for the bar, so the last line of the page is not sitting under it.
   Measured against the closed sheet, with a finger's width to spare. */
.page--wide {
  padding-bottom: 6rem;
}

/* Reads like the level line on a cell card, because it does the same job:
   one small gold word saying what you are looking at. */
.history__game {
  margin: 0 0 0.125rem;
  font-size: 0.75rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--gold);
}

.history__game:empty {
  display: none;
}

.history__bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
}

.history__title {
  margin: 0;
  font-size: 1.0625rem;
}

.history__panel {
  display: none;
  overflow-y: auto;
  /* The list scrolls inside the sheet; the page behind it stays put. */
  overscroll-behavior: contain;
}

.history--open .history__panel {
  display: block;
}

.history__list {
  list-style: none;
  margin: 0.5rem 0 0;
  padding: 0;
}

.history__item {
  padding: 0.6rem 0;
  border-top: 1px solid var(--line);
}

.history__label {
  margin: 0 0 0.2rem;
  font-size: 0.8125rem;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}

.history__kind {
  margin: 0.25rem 0 0.2rem;
  font-size: 0.875rem;
  color: var(--muted);
}

/* A cell in the list is the cell on the board: the same text opens the same
   card. It is a button and looks like one word of a sentence, because a row
   of framed buttons would read as a menu. */
.history__cell {
  display: block;
  width: 100%;
  padding: 0.15rem 0;
  margin: 0;
  border: 0;
  background: transparent;
  color: var(--champagner);
  font: inherit;
  font-size: 0.9375rem;
  line-height: 1.4;
  text-align: left;
  cursor: pointer;
}

.history__cell:hover,
.history__cell:focus-visible {
  color: var(--gold);
  text-decoration: underline;
}

.history__item--quiet .history__label {
  color: var(--muted);
  font-style: italic;
}

/* Wide enough for both: the column stands to the right of the board and
   stays in place while the board is read. */
@media (min-width: 62rem) {
  .page--wide {
    max-width: 68rem;
    padding-bottom: 0;
  }

  .game {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 18rem;
    gap: 1.5rem;
    align-items: start;
  }

  .history {
    position: sticky;
    top: 1rem;
    z-index: auto;
    max-height: calc(100vh - 3rem);
    background: transparent;
    border-top: 0;
    padding: 0;
  }

  .history__toggle {
    /* Nothing to unfold: the panel is always open at this width. */
    display: none;
  }

  .history__panel {
    display: block;
  }
}

/* --- snakes and arrows ------------------------------------------------ */

/* The curve itself is the ruler, never the drawing. */
.move__geometry {
  fill: none;
  stroke: none;
}

/* The snake is a filled shape, not a stroke: a stroke is one width all the
   way along, and a snake is not. */
.move__body {
  fill: #3fa88b;
}

/* The same outline again, wider and dark, so the body holds its edge over
   the palest cells of the artwork. */
.move__shadow {
  fill: none;
  stroke: #06101f;
  stroke-width: 26;
  stroke-linejoin: round;
}

/* Gold across the back: the board is gold everywhere else, and a snake that
   borrowed none of it would look like it came from another drawing. */
.move__scales {
  fill: none;
  stroke: var(--gold);
  stroke-width: 9;
  stroke-linecap: round;
  opacity: 0.75;
}

.move__skull {
  /* Lighter than the body, so the head is found before it is examined. */
  fill: #5fd0ae;
  stroke: #06101f;
  stroke-width: 12;
  stroke-linejoin: round;
}

.move__eye {
  fill: #06101f;
}

.move__tongue {
  fill: none;
  stroke: #e2564f;
  /* Board units: at board size a cell is about 60 px, and a hairline tongue
     is no tongue at all. */
  stroke-width: 15;
  stroke-linecap: round;
}

/* --- the arrow -------------------------------------------------------- */

.move__shaft {
  fill: #e8d9a8;
  stroke: #06101f;
  stroke-width: 7;
  stroke-linejoin: round;
}

.move__point,
.move__fletch {
  fill: var(--gold);
  stroke: #06101f;
  stroke-width: 7;
  stroke-linejoin: round;
}

/* A stretch of curve just behind the point, and nothing ahead of it. */
.move__trail {
  fill: none;
  stroke: var(--gold);
  stroke-width: 16;
  stroke-linecap: round;
  opacity: 0.4;
}

/* --- the die ---------------------------------------------------------- */

/* Under the board, in the middle of it: the throw is what the player came
   to do, and the board is what they are looking at when they reach for it. */
.roll {
  display: flex;
  gap: 1rem;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  margin: 0.25rem 0 0.75rem;
}

.die {
  width: 4.5rem;
  height: 4.5rem;
  flex: none;
}

.die__body {
  fill: var(--champagner);
  stroke: #06101f;
  stroke-width: 3;
}

.die__pips circle {
  fill: var(--nachtblau);
}

/* Blank while it tumbles: a die flashing numbers on the way to a result
   suggests those numbers were results too. */
.die--rolling {
  animation: die-tumble 900ms cubic-bezier(0.3, 0, 0.2, 1);
}

@keyframes die-tumble {
  0% { transform: rotate(0deg) scale(1); }
  55% { transform: rotate(430deg) scale(1.12); }
  100% { transform: rotate(720deg) scale(1); }
}

.roll__say {
  text-align: center;
  color: var(--champagner);
  margin: 0;
}

.roll__say--quiet {
  color: var(--muted);
}

@media (prefers-reduced-motion: reduce) {
  .die--rolling {
    animation: none;
  }
}

/* A snake that stayed on the board after it had carried the player would be
   a line drawn on Alex's artwork, and the artwork is the board. */
.move--leaving {
  opacity: 0;
  transition: opacity 500ms ease-out;
}

@media (prefers-reduced-motion: reduce) {
  .move--leaving {
    transition: none;
  }
}

/* ---- the legal pages ---------------------------------------------------
   Impressum and Datenschutzerklärung are plain HTML with no script behind
   them, so everything they need has to be reachable from the tag alone. */

.legal {
  margin-top: 3rem;
  padding-top: 1.25rem;
  border-top: 1px solid rgba(239, 231, 216, 0.18);
  display: flex;
  gap: 1.5rem;
  font-size: 0.8125rem;
}

.legal a {
  /* Quieter than a link in the text: present on every page, and never the
     thing anyone came for. */
  color: rgba(239, 231, 216, 0.65);
  text-decoration: none;
}

.legal a:hover,
.legal a:focus {
  color: var(--gold);
  text-decoration: underline;
}

/* The two pages are the only place with a third heading level in running
   text; everywhere else h3 belongs to a card. */
#content h3 {
  font-size: 1.0625rem;
  margin-top: 1.6rem;
  color: var(--gold);
}

#content ul {
  margin: 0 0 1.1em;
  padding-left: 1.25rem;
}

#content li {
  margin-bottom: 0.5em;
}

#content hr {
  border: 0;
  border-top: 1px solid rgba(239, 231, 216, 0.18);
  margin: 3rem 0 2.5rem;
}

#content code {
  font-size: 0.9em;
  color: var(--gold);
}

/* What is still missing from these pages. Meant to be impossible to publish
   by accident: Alex's own details go here, and until they do the gap shows.
   The dashed frame is not decoration, it is the alarm. */
#content mark {
  background: transparent;
  color: var(--gold);
  border: 1px dashed var(--gold);
  border-radius: 2px;
  padding: 0 0.35em;
}
