/* The simulator. It wears the website's look (web/css/site.css, from brand-ideas/opensky): the evening sky,
   cloud paper, the signal orange, and the same three type roles. The table hangs in that sky.

   What lies on the table is drawn to the real sizes (docs/hardware.md, docs/components.md): a 50 mm white tile
   with a 42 mm window, a 410 mm felt mat, 5 mm between tiles. One millimetre is var(--u) pixels. Tiles never
   glow: marks on them are solid ink, and anything that beckons sits on the felt. Light belongs to the sky. */

:root {
  /* the sky and the paper */
  --dusk: #052766; --dusk-deep: #0a1a4a; --violet: #6e62b8; --peach: #d5a6a2; --cloud: #fbf1e6; --signal: #f0642b;
  --ink: #1b1d3c; --blossom: #f4a9b8; --muted: rgba(27, 29, 60, .62); --rule: rgba(27, 29, 60, .1);
  --shade: 3, 8, 34;                      /* a shadow in the sky is the night's own blue */
  --panel: radial-gradient(120% 100% at 26% 12%, #1c3f97, #0d2260 80%);   /* a piece of night set into paper */
  /* the product */
  --tile: #fbfbf8;
  --panel-white: #c6c3ba;                 /* the display's own white: PANEL_LOOK in tools/faces/make_faces.py */
  --felt: #3b3c3e;
  --mark: #17171a;                        /* solid ink on a tile */
  /* type: the website's stand-ins, all system fonts */
  --display: "HelveticaNeue-CondensedBlack", "Helvetica Neue Condensed Black", "Arial Narrow Bold", Impact, sans-serif;
  --body: "Avenir Next", Avenir, "Helvetica Neue", Helvetica, Arial, sans-serif;
  --plate: "DIN Alternate", "DIN Condensed", "Helvetica Neue", Arial, sans-serif;
  --out: cubic-bezier(.22, 1, .36, 1);
}

* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
  margin: 0;
  min-height: 100vh;
  min-height: 100dvh;
  background: var(--dusk-deep);
  color: var(--ink);
  font: 500 15.5px/1.45 var(--body);
  -webkit-font-smoothing: antialiased;
}
h1, h2, h3, p { margin: 0; }
button, select, input { font: inherit; color: inherit; }
a { color: inherit; }
:focus-visible { outline: 3px solid var(--signal); outline-offset: 3px; }

.app { position: relative; z-index: 1; min-height: 100vh; min-height: 100dvh; display: grid; grid-template-rows: auto 1fr; }

/* ---------------------------------------------------------------- the sky
   One sky behind every screen. The shelf stands at dusk, on a floor of cloud with the moon up. Setting a game
   up climbs a little; at the table it is night, the clouds are far below and dim, and the white tiles are
   the brightest things there are. */

