/*
 * Creator setup.
 *
 * One question per screen, a spring between them, and nothing else on the page.
 * The rules that matter are the timing curve and the stagger: everything here
 * moves on cubic-bezier(.32,.72,0,1), which is the curve a sheet uses when it
 * comes up on a phone. It starts fast, settles slowly, and never overshoots, so
 * a card that is only travelling 24px still reads as a physical object rather
 * than as a fade.
 *
 * Every animation runs *from* hidden to shown, so if motion is off, or the
 * stylesheet is still in flight, the page is a finished page and not an empty
 * one.
 */

:root {
  --on-ease: cubic-bezier(.32, .72, 0, 1);
  --on-ink: #f4f4f6;
  --on-dim: #9a9aa3;
  --on-line: #2a2a30;
  --on-card: #17171b;
  --on-accent: #b56cff;
  --on-go: #3fdc6f;
}

* { box-sizing: border-box; }

body {
  background:
    radial-gradient(120% 80% at 50% -10%, #1b1420 0%, transparent 60%),
    #0b0b0d;
  color: var(--on-ink);
  font: 400 17px/1.5 'Archivo', system-ui, -apple-system, 'Segoe UI', sans-serif;
  -webkit-font-smoothing: antialiased;
  min-height: 100svh;
}

.on {
  min-height: 100svh;
  display: grid;
  grid-template-rows: auto 1fr auto;
  padding: max(18px, env(safe-area-inset-top)) 20px max(22px, env(safe-area-inset-bottom));
  gap: 18px;
}

/* ---------------- top: mark, progress, back ---------------- */

.on-top {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 16px;
  max-width: 760px;
  width: 100%;
  margin: 0 auto;
}

.on-mark { height: 26px; width: auto; opacity: .9; justify-self: start; }

.on-rail { display: flex; gap: 6px; justify-self: center; }

.on-tick {
  width: 26px;
  height: 4px;
  border-radius: 999px;
  background: #2a2a30;
  transition: background .4s var(--on-ease), width .4s var(--on-ease);
}
.on-tick.is-done { background: #4a4a55; }
.on-tick.is-now { background: var(--on-accent); width: 42px; }

/* Author `display` beats the user agent's `[hidden] { display: none }`, so a
   button styled as a grid stays on screen after `hidden = true` silently does
   nothing. It showed on the last card, where there is nothing to go back to. */
.on-back[hidden] { display: none; }

.on-back {
  justify-self: end;
  display: grid;
  place-items: center;
  width: 38px;
  height: 38px;
  border-radius: 50%;
  color: var(--on-dim);
  background: transparent;
  border: 1px solid var(--on-line);
  cursor: pointer;
  transition: color .2s, border-color .2s, transform .2s var(--on-ease);
}
.on-back:hover { color: var(--on-ink); border-color: #3d3d46; }
.on-back:active { transform: scale(.94); }

/* ---------------- the stage ---------------- */

.on-stage {
  position: relative;
  display: grid;
  /*
   * minmax(0, 1fr), not auto.
   *
   * An implicit `auto` track sizes to its content's max-content, and the game
   * carousel's content is fifty tiles wide. The scroll container clips it
   * visually but still reports that width up the tree, so the track grew to
   * about ten thousand pixels and the card, dutifully centred in it, sat five
   * thousand pixels off the right of the screen. The page looked blank.
   *
   * It only showed up once the catalogue grew: with five games the overflow was
   * a couple of hundred pixels and the card merely sat slightly off centre.
   */
  grid-template-columns: minmax(0, 1fr);
  place-items: center;
  width: 100%;
}

.on-card {
  grid-area: 1 / 1;
  width: min(560px, 100%);
  display: flex;
  flex-direction: column;
  gap: 22px;
  text-align: center;
}

/*
 * The spring. Forward is a card arriving from the right while the last one
 * leaves to the left; back is the mirror. 24px of travel, not 100: a long slide
 * reads as a page transition, a short one reads as a card being dealt, and this
 * is a card being dealt.
 */
@media (prefers-reduced-motion: no-preference) {
  .on-card.is-in  { animation: on-in .42s var(--on-ease) both; }
  .on-card.is-out { animation: on-out .3s var(--on-ease) both; }
  .on-card.back.is-in  { animation-name: on-in-back; }
  .on-card.back.is-out { animation-name: on-out-back; }

  /* Children arrive after the card, 45ms apart, so the eye is led down it
     instead of being handed the whole screen at once. */
  .on-card.is-in > * { animation: on-rise .44s var(--on-ease) both; }
  .on-card.is-in > *:nth-child(1) { animation-delay: .06s; }
  .on-card.is-in > *:nth-child(2) { animation-delay: .105s; }
  .on-card.is-in > *:nth-child(3) { animation-delay: .15s; }
  .on-card.is-in > *:nth-child(4) { animation-delay: .195s; }
  .on-card.is-in > *:nth-child(5) { animation-delay: .24s; }
}

@keyframes on-in       { from { opacity: 0; transform: translateX(24px)  scale(.985); } }
@keyframes on-in-back  { from { opacity: 0; transform: translateX(-24px) scale(.985); } }
@keyframes on-out      { to   { opacity: 0; transform: translateX(-18px) scale(.985); } }
@keyframes on-out-back { to   { opacity: 0; transform: translateX(18px)  scale(.985); } }
@keyframes on-rise     { from { opacity: 0; transform: translateY(10px); } }

/* ---------------- type ---------------- */

.on-kicker {
  margin: 0;
  font-size: 13px;
  font-weight: 800;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--on-accent);
}

.on-title {
  margin: 0;
  font-size: clamp(30px, 6vw, 40px);
  font-weight: 800;
  line-height: 1.12;
  letter-spacing: -.02em;
}

.on-sub { margin: 0; font-size: 17px; line-height: 1.45; color: var(--on-dim); }

/* ---------------- controls ---------------- */

.on-field {
  width: 100%;
  padding: 17px 20px;
  font: inherit;
  font-size: 19px;
  color: var(--on-ink);
  text-align: center;
  background: var(--on-card);
  border: 1px solid var(--on-line);
  border-radius: 16px;
  transition: border-color .2s, background .2s;
}
.on-field::placeholder { color: #5f5f68; }
.on-field:focus { outline: none; border-color: var(--on-accent); background: #1c1c21; }

/* A grid of choices. One tap, no confirm: choosing is the same gesture as
   continuing, which is what removes a whole click from every screen. */
.on-picks { display: grid; gap: 12px; }
.on-picks.two { grid-template-columns: 1fr 1fr; }

.on-pick {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 7px;
  padding: 20px;
  text-align: left;
  font: inherit;
  color: var(--on-ink);
  background: var(--on-card);
  border: 1px solid var(--on-line);
  border-radius: 18px;
  cursor: pointer;
  transition: transform .22s var(--on-ease), border-color .22s, background .22s;
}
.on-pick:hover { border-color: #3d3d46; background: #1c1c21; }
.on-pick:active { transform: scale(.985); }
.on-pick.is-on { border-color: var(--on-accent); background: rgba(181, 108, 255, .1); }
.on-pick.is-on::after {
  content: "";
  position: absolute;
  top: 16px; right: 16px;
  width: 9px; height: 9px;
  border-radius: 50%;
  background: var(--on-accent);
}

.on-pick b { font-size: 19px; font-weight: 700; }
.on-pick span { font-size: 15px; line-height: 1.4; color: var(--on-dim); }
.on-pick em { font-style: normal; font-size: 12px; font-weight: 800; letter-spacing: .12em; text-transform: uppercase; color: var(--on-go); }
.on-pick em.wait { color: #ffd66e; }

.on-chips { display: flex; flex-wrap: wrap; gap: 10px; justify-content: center; }
.on-chip {
  padding: 12px 18px;
  font: inherit;
  font-size: 16px;
  font-weight: 600;
  color: var(--on-ink);
  background: var(--on-card);
  border: 1px solid var(--on-line);
  border-radius: 999px;
  cursor: pointer;
  transition: transform .22s var(--on-ease), border-color .22s, background .22s;
}
.on-chip:hover { border-color: #3d3d46; }
.on-chip:active { transform: scale(.96); }
.on-chip.is-on { border-color: var(--on-accent); background: rgba(181, 108, 255, .14); }

/* ---------------- the game picker ---------------- */

.on-pickers { display: flex; flex-direction: column; gap: 12px; }

.on-tabs { display: flex; gap: 8px; justify-content: center; flex-wrap: wrap; }

.on-tab {
  padding: 9px 16px;
  font: inherit;
  font-size: 14px;
  font-weight: 700;
  color: var(--on-dim);
  background: transparent;
  border: 1px solid var(--on-line);
  border-radius: 999px;
  cursor: pointer;
  transition: color .2s, border-color .2s, background .2s;
}
.on-tab:hover { color: var(--on-ink); }
.on-tab.is-on { color: var(--on-ink); border-color: var(--on-accent); background: rgba(181, 108, 255, .14); }

.on-search {
  width: 100%;
  padding: 13px 16px;
  font: inherit;
  font-size: 16px;
  color: var(--on-ink);
  background: var(--on-card);
  border: 1px solid var(--on-line);
  border-radius: 14px;
}
.on-search::placeholder { color: #5f5f68; }
.on-search:focus { outline: none; border-color: var(--on-accent); }

/*
 * A carousel, not a grid. The catalogue is fifty titles and growing, and a grid
 * that reflows keeps changing how tall this screen is. Sideways keeps the step
 * one screen high however long the list gets.
 *
 * Arrows sit over the ends rather than beside them, so the artwork keeps the
 * full width. They hide themselves when there is nothing further that way.
 */
/*
 * Full bleed, deliberately. Everything else on this flow lives in a 560px
 * column, and a carousel inside that column shows three tiles. Breaking out to
 * the viewport width shows eight or nine without shrinking any of them, which
 * is the whole point of a carousel.
 */
.on-carousel {
  position: relative;
  width: 100vw;
  margin-left: calc(50% - 50vw);
  min-width: 0;
  /* The stage clips at its own bounds otherwise, and the tiles turned towards
     the middle are exactly the ones that would get cut. */
  overflow: visible;
}

.on-shelf {
  display: flex;
  gap: 14px;
  overflow-x: auto;
  /*
   * No scroll-snap. It fought the arrows twice: it parks the resting position
   * at the padding rather than zero, and it hijacked the tween mid flight,
   * moving thirteen pixels and stopping. The arrows page explicitly and the
   * tween is ours, so there is nothing for snapping to add.
   */
  /*
   * Room for the arc. The outer tiles sit up to 78px lower than the middle
   * one, so without the bottom padding the curve is simply cut off, and
   * without the top padding the centre tile's shadow is.
   */
  padding: 22px max(20px, calc(50vw - 460px)) 178px;
  min-width: 0;
  scrollbar-width: none;
}
.on-shelf::-webkit-scrollbar { display: none; }

.on-arrow {
  position: absolute;
  top: 150px;
  z-index: 2;
  width: 40px;
  height: 40px;
  display: grid;
  place-items: center;
  font: inherit;
  font-size: 26px;
  line-height: 1;
  color: var(--on-ink);
  background: rgba(10, 10, 12, .82);
  border: 1px solid var(--on-line);
  border-radius: 50%;
  cursor: pointer;
  backdrop-filter: blur(6px);
  transition: transform .2s var(--on-ease), border-color .2s;
}
.on-arrow:hover { border-color: var(--on-accent); }
.on-arrow:active { transform: scale(.92); }
.on-arrow[hidden] { display: none; }
.on-arrow.prev { left: 16px; }
.on-arrow.next { right: 16px; }

.on-game {
  flex: 0 0 auto;
  width: 208px;
  will-change: transform, opacity;
  transition: opacity .25s linear;
  /* The arc is written inline every frame; the origin is what makes a tile
     pivot on its own base rather than swinging from its centre. */
  transform-origin: 50% 80%;
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 0;
  font: inherit;
  text-align: left;
  color: var(--on-ink);
  background: none;
  border: 0;
  cursor: pointer;
}

.on-art {
  width: 208px;
  height: 277px;          /* 3:4, the shape a game cover is */
  border-radius: 16px;
  background: #17171b center / cover no-repeat;
  border: 2px solid transparent;
  /* The drop shadow is what sells the depth: without it a rotated tile reads
     as a skewed picture rather than as a card standing in space. */
  box-shadow: 0 0 0 1px var(--on-line) inset, 0 18px 34px rgba(0, 0, 0, .55);
  transition: transform .22s var(--on-ease), border-color .22s;
}
/* No hover transform: the depth pass owns this property and writes it
   every frame, so the two would take turns. The border does the work. */
.on-game:hover .on-art { border-color: #3d3d46; }
.on-game.is-on .on-art { border-color: var(--on-accent); }

/* Drawn from the slug, because we license none of this artwork. */
.on-art.is-drawn { display: grid; place-items: end center; padding: 18px; }
/* Set on the art, not over it: the tile is the picture and the name is part of
   the composition rather than a label stuck on afterwards. */
.on-art.is-drawn span {
  font-size: 21px;
  font-weight: 800;
  line-height: 1.2;
  letter-spacing: -.01em;
  color: #fff;
  text-align: center;
  text-wrap: balance;
  text-shadow: 0 2px 14px rgba(0, 0, 0, .75);
}

.on-game b { font-size: 15px; font-weight: 700; line-height: 1.25; }
.on-game.is-on b { color: var(--on-accent); }
.on-studio { font-size: 12.5px; color: #6f6f78; line-height: 1.3; }

/* ---------------- whose money ---------------- */

.on-providers {
  border-top: 1px solid var(--on-line);
  padding-top: 18px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.on-providers[hidden] { display: none; }

.on-ask { margin: 0; font-size: 17px; font-weight: 700; }

.on-provider-row { display: flex; flex-wrap: wrap; gap: 9px; justify-content: center; }

.on-provider {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 10px 15px;
  font: inherit;
  color: var(--on-ink);
  background: var(--on-card);
  border: 1px solid var(--on-line);
  border-radius: 12px;
  cursor: pointer;
  transition: border-color .2s, background .2s, transform .2s var(--on-ease);
}
.on-provider:hover { border-color: #3d3d46; }
.on-provider:active { transform: scale(.97); }
.on-provider.is-on { border-color: var(--on-accent); background: rgba(181, 108, 255, .14); }
.on-provider b { font-size: 15px; font-weight: 600; }
.on-provider em {
  font-style: normal;
  font-size: 10.5px;
  font-weight: 800;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--on-go);
}

.on-fine { margin: 0; font-size: 12.5px; line-height: 1.45; color: #6f6f78; }

.on-empty { margin: 22px auto; font-size: 15px; color: var(--on-dim); }

.on-go {
  width: 100%;
  padding: 17px 22px;
  font: inherit;
  font-size: 18px;
  font-weight: 700;
  color: #0b0b0d;
  background: var(--on-ink);
  border: 0;
  border-radius: 999px;
  cursor: pointer;
  transition: transform .22s var(--on-ease), opacity .22s;
}
.on-go:hover { opacity: .92; }
.on-go:active { transform: scale(.975); }
.on-go[disabled] { opacity: .35; cursor: not-allowed; }
.on-go.green { background: var(--on-go); }

.on-skip {
  font: inherit;
  font-size: 15px;
  color: var(--on-dim);
  background: none;
  border: 0;
  cursor: pointer;
  padding: 6px;
}
.on-skip:hover { color: var(--on-ink); }

.on-note {
  margin: 0;
  font-size: 14px;
  line-height: 1.45;
  color: #7e7e88;
  padding: 14px 16px;
  border: 1px solid var(--on-line);
  border-radius: 14px;
  text-align: left;
}

.on-crumb {
  margin: 0;
  text-align: center;
  font-size: 13px;
  color: #5f5f68;
  min-height: 1.2em;
}

/* The last screen, where the tick lands before the button does. */
.on-seal {
  width: 74px;
  height: 74px;
  margin: 0 auto;
  border-radius: 50%;
  display: grid;
  place-items: center;
  background: rgba(63, 220, 111, .14);
  border: 1px solid rgba(63, 220, 111, .5);
  color: var(--on-go);
}
@media (prefers-reduced-motion: no-preference) {
  .is-in .on-seal { animation: on-pop .5s var(--on-ease) both .1s; }
}
@keyframes on-pop { from { opacity: 0; transform: scale(.7); } }

@media (max-width: 560px) {
  .on-picks.two { grid-template-columns: 1fr; }
  .on-card { gap: 18px; }
}