.sky {
  position: fixed;
  inset: 0;
  z-index: 0;
  overflow: hidden;
  pointer-events: none;
  background: linear-gradient(#052767 0%, #0b3178 32%, #164092 60%, #2c51a9 76%, #6a62b6 89%, #b78fae 96%, #d5a6a2 100%);
}
.sky > * { position: absolute; }
.sky__night { inset: 0; opacity: 0; background: radial-gradient(120% 95% at 30% 6%, #17398c 0%, #0d2669 46%, #081a50 100%); transition: opacity 1.1s ease; }
.sky__stars {
  inset: 0;
  opacity: .9;
  background:
    radial-gradient(1.6px 1.6px at 12% 9%, #fff4d0 50%, transparent 51%), radial-gradient(1.2px 1.2px at 31% 22%, #fff 50%, transparent 51%),
    radial-gradient(2px 2px at 47% 6%, #ffe9a8 50%, transparent 51%), radial-gradient(1.3px 1.3px at 63% 17%, #fff 50%, transparent 51%),
    radial-gradient(1.8px 1.8px at 78% 4%, #fff4d0 50%, transparent 51%), radial-gradient(1.2px 1.2px at 91% 26%, #fff 50%, transparent 51%),
    radial-gradient(1.5px 1.5px at 5% 33%, #fff 50%, transparent 51%), radial-gradient(1.4px 1.4px at 22% 41%, #ffe9a8 50%, transparent 51%),
    radial-gradient(1.2px 1.2px at 56% 36%, #fff 50%, transparent 51%), radial-gradient(1.7px 1.7px at 84% 44%, #fff4d0 50%, transparent 51%),
    radial-gradient(1.2px 1.2px at 38% 58%, #fff 50%, transparent 51%), radial-gradient(1.3px 1.3px at 70% 63%, #fff 50%, transparent 51%);
  background-size: 620px 520px;
  -webkit-mask-image: linear-gradient(#000 36%, transparent 78%);
  mask-image: linear-gradient(#000 36%, transparent 78%);
}
/* the stars low in the sky come out when it is night down there too */
.sky__stars--low { opacity: 0; background-position: 310px 190px; -webkit-mask-image: linear-gradient(transparent 34%, #000 80%); mask-image: linear-gradient(transparent 34%, #000 80%); transition: opacity 1.1s ease; }
/* a handful of brighter ones, which come and go */
.sky__stars--bright {
  background:
    radial-gradient(2.6px 2.6px at 17% 15%, #fff4d0 50%, transparent 52%), radial-gradient(2.2px 2.2px at 69% 8%, #fff 50%, transparent 52%),
    radial-gradient(2.4px 2.4px at 43% 27%, #ffe9a8 50%, transparent 52%), radial-gradient(2.1px 2.1px at 88% 34%, #fff 50%, transparent 52%),
    radial-gradient(2.2px 2.2px at 7% 47%, #fff4d0 50%, transparent 52%), radial-gradient(2px 2px at 58% 52%, #fff 50%, transparent 52%);
  background-size: auto;
  -webkit-mask-image: none;
  mask-image: none;
  animation: twinkle 4.8s ease-in-out infinite alternate;
}
@keyframes twinkle { from { opacity: .2; } to { opacity: .95; } }

.sky__moon { right: -104px; top: 34px; width: 340px; height: auto; transition: translate 1.3s var(--out), opacity 1.1s ease; }
.sky__cloud {
  width: var(--w);
  height: auto;
  max-width: none;
  /* the cloud sits in the middle of its picture: this puts its underside --up above the bottom of the window */
  bottom: calc(var(--w) * -.29 + var(--up, 0px));
  animation: drift var(--dur, 48s) ease-in-out infinite alternate;
  transition: translate 1.3s var(--out), opacity 1.1s ease;
}
.sky__cloud--a { --w: 660px; --up: -34px; --d: 34px; left: -70px; }
.sky__cloud--b { --w: 540px; --up: 6px; --d: 46px; --dur: 60s; left: 33%; }
.sky__cloud--c { --w: 520px; --up: -22px; --d: 30px; --dur: 54s; right: -80px; }
.sky__cloud--d { --w: 380px; --up: 150px; --d: 52px; --dur: 66s; left: 8%; opacity: .9; }
.sky__cloud--e { --w: 260px; --up: 116px; --d: 40px; --dur: 72s; right: 16%; opacity: .92; }
@keyframes drift { from { transform: translate3d(calc(var(--d, 30px) * -1), 0, 0); } to { transform: translate3d(var(--d, 30px), 0, 0); } }

body[data-screen='setup'] .sky__night { opacity: .5; }
body[data-screen='setup'] .sky__stars--low { opacity: .45; }
body[data-screen='setup'] .sky__moon { translate: 26px -40px; }
body[data-screen='setup'] .sky__cloud { translate: 0 70px; }
body[data-screen='setup'] :is(.sky__cloud--d, .sky__cloud--e) { opacity: .5; }

body[data-screen='play'] .sky__night { opacity: 1; }
body[data-screen='play'] .sky__stars--low { opacity: .8; }
body[data-screen='play'] .sky__moon { translate: 80px -150px; opacity: 0; }
body[data-screen='play'] .sky__cloud { translate: 0 150px; opacity: 0; }
body[data-screen='play'] :is(.sky__cloud--a, .sky__cloud--c) { translate: 0 26px; opacity: .2; }

/* ---------------------------------------------------------------- top bar */

.top { position: relative; z-index: 5; display: flex; align-items: center; gap: 8px 20px; flex-wrap: wrap; padding: 12px 22px 10px; color: var(--cloud); }

/* the logo (brand-ideas/fullstop): the back of a tile, white with its one button, beside the name.
   Point at it and it turns over to a face from one of the games. */
.logo { display: inline-flex; align-items: center; gap: .26em; font-size: 38px; text-decoration: none; flex: none; border-radius: 6px; }
.logo__tile { width: 1em; height: 1em; flex: none; perspective: 6em; }
.logo__card { position: relative; display: block; width: 100%; height: 100%; transform-style: preserve-3d; transition: transform .62s cubic-bezier(.3, .9, .3, 1); }
.logo__back, .logo__front { position: absolute; inset: 0; border-radius: 8.4%; -webkit-backface-visibility: hidden; backface-visibility: hidden;
  box-shadow: 0 .04em .07em rgba(var(--shade), .28), 0 .16em .3em -.08em rgba(var(--shade), .45); }
.logo__back { background: var(--cloud); }
.logo__back::after { content: ''; position: absolute; right: 6.8%; bottom: 6.8%; width: 22.4%; aspect-ratio: 1; border-radius: 50%; background: var(--signal); }
.logo__front { background: #f2f1ed; transform: rotateY(180deg); }
.logo__front b { position: absolute; inset: 8%; border-radius: 4.8%; background: var(--panel-white) url('../img/brand/flip.webp') calc(var(--f, 0) * 20%) 0 / 600% 100% no-repeat; }
.logo.is-up .logo__card { transform: rotateY(180deg); }
.logo__word { width: auto; height: .86em; }

.top__tag { padding-left: 16px; border-left: 1.5px solid rgba(251, 241, 230, .26); font: 700 12px/2.2 var(--plate); letter-spacing: .2em; text-transform: uppercase; color: var(--blossom); text-decoration: none; transition: color .2s; }
.top__tag:hover { color: var(--cloud); }
.top__crumbs { flex: 1; min-width: 0; display: flex; gap: 10px; white-space: nowrap; font: 700 12px/1 var(--plate); letter-spacing: .15em; text-transform: uppercase; }
.top__crumbs > * { color: rgba(251, 241, 230, .7); text-decoration: none; transition: color .2s; }
.top__crumbs > :last-child { color: var(--cloud); }
.top__crumbs > * + *::before { content: '›'; margin-right: 10px; color: rgba(251, 241, 230, .45); }
.top__crumbs a:hover { color: var(--blossom); }

/* buttons: the one that moves things on, and the quiet one beside it */
.go, .quiet {
  display: inline-block;
  border: 0;
  border-radius: 999px;
  cursor: pointer;
  text-align: center;
  text-decoration: none;
  white-space: nowrap;
  font: 700 14px/1 var(--plate);
  letter-spacing: .14em;
  text-transform: uppercase;
  transition: background-color .2s, transform .18s var(--out);
}
.go { padding: 1.1em 1.5em 1.04em; background: var(--signal); color: #fff; }
.go:hover { background: #ff7a41; }
.go:active { transform: scale(.97); background: #d64f1f; }
.quiet { padding: .9em 1.2em .82em; font-size: 12px; background: color-mix(in srgb, currentColor 11%, transparent); }
.quiet:hover { background: color-mix(in srgb, currentColor 20%, transparent); }

.eyebrow { font: 700 13px/1.2 var(--plate); letter-spacing: .2em; text-transform: uppercase; color: var(--blossom); }
/* the full stop that ends a line the way it ends the name */
.stop { display: inline-block; width: .18em; height: .18em; margin-left: .035em; border-radius: 50%; background: var(--signal); }

/* paper in the sky: cloud white on a soft, layered shadow */
.card {
  background: var(--cloud);
  border-radius: 26px;
  box-shadow: 0 2px 5px rgba(var(--shade), .16), 0 18px 34px -14px rgba(var(--shade), .5), 0 44px 70px -38px rgba(var(--shade), .75);
}

/* A player's mark: their colour with their symbol. */
.chip {
  flex: none;
  display: inline-grid;
  place-items: center;
  width: 1.5em;
  height: 1.5em;
  border-radius: 50%;
  background: var(--paint);
  isolation: isolate;
  vertical-align: middle;
}
.chip[hidden] { display: none; }
.chip img { width: 68%; height: 68%; mix-blend-mode: screen; }
.chip--dark-ink img { filter: invert(1); mix-blend-mode: multiply; }

/* things arrive when the screen changes, never on a redraw of the same screen */
.is-fresh :is(.shelf > :not(.shelf__games), .box, .setup > *, .side > *) { animation: arrive .7s var(--out) both; }
.is-fresh .shelf__line { animation-delay: .06s; }
.is-fresh .box { animation-delay: calc(.12s + var(--i, 0) * .07s); }
.is-fresh :is(.setup, .side) > :nth-child(2) { animation-delay: .1s; }
.is-fresh .table__stage { animation: land .8s var(--out) both; }
@keyframes arrive { from { opacity: 0; transform: translate3d(0, 22px, 0); } }
@keyframes land { from { opacity: 0; transform: translate3d(0, 26px, 0) scale(.975); } }

/* ---------------------------------------------------------------- the shelf */

.shelf { max-width: 1200px; width: 100%; margin: 0 auto; padding: clamp(18px, 5vh, 54px) 24px 96px; color: var(--cloud); }
/* the words carry a little of the night with them, so a cloud or the moon behind a letter falls back from it */
.shelf h1, .shelf__line { text-shadow: 0 0 1px rgba(6, 41, 107, .95), 0 0 4px rgba(6, 41, 107, .8), 0 0 14px rgba(6, 41, 107, .4); }
.shelf h1 { margin-top: 14px; font: 400 clamp(50px, 7.2vw, 96px)/.98 var(--display); letter-spacing: .005em; }
.shelf__line { margin-top: 18px; max-width: 29em; font: 400 clamp(17px, 1.6vw, 21px)/1.5 var(--body); text-wrap: pretty; }
.shelf__games { display: grid; grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); gap: 24px; margin-top: clamp(26px, 4.5vh, 44px); }

/* a game: paper, with a piece of the sky set into it and three of its tiles hanging there */
.box {
  position: relative;
  display: flex;
  flex-direction: column;
  padding: 12px 12px 14px;
  border-radius: 26px;
  background: var(--cloud);
  color: var(--ink);
  text-decoration: none;
  box-shadow: 0 2px 5px rgba(var(--shade), .16), 0 18px 34px -14px rgba(var(--shade), .5), 0 44px 70px -38px rgba(var(--shade), .75);
  transition: translate .34s var(--out), box-shadow .34s var(--out);
}
.box:hover, .box:focus-visible { translate: 0 -7px; box-shadow: 0 2px 5px rgba(var(--shade), .16), 0 26px 40px -14px rgba(var(--shade), .55), 0 60px 80px -36px rgba(var(--shade), .8); }
.box h2 { margin: 18px 8px 0; font: 400 34px/1 var(--display); letter-spacing: .01em; }
.box > p { margin: 7px 8px 0; font-size: 15.5px; line-height: 1.42; text-wrap: pretty; }
.box > .box__meta { display: flex; align-items: center; gap: 0 .7em; flex-wrap: wrap; margin-top: auto; padding-top: 16px; min-height: 50px;
  font: 700 11px/1.3 var(--plate); letter-spacing: .14em; text-transform: uppercase; color: var(--muted); }
.box__meta span + span::before { content: '·'; margin-right: .7em; }
.box__go { flex: none; margin-left: auto; width: 34px; height: 34px; border-radius: 50%; display: grid; place-items: center; background: rgba(27, 29, 60, .07); color: var(--ink);
  transition: background-color .25s, color .25s, transform .3s var(--out); }
.box__go::before { content: ''; width: 9px; height: 9px; margin-left: -3px; border: solid currentColor; border-width: 2.2px 2.2px 0 0; border-radius: 1px; rotate: 45deg; }
.box:hover .box__go, .box:focus-visible .box__go { background: var(--signal); color: #fff; transform: translate3d(3px, 0, 0); }

.box__cover {
  --u: 1.5px;
  position: relative;
  isolation: isolate;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 5.5%;
  padding: 19% 9% 17%;
  border-radius: 17px;
  overflow: hidden;
  background: var(--piece, linear-gradient(165deg, #0a1a4a, #1b4298 55%, #5d61b4));
}
.box__cover::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -2;
  opacity: var(--stars, 1);
  background:
    radial-gradient(1.4px 1.4px at 14% 16%, #fff4d0 50%, transparent 51%), radial-gradient(1.1px 1.1px at 30% 44%, #fff 50%, transparent 51%),
    radial-gradient(1.6px 1.6px at 84% 12%, #ffe9a8 50%, transparent 51%), radial-gradient(1.1px 1.1px at 90% 52%, #fff 50%, transparent 51%),
    radial-gradient(1.3px 1.3px at 62% 24%, #fff 50%, transparent 51%), radial-gradient(1.2px 1.2px at 8% 70%, #fff4d0 50%, transparent 51%);
}
.box__cloud { position: absolute; z-index: -1; left: var(--cl, -24%); bottom: 0; width: var(--cw, 92%); height: auto; max-width: none; translate: 0 43%; --d: 9px; animation: drift var(--dur, 26s) ease-in-out infinite alternate; }
/* each game has its own hour of the evening */
.box:nth-child(4n + 2) .box__cover { --piece: linear-gradient(165deg, #3f55ab, #8176ba 56%, #dcaea6); --stars: .35; --cl: 36%; --cw: 84%; --dur: 31s; }
.box:nth-child(4n + 3) .box__cover { --piece: linear-gradient(165deg, #123a8c, #3f55ab 52%, #8d7dbb); --stars: .7; --cl: -10%; --cw: 70%; --dur: 23s; }
.box:nth-child(4n + 4) .box__cover { --piece: linear-gradient(165deg, #5560b2, #9a80b8 52%, #e2b4a8); --stars: .25; --cl: 30%; --cw: 96%; --dur: 34s; }

/* the three tiles: each at its own height, a little turned, and never quite still */
.cover-tile { position: relative; aspect-ratio: 1; transition: translate .5s var(--out), rotate .5s var(--out); animation: float var(--dur, 7s) ease-in-out infinite; animation-delay: var(--delay, 0s); }
.cover-tile:nth-of-type(1) { translate: 0 15%; rotate: -6deg; --dur: 7.6s; }
.cover-tile:nth-of-type(2) { translate: 0 -15%; rotate: 2deg; --dur: 6.4s; --delay: -2.2s; z-index: 1; }
.cover-tile:nth-of-type(3) { translate: 0 9%; rotate: 7deg; --dur: 8.3s; --delay: -4.4s; }
.box:is(:hover, :focus-visible) .cover-tile:nth-of-type(1) { translate: -5% 4%; rotate: -10deg; }
.box:is(:hover, :focus-visible) .cover-tile:nth-of-type(2) { translate: 0 -26%; rotate: 0deg; }
.box:is(:hover, :focus-visible) .cover-tile:nth-of-type(3) { translate: 5% -1%; rotate: 11deg; }
@keyframes float { 50% { transform: translate3d(0, -5%, 0); } }
.box__cover .tile__side { box-shadow: inset 0 0 0 1px rgba(27, 29, 60, .08), 0 2px 3px rgba(var(--shade), .28), 0 13px 17px -5px rgba(var(--shade), .5); }

/* ---------------------------------------------------------------- setup */

.setup { max-width: 1100px; width: 100%; margin: 0 auto; padding: clamp(8px, 2vh, 24px) 24px 72px; display: grid; grid-template-columns: minmax(0, 440px) minmax(0, 1fr); gap: 30px; align-items: start; }
.setup > .card { padding: 14px 14px 0; }
.setup .box__cover { padding: 8.5% 14% 7.5%; gap: 9%; }
.setup__form { padding: 20px 12px 0; }
.setup .card .eyebrow { color: var(--signal); font-size: 12px; }
.setup h1 { margin-top: 8px; font: 400 clamp(40px, 4.4vw, 50px)/.98 var(--display); letter-spacing: .005em; }
.setup__line { margin-top: 8px; font-size: 16.5px; line-height: 1.42; text-wrap: pretty; }
.setup h2 { margin: 20px 0 6px; font: 700 11.5px/1.2 var(--plate); letter-spacing: .18em; text-transform: uppercase; color: var(--muted); }
.seat { display: flex; align-items: center; gap: 10px; padding: 4px 0; }
.seat > span { width: 4.6em; font-weight: 700; }
.seat > .seat__wide { width: calc(4.6em + 1.5em + 10px); }
.seat select, .seat input, .field input {
  flex: 1;
  min-width: 0;
  padding: 10px 14px;
  border: 0;
  border-radius: 12px;
  background-color: #fff;
  box-shadow: inset 0 0 0 1px var(--rule), 0 1px 2px rgba(27, 29, 60, .06), 0 6px 12px -10px rgba(27, 29, 60, .4);
  font-weight: 600;
}
select {
  -webkit-appearance: none;
  appearance: none;
  cursor: pointer;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'%3E%3Cpath d='M1.5 1.5 6 6l4.5-4.5' fill='none' stroke='%231b1d3c' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") right 14px center / 11px auto no-repeat;
}
.seat select { padding-right: 36px; }
:is(select, input):focus-visible { outline-offset: 1px; }
/* the button that deals stays in reach at the foot of the window, however long the form above it */
.setup__go { position: sticky; bottom: 0; z-index: 2; margin: 2px -12px 0; padding: 18px 12px 16px; border-radius: 0 0 26px 26px; background: linear-gradient(rgba(251, 241, 230, 0), var(--cloud) 16px); }
.setup__go .go { display: block; width: 100%; font-size: 16px; box-shadow: 0 12px 20px -12px rgba(240, 100, 43, .8); }

/* how to play: cloud type on a pane of the night */
.rules { padding: 30px 34px 34px; border-radius: 26px; color: var(--cloud); background: rgba(8, 22, 72, .46); -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px);
  box-shadow: inset 0 1px 0 rgba(251, 241, 230, .09), 0 34px 60px -36px rgba(var(--shade), .8); }
.rules p:not(.eyebrow) { position: relative; max-width: 37em; padding-left: 24px; font: 400 16.5px/1.52 var(--body); text-wrap: pretty; }
.rules p + p { margin-top: 12px; }
.rules p:not(.eyebrow)::before { content: ''; position: absolute; left: 3px; top: .62em; width: 6px; height: 6px; border-radius: 50%; background: var(--signal); }
.rules .eyebrow + p:not(.eyebrow) { margin: 14px 0 20px; padding-left: 0; font-size: clamp(19px, 1.7vw, 22px); line-height: 1.42; }
.rules .eyebrow + p::before { display: none; }

/* ---------------------------------------------------------------- the table and the panel beside it */

@media (min-width: 861px) { body[data-screen='play'] .app { height: 100vh; height: 100dvh; } }
/* Clipped at its own edge: the panel arrives from just below the window, and that must not make the page taller for a moment. */
.play { display: grid; grid-template-columns: minmax(0, 1fr) 360px; gap: 18px; padding: 4px 18px 18px; min-height: 520px; overflow: hidden; overflow: clip; }
.play__table { position: relative; min-width: 0; min-height: 0; }
.table { display: grid; place-items: center; overflow: hidden; }
.table__stage { position: relative; }

/* The panel: paper for who plays and whose move it is, and under it a pane of the night for what has
   happened, the rules and the state. The pane takes whatever height is left, so an empty log is just sky. */
.side { min-width: 0; min-height: 0; display: grid; grid-template-rows: auto minmax(170px, 1fr); gap: 14px; }
.side__card { padding-bottom: 12px; }
.side__head { display: flex; justify-content: space-between; align-items: center; gap: 10px; padding: 18px 18px 12px; }
/* a game's name is on a plate, as on the website */
.side__head strong { display: inline-flex; align-items: center; gap: .55em; padding: .62em .7em .56em; border-radius: .28em; background: var(--ink); color: var(--cloud);
  box-shadow: inset 0 0 0 .11em var(--ink), inset 0 0 0 .17em var(--cloud); font: 700 15px/1 var(--plate); letter-spacing: .14em; text-transform: uppercase; white-space: nowrap; }
.side__head strong::before, .side__head strong::after { content: ''; width: .16em; height: .16em; border-radius: 50%; background: var(--cloud); }
.side__head span { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font: 700 10.5px/1.3 var(--plate); letter-spacing: .14em; text-transform: uppercase; color: var(--muted); }

.side__book { min-height: 0; display: grid; grid-template-rows: auto minmax(0, 1fr) auto; overflow: hidden; border-radius: 26px; color: var(--cloud);
  background: rgba(251, 241, 230, .075); -webkit-backdrop-filter: blur(12px); backdrop-filter: blur(12px);
  box-shadow: inset 0 1px 0 rgba(251, 241, 230, .1), 0 34px 60px -36px rgba(var(--shade), .8); }
.side__foot { padding: 10px 18px 14px; font: 700 10.5px/1.3 var(--plate); letter-spacing: .14em; text-transform: uppercase; color: rgba(251, 241, 230, .62); }
.side__foot select { margin-left: 6px; padding: 6px 28px 6px 12px; border: 0; border-radius: 999px; font: inherit; color: var(--cloud);
  background: rgba(251, 241, 230, .1) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'%3E%3Cpath d='M1.5 1.5 6 6l4.5-4.5' fill='none' stroke='%23fbf1e6' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") right 11px center / 9px auto no-repeat; }
.side__foot option { background: #fff; color: var(--ink); }

.players { list-style: none; margin: 0; padding: 0 12px; display: grid; gap: 2px; }
.players li { display: flex; align-items: center; gap: 10px; padding: 7px 10px; border-radius: 15px; transition: background-color .25s; }
.players li.is-turn { background: #fff; box-shadow: 0 1px 2px rgba(27, 29, 60, .08), 0 10px 18px -12px rgba(27, 29, 60, .45); }
.players .chip { font-size: 18px; }
.players__name { flex: 1; min-width: 0; font-size: 16px; font-weight: 700; line-height: 1.15; }
.players__name small { display: block; margin-top: 3px; font: 700 10px/1.2 var(--plate); letter-spacing: .14em; text-transform: uppercase; color: var(--muted); }
.players__tally { font-size: 13px; font-weight: 600; color: var(--muted); white-space: nowrap; }
.players li.is-turn .players__tally { color: var(--ink); }
.players li.is-thinking .players__tally { animation: think 1.1s ease-in-out infinite alternate; }
@keyframes think { from { opacity: .35; } }

/* what is happening now. When the move is yours, it is a piece of the night with the moves in it. */
.now { margin: 10px 12px 0; padding: 14px 16px 15px; border-radius: 20px; background: rgba(27, 29, 60, .06); }
.now--yours, .now--over { background: var(--panel); color: var(--cloud); box-shadow: 0 18px 28px -18px rgba(10, 26, 74, .85); }
.now.is-new { animation: your-move .75s ease-out; }
@keyframes your-move { from { box-shadow: 0 18px 28px -18px rgba(10, 26, 74, .85), 0 0 0 0 rgba(240, 100, 43, .55); } to { box-shadow: 0 18px 28px -18px rgba(10, 26, 74, .85), 0 0 0 12px rgba(240, 100, 43, 0); } }
.now__badge { margin-bottom: 5px; font: 700 11.5px/1.3 var(--plate); letter-spacing: .18em; text-transform: uppercase; color: var(--blossom); }
.now__status { font-size: 17px; font-weight: 600; line-height: 1.3; text-wrap: balance; }
.now__help { margin-top: 5px; font-size: 13.5px; line-height: 1.4; opacity: .82; }
.now__moves { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 12px; align-items: center; }
.now__moves button:not(.go):not(.quiet) { padding: 8px 12px; border: 0; border-radius: 12px; background: var(--cloud); color: var(--ink); cursor: pointer; text-align: left;
  font: 600 13px/1.3 var(--body); transition: background-color .2s, transform .18s var(--out); }
.now__moves button:not(.go):not(.quiet):hover { background: #fff; transform: translate3d(0, -1px, 0); }
.now .go { margin-top: 12px; }
.now__moves .go { margin-top: 0; }
/* the end of a game: who won, as a headline */
.now__winners { display: flex; gap: 6px; margin-bottom: 10px; font-size: 22px; }
.now__winners .chip { box-shadow: 0 0 0 2px rgba(251, 241, 230, .9); }
.now--over .now__status { font: 400 30px/1.02 var(--display); letter-spacing: .01em; }

.tabs { justify-self: start; display: flex; gap: 2px; margin: 14px 14px 0; padding: 3px; border-radius: 999px; background: rgba(251, 241, 230, .09); }
.tabs button { padding: 7px 14px 6px; border: 0; border-radius: 999px; background: transparent; color: rgba(251, 241, 230, .66); cursor: pointer; font: 700 11px/1 var(--plate); letter-spacing: .14em; text-transform: uppercase; transition: color .2s; }
.tabs button:hover { color: var(--cloud); }
.tabs button.is-on { background: var(--cloud); color: var(--ink); }
.pane { margin: 0; padding: 14px 20px 22px; overflow: auto; font-size: 14px; line-height: 1.42; scrollbar-width: thin; scrollbar-color: rgba(251, 241, 230, .28) transparent;
  -webkit-mask-image: linear-gradient(#000 calc(100% - 22px), transparent); mask-image: linear-gradient(#000 calc(100% - 22px), transparent); }   /* what runs on below fades out */
.log { list-style: none; display: grid; gap: 8px; align-content: start; }
.log li { display: flex; gap: 8px; align-items: flex-start; }
.log li:not(:first-child) { opacity: .7; }
.log .chip { font-size: 11.5px; margin-top: 1px; box-shadow: 0 0 0 1px rgba(251, 241, 230, .22); }
.log__talk span { padding: 6px 11px; border-radius: 4px 14px 14px 14px; background: rgba(251, 241, 230, .12); font-style: italic; }
.log__note { color: #ffb797; }
.pane--rules p + p { margin-top: 9px; }
.state h3 { margin: 10px 0 5px; font: 700 10.5px/1.3 var(--plate); letter-spacing: .16em; text-transform: uppercase; color: rgba(251, 241, 230, .62); }
.state h3:first-child { margin-top: 0; }
.state ol { margin: 0; padding-left: 1.5em; }
.state pre { margin: 0 0 12px; padding: 11px 12px; border-radius: 12px; background: rgba(4, 12, 46, .4); font: 11px/1.4 ui-monospace, Menlo, monospace; white-space: pre-wrap; word-break: break-word; }
.state .quiet { white-space: normal; line-height: 1.3; }

/* The cover: cloud rolls in over the table while the next person takes the screen. */
.curtain { position: absolute; inset: 0; z-index: 200; display: grid; place-items: center; padding: 20px; overflow: hidden; text-align: center;
  background: radial-gradient(closest-side, rgba(11, 32, 92, .76), rgba(11, 32, 92, .62) 62%, rgba(11, 32, 92, 0)); -webkit-backdrop-filter: blur(16px); backdrop-filter: blur(16px); }
.curtain__cloud { position: absolute; width: min(78%, 620px); height: auto; max-width: none; pointer-events: none; animation: roll-in 1s var(--out) both, drift 30s ease-in-out 1s infinite alternate; }
.curtain__cloud:nth-of-type(1) { left: 3%; top: 4%; --from: -60%; --d: 14px; }
.curtain__cloud:nth-of-type(2) { right: 3%; bottom: 2%; --from: 60%; --d: -14px; }
@keyframes roll-in { from { translate: var(--from, -60%) 0; opacity: 0; } }
.curtain .card { position: relative; max-width: 380px; padding: 30px 30px 28px; animation: arrive .5s var(--out) both; }
.curtain h2 { display: flex; gap: 12px; justify-content: center; align-items: center; font: 400 36px/1 var(--display); letter-spacing: .01em; }
.curtain h2 .chip { font-size: 22px; }
.curtain p { margin: 12px 0 20px; font-size: 16.5px; text-wrap: balance; }

/* The end of a game: paper lanterns go up round the table. Their light is in the sky, never on a tile. */
.lanterns { position: absolute; inset: 0; z-index: 0; display: none; pointer-events: none; }
.is-over > .lanterns { display: block; }
.lantern { position: absolute; left: var(--at); bottom: -46px; width: 26px; opacity: 0; animation: rise var(--dur, 22s) linear infinite; animation-delay: var(--delay, 0s); }
.lantern img { position: relative; display: block; width: 100%; height: auto; filter: brightness(1.12) saturate(1.1); }
.lantern::before { content: ''; position: absolute; inset: -190% -230%; border-radius: 50%;
  background: radial-gradient(closest-side, rgba(255, 232, 130, .7), rgba(255, 214, 92, .32) 34%, rgba(255, 200, 70, .1) 62%, rgba(255, 200, 70, 0));
  animation: glow 3.4s ease-in-out infinite; animation-delay: var(--delay, 0s); }
@keyframes glow { 50% { opacity: .68; transform: scale(.92); } }
@keyframes rise { 0% { transform: translate3d(0, 0, 0); opacity: 0; } 7% { opacity: 1; } 84% { opacity: 1; }
  100% { transform: translate3d(var(--dx, 20px), calc(var(--rise, 92vh) * -1), 0); opacity: 0; } }

dialog.card { border: 0; max-width: 480px; width: calc(100% - 32px); padding: 36px 34px 30px; color: var(--ink); }
dialog.card[open] { animation: sheet .35s cubic-bezier(.2, .9, .3, 1); }
@keyframes sheet { from { opacity: 0; transform: translate3d(0, 26px, 0) scale(.97); } }
dialog::backdrop { background: rgba(10, 26, 74, .62); -webkit-backdrop-filter: blur(5px); backdrop-filter: blur(5px); }
dialog h2 { margin-bottom: 12px; font: 400 40px/1 var(--display); letter-spacing: .01em; }
dialog p { text-wrap: pretty; }
.field { display: grid; gap: 6px; margin-top: 18px; font: 700 11px/1.2 var(--plate); letter-spacing: .16em; text-transform: uppercase; color: var(--muted); }
.field input { font: 600 15px/1.3 var(--body); letter-spacing: 0; text-transform: none; color: var(--ink); }
.field__note { margin-top: 6px; font-size: 13px; color: var(--muted); }
dialog .now__moves { margin-top: 26px; gap: 10px; }

/* ---------------------------------------------------------------- things on the table */

.thing {
  position: absolute;
  left: 0;
  top: 0;
  width: calc(var(--s, 50) * var(--u));
  height: calc(var(--s, 50) * var(--u));
  transform: translate(calc(var(--x) * var(--u) - 50%), calc(var(--y) * var(--u) - 50%)) rotate(var(--r, 0deg));
  transition: transform 0.55s cubic-bezier(0.2, 0.75, 0.25, 1), width 0.4s ease, height 0.4s ease;
  z-index: 10;
}

/* the mat hangs in the night: its shadow falls away into the sky under it */
.mat {
  z-index: 1;
  border-radius: calc(var(--u) * 6);
  background: var(--felt) url('./parts/mat_felt_A_preview.png') center / 100% 100%;
  box-shadow: 0 calc(var(--u) * 0.6) calc(var(--u) * 1.2) rgba(var(--shade), 0.5), 0 calc(var(--u) * 6) calc(var(--u) * 14) calc(var(--u) * -3) rgba(var(--shade), 0.8), 0 0 calc(var(--u) * 26) rgba(var(--shade), 0.28);
}

/* A tile: white body, e-paper window, and on the back only the page button. */
.tile { border-radius: 8.4%; perspective: 900px; }
.tile__body { position: absolute; inset: 0; transform-style: preserve-3d; transform: rotateY(180deg); transition: transform 0.55s cubic-bezier(0.3, 0.7, 0.2, 1), translate 0.2s ease; }
.tile.is-up .tile__body { transform: rotateY(0deg); }
.tile__side {
  position: absolute;
  inset: 0;
  border-radius: 8.4%;
  background: var(--tile);
  backface-visibility: hidden;
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.05), 0 calc(var(--u) * 0.4) calc(var(--u) * 0.7) rgba(4, 6, 20, 0.42), 0 calc(var(--u) * 1.6) calc(var(--u) * 2.6) calc(var(--u) * -0.8) rgba(4, 6, 20, 0.6);
}
.tile__back { transform: rotateY(180deg); }
.tile[data-stack='1'] .tile__side { box-shadow: 0 calc(var(--u) * 1.3) 0 #dcd8ce, 0 calc(var(--u) * 2.6) calc(var(--u) * 3) rgba(4, 6, 20, 0.55); }
.tile[data-stack='2'] .tile__side { box-shadow: 0 calc(var(--u) * 1.3) 0 #dcd8ce, 0 calc(var(--u) * 2.6) 0 #cdc8bc, 0 calc(var(--u) * 4) calc(var(--u) * 3.4) rgba(4, 6, 20, 0.55); }
.tile[data-stack='3'] .tile__side { box-shadow: 0 calc(var(--u) * 1.3) 0 #dcd8ce, 0 calc(var(--u) * 2.6) 0 #cdc8bc, 0 calc(var(--u) * 3.9) 0 #bfb9ac, 0 calc(var(--u) * 5.4) calc(var(--u) * 3.8) rgba(4, 6, 20, 0.55); }
.tile__face { position: absolute; inset: 8%; border-radius: 4.8%; overflow: hidden; background: var(--panel-white); }
.tile__face > * { display: block; width: 100%; height: 100%; user-select: none; }
.tile__button { position: absolute; right: 6.8%; bottom: 6.8%; width: 22.4%; aspect-ratio: 1; border-radius: 50%; box-shadow: inset 0 0 0 1px #d8d5cd; }
.tile__button::after { content: ''; position: absolute; inset: 18.75%; border-radius: 50%; background: #f0eee9; box-shadow: inset 0 0 0 1px #dedbd3; }
.tile.is-standing { z-index: 11; }

/* A page change on a tile lying face up: e-paper flashes before the new picture settles. */
.tile__face.is-refreshing { animation: refresh 0.62s steps(1, end); }
@keyframes refresh {
  0% { filter: none; }
  18% { filter: invert(1); }
  40% { filter: brightness(0); }
  58% { filter: invert(1) contrast(0.6); }
  78% { filter: contrast(0.5) brightness(1.2); }
  100% { filter: none; }
}

/* What can be touched. A tile lifts under the finger; a picked tile stays lifted with a white ring on the felt. */
.is-target { cursor: pointer; }
.tile.is-target:hover .tile__body, .tile.is-target:focus-visible .tile__body, .tile.is-picked .tile__body { translate: 0 calc(var(--u) * -1.6); }
.tile.is-target:focus-visible, .tile.is-picked { outline: calc(var(--u) * 0.9) solid #fff; outline-offset: calc(var(--u) * 1); z-index: 30; }
.tile.is-target:hover { z-index: 30; }

/* Rows of a card that can be called, and the row that was. */
.tile__over { position: absolute; inset: 8%; pointer-events: none; }
.tile:not(.is-up) .tile__over { display: none; }
.tile__region, .tile__mark { position: absolute; border-radius: 3px; }
.tile__region { pointer-events: auto; border: 0; padding: 0; background: transparent; cursor: pointer; }
.tile__region:hover, .tile__region:focus-visible, .tile__mark { outline: 3px solid var(--mark); outline-offset: -1px; }
.tile__region:hover, .tile__region:focus-visible { background: rgba(23, 23, 26, 0.1); }
.tile__region:active { background: rgba(23, 23, 26, 0.22); }

/* Wooden pawns, seen from above. */
.pawn {
  z-index: 40;
  display: grid;
  place-items: center;
  border-radius: 50%;
  isolation: isolate;
  background: radial-gradient(circle at 36% 30%, color-mix(in srgb, var(--paint) 72%, #fff), var(--paint) 58%, color-mix(in srgb, var(--paint) 78%, #000));
  box-shadow: 0 calc(var(--u) * 0.7) calc(var(--u) * 0.9) rgba(0, 0, 0, 0.5), inset 0 0 0 calc(var(--u) * 0.3) rgba(0, 0, 0, 0.2);
}
.pawn img { width: 62%; height: 62%; mix-blend-mode: screen; }
.pawn--dark-ink img { filter: invert(1); mix-blend-mode: multiply; }
.pawn.is-target::after, .die.is-target::after {
  content: '';
  position: absolute;
  inset: -22%;
  border-radius: 50%;
  border: calc(var(--u) * 0.8) solid var(--cloud);
  animation: beckon 0.9s ease-in-out infinite alternate;
}
.pawn.is-target:hover, .pawn.is-target:focus-visible { scale: 1.15; outline: none; }
@keyframes beckon { from { opacity: 0.35; scale: 0.92; } to { opacity: 1; scale: 1.06; } }

/* The die, in its player's colour, and the box lid it is rolled in. */
.die {
  z-index: 40;
  display: grid;
  grid-template: repeat(3, 1fr) / repeat(3, 1fr);
  padding: calc(var(--s) * var(--u) * 0.13);
  border-radius: 20%;
  background: linear-gradient(145deg, color-mix(in srgb, var(--paint) 80%, #fff), var(--paint) 60%);
  box-shadow: 0 calc(var(--u) * 0.9) calc(var(--u) * 1.2) rgba(0, 0, 0, 0.55), inset 0 0 0 calc(var(--u) * 0.3) rgba(0, 0, 0, 0.15);
}
.die i { margin: 14%; border-radius: 50%; }
.die i.on { background: var(--ink); }
.die.is-target:focus-visible { outline: none; scale: 1.1; }
.die.is-rolling { animation: tumble 0.6s cubic-bezier(0.3, 0.6, 0.3, 1); }
@keyframes tumble {
  0% { rotate: -260deg; translate: calc(var(--u) * -16) calc(var(--u) * -5); }
  55% { rotate: 24deg; translate: calc(var(--u) * 2) 0; }
  100% { rotate: 0deg; translate: 0 0; }
}
.tray {
  z-index: 3;
  width: calc(var(--w) * var(--u));
  height: calc(var(--h) * var(--u));
  border: calc(var(--u) * 2.4) solid var(--cloud);
  border-radius: calc(var(--u) * 5);
  background: radial-gradient(circle at 40% 30%, #46474a, #303133);
  box-shadow: 0 calc(var(--u) * 1) calc(var(--u) * 2.4) rgba(var(--shade), 0.6), 0 calc(var(--u) * 4) calc(var(--u) * 8) calc(var(--u) * -3) rgba(var(--shade), 0.8), inset 0 calc(var(--u) * 1) calc(var(--u) * 2) rgba(0, 0, 0, 0.5);
}

/* A holder: the rail a hand of tiles stands in. */
.holder {
  z-index: 12;
  width: calc(var(--w) * var(--u));
  height: calc(var(--u) * 9);
  border-radius: calc(var(--u) * 3);
  background: linear-gradient(180deg, #8a6644, #5c4029);
  box-shadow: 0 calc(var(--u) * 0.8) calc(var(--u) * 1.6) rgba(var(--shade), 0.6), 0 calc(var(--u) * 3) calc(var(--u) * 6) calc(var(--u) * -2) rgba(var(--shade), 0.7), inset 0 calc(var(--u) * 0.5) 0 rgba(255, 255, 255, 0.2);
}

/* Words beside the table: whose side this is, and their score. */
.label {
  z-index: 45;
  width: auto;
  height: auto;
  display: flex;
  align-items: center;
  gap: 0.5em;
  padding: 0.2em 0.85em 0.2em 0.24em;
  border-radius: 999px;
  white-space: nowrap;
  pointer-events: none;
  background: rgba(6, 18, 60, 0.6);
  color: var(--cloud);
  font: 700 max(10.5px, calc(var(--u) * 5.6))/1.2 var(--plate);
  letter-spacing: 0.1em;
  text-transform: uppercase;
}
.label .chip { font-size: 0.86em; }
.label .chip[hidden] + span { margin-left: 0.6em; }
.label em { margin-right: -0.5em; padding: 0.2em 0.7em 0.14em; border-radius: 999px; background: var(--signal); color: #fff; font-style: normal; font-size: 0.82em; letter-spacing: 0.12em; }
.label em[hidden] { display: none; }

/* A closer look at a small tile. */
.loupe { position: absolute; left: 6px; bottom: 6px; z-index: 100; width: 210px; height: 210px; padding: 17px; border-radius: 18px; background: var(--tile); box-shadow: 0 4px 8px rgba(var(--shade), 0.4), 0 26px 44px -14px rgba(var(--shade), 0.9); pointer-events: none; }
.loupe > * { display: block; width: 100%; height: 100%; border-radius: 8px; }
.loupe[hidden] { display: none; }

/* People who ask for less motion get the table without slides, flips and flashes, and a still sky. */
@media (prefers-reduced-motion: reduce) {
  .thing, .tile__body, .box, .box__go, .cover-tile, .logo__card, .sky__night, .sky__stars, .sky__moon, .sky__cloud, .go, .quiet, .players li { transition: none; }
  .sky__cloud, .sky__stars--bright, .box__cloud, .cover-tile, .curtain__cloud, .curtain .card, .lantern, .lantern::before, .now.is-new, .players li.is-thinking .players__tally,
  .is-fresh :is(.shelf > *, .box, .setup > *, .side > *, .table__stage), dialog.card[open],
  .die.is-rolling, .tile__face.is-refreshing, .pawn.is-target::after, .die.is-target::after { animation: none; }
  .lantern { display: none; }
}

@media (max-width: 1100px) {
  .sky__moon { width: 260px; right: -96px; }
  .sky__cloud--a { --w: 520px; } .sky__cloud--b { --w: 420px; } .sky__cloud--c { --w: 420px; }
}
@media (max-width: 860px) {
  .top { padding: 10px 16px 8px; gap: 8px 14px; }
  .logo { font-size: 34px; }
  .top__crumbs { order: 3; flex-basis: 100%; font-size: 11px; letter-spacing: .12em; }
  .top > .quiet { margin-left: auto; font-size: 10.5px; letter-spacing: .1em; }
  .shelf { padding: 14px 16px 72px; }
  .shelf__games { grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 16px; }
  .setup { grid-template-columns: 1fr; padding: 8px 16px 56px; gap: 18px; }
  .rules { padding: 24px 22px 26px; }
  .play { grid-template-columns: 1fr; padding: 2px 12px 14px; gap: 12px; min-height: 0; }
  .play__table { height: min(100vw, 70vh); --rise: min(100vw, 70vh); }
  .side { grid-template-rows: auto auto; gap: 12px; }
  .side__book { max-height: 70vh; }
  .loupe { display: none; }
  .sky__moon { width: 190px; right: -70px; top: 70px; opacity: .92; }
  .sky__cloud--a { --w: 360px; left: -60px; } .sky__cloud--b { --w: 300px; left: 38%; } .sky__cloud--c { --w: 320px; right: -90px; }
  .sky__cloud--d { --w: 230px; --up: 110px; } .sky__cloud--e { display: none; }
}
@media (max-width: 640px) {
  .sky__moon { display: none; }                 /* on a narrow screen the words have the whole width, and the moon would sit behind them */
}
@media (max-width: 520px) {
  .top__tag { display: none; }
  .shelf__games { grid-template-columns: 1fr 1fr; gap: 12px; }
  .box { padding: 8px 8px 10px; border-radius: 20px; }
  .box__cover { border-radius: 13px; }
  .box h2 { margin: 12px 6px 0; font-size: 25px; }
  .box > p { margin: 5px 6px 0; font-size: 13.5px; line-height: 1.36; }
  .box > .box__meta { padding-top: 10px; min-height: 0; font-size: 9.5px; letter-spacing: .1em; }
  .box__go { display: none; }
  .setup__form { padding: 18px 6px 6px; }
}
