/* The Odd Stair: a spotlight on a dark stage. The stairs sit in the one lit pool; the rest falls away. */

@property --spot-x {
  syntax: '<length>';
  inherits: false;
  initial-value: 0px;
}

@property --spot-y {
  syntax: '<length>';
  inherits: false;
  initial-value: 0px;
}

@property --spot-r {
  syntax: '<length>';
  inherits: false;
  initial-value: 0px;
}

*,
*::before,
*::after {
  box-sizing: border-box;
}

html,
body {
  height: 100%;
  margin: 0;
}

body {
  overflow: hidden;
  background-color: var(--ak-bg);
  /* The painted stage under a flat wash: quiet enough that the grid and the one accent carry it. */
  background-image:
    linear-gradient(color-mix(in srgb, var(--ak-bg) 72%, transparent), color-mix(in srgb, var(--ak-bg) 72%, transparent)),
    var(--ak-backdrop-layer, var(--ak-bg-art));
  background-position: center top;
  background-size: cover;
  color: var(--ak-ink);
  font-family: var(--ak-font-body);
  -webkit-tap-highlight-color: transparent;
}

[hidden] {
  display: none !important;
}

.sr {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* ---- The stage: logo, board, bench. Upright the board sits over the bench. ---- */

.stage {
  --logo-h: 34px;
  --toast-room: 68px;
  --bench-min: 150px;
  --edge-b: max(12px, env(safe-area-inset-bottom));
  /* Upright the grid runs edge to edge; only the height can hold it back. */
  --board: min(
    calc(100dvw - env(safe-area-inset-left) - env(safe-area-inset-right)),
    calc(100dvh - var(--ac-status-h, 60px) - 4px - var(--logo-h) - 16px - var(--bench-min) - var(--toast-room) - var(--edge-b)),
    560px
  );
  position: fixed;
  inset: 0;
  z-index: 0;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  grid-template-rows: var(--logo-h) var(--board) minmax(0, 1fr);
  grid-template-areas: "logo" "board" "bench";
  justify-items: center;
  row-gap: 8px;
  padding:
    calc(var(--ac-status-h, 60px) + 4px)
    env(safe-area-inset-right)
    var(--edge-b)
    env(safe-area-inset-left);
  touch-action: manipulation;
}

/* Nothing of the play screen shows until the game starts: the opening screen is the first thing seen. */
.stage:not(.is-live) {
  visibility: hidden;
}

.logo {
  grid-area: logo;
  position: relative;
  z-index: 1;
  height: var(--logo-h);
  width: auto;
  max-width: 100%;
  object-fit: contain;
  user-select: none;
  -webkit-user-drag: none;
}

.board-wrap {
  grid-area: board;
  position: relative;
  z-index: 1;
  width: var(--board);
  height: var(--board);
}

/* Exact cells, one-pixel grey lines between them. */
.board {
  display: grid;
  grid-template-columns: repeat(var(--n, 3), minmax(0, 1fr));
  grid-template-rows: repeat(var(--n, 3), minmax(0, 1fr));
  gap: 1px;
  width: 100%;
  height: 100%;
  border: 1px solid var(--ak-ink-muted);
  background: var(--ak-ink-muted);
}

.tile {
  position: relative;
  display: block;
  min-width: 44px;
  min-height: 44px;
  margin: 0;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: var(--ak-btn-fill);
  color: var(--ak-btn-ink);
  cursor: pointer;
  touch-action: manipulation;
  -webkit-appearance: none;
  appearance: none;
}

.tile svg {
  display: block;
  width: 100%;
  height: 100%;
  pointer-events: none;
}

.tile:focus-visible {
  z-index: 1;
  outline: 3px solid var(--ak-focus);
  outline-offset: -3px;
}

.board.is-locked .tile {
  cursor: default;
}

/* Rings sit in the cell's margin, never on the stair. Solid is your tap, dashed is its partner. */
.tile::after {
  content: '';
  position: absolute;
  inset: 4px;
  border: 0 solid var(--ak-btn-ink);
  pointer-events: none;
}

.tile.is-tapped::after {
  border-width: 2px;
}

.tile.is-partner::after,
.tile.is-example::after {
  border-width: 2px;
  border-style: dashed;
}

.tile.is-found::after {
  inset: 3px;
  border-width: 3px;
  border-style: solid;
  border-color: var(--ak-accent);
}

.tile.is-ruled svg {
  opacity: 0.38;
}

.tile-count {
  position: absolute;
  top: 9px;
  left: 11px;
  color: var(--ak-btn-ink);
  font: 700 14px/1 var(--ak-font-body);
  letter-spacing: 0.08em;
  pointer-events: none;
}

.tile.is-flipped .tile.is-ruled svg {
  opacity: 0.38;
}

.tile-count {
  right: 11px;
  left: auto;
}

/* Stair pieces, on the board and on the bench. */
.st-bg {
  fill: var(--ak-btn-fill);
}

.st-floor {
  stroke: var(--ak-ink-muted);
  stroke-width: 1;
  vector-effect: non-scaling-stroke;
}

.st-body {
  fill: var(--ak-btn-ink);
}

.st-riser {
  stroke: var(--ak-btn-fill);
  stroke-width: 1.25;
  vector-effect: non-scaling-stroke;
}

.st-ring {
  fill: none;
  stroke: var(--ak-btn-ink);
  stroke-width: 2;
  vector-effect: non-scaling-stroke;
}

.st-ring.is-dashed {
  stroke-dasharray: 6 4;
}

.st-num {
  fill: var(--ak-btn-fill);
  font-family: var(--ak-font-body);
  font-weight: 600;
  text-anchor: middle;
  opacity: 0;
}

.st-num.on {
  opacity: 1;
}

.st-num.is-ghost {
  fill: var(--ak-btn-ink);
}

.st-mark {
  fill: var(--ak-accent);
  opacity: 0;
}

.st-notch {
  fill: var(--ak-btn-fill);
  opacity: 0;
}

.st-ghost {
  fill: none;
  stroke: var(--ak-accent);
  stroke-width: 2;
  stroke-dasharray: 5 3;
  vector-effect: non-scaling-stroke;
  opacity: 0;
}

.st-notch.is-ghost {
  fill: var(--ak-accent);
}

.st-mark.on,
.st-notch.on,
.st-ghost.on {
  opacity: 1;
}

/* ---- The light. Corners and chrome fall into shadow; the pool sits on what you can act on. ---- */

.spot {
  position: fixed;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  background: radial-gradient(
    circle var(--spot-r) at var(--spot-x) var(--spot-y),
    transparent 0,
    transparent 60%,
    color-mix(in srgb, var(--ak-ink) 45%, transparent) 100%
  );
}

.stage:not(.is-focus) .spot,
.stage.is-lit .spot {
  opacity: 0;
}

/* ---- The bench: two stairs counted side by side, and one calm line. ---- */

.bench {
  grid-area: bench;
  position: relative;
  z-index: 3;
  display: flex;
  flex-direction: column;
  justify-content: safe center;
  gap: 10px;
  width: min(calc(100% - 24px), 520px);
  min-height: 0;
  overflow: hidden;
  padding: 4px 0 var(--toast-room);
}

.bench.is-quiet {
  padding-bottom: 0;
}

.caption:empty {
  display: none;
}

/* The climb so far: ten steps rising, one per level. Solid is found on the first tap, outlined is
   found after a guess, dashed is the level in play. Each found step carries its odd count. */
.track {
  display: grid;
  flex: none;
  grid-template-columns: repeat(10, minmax(0, 1fr));
  align-items: end;
  gap: 3px;
  height: 44px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.track li {
  display: flex;
  justify-content: center;
  height: calc(45% + var(--i, 0) * 6.1%);
  padding-top: 3px;
  border: 1px solid var(--ak-ink-muted);
  background: var(--ak-bg);
  color: var(--ak-ink);
  font: 800 12px/1 var(--ak-font-display);
}

.track li.is-clean {
  border-color: var(--ak-btn-fill);
  background: var(--ak-btn-fill);
  color: var(--ak-btn-ink);
}

.track li.is-guessed {
  border: 2px solid var(--ak-ink);
}

.track li.is-current {
  border: 2px dashed var(--ak-ink);
}

.stage.is-ending .track {
  display: none;
}

.pair {
  display: grid;
  flex: 1 1 auto;
  grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
  align-items: center;
  gap: 10px;
  min-height: 0;
  max-height: 300px;
}

.fig {
  align-self: stretch;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  min-height: 0;
  margin: 0;
}

.fig-art {
  flex: 1 1 auto;
  width: 100%;
  min-height: 0;
  overflow: hidden;
}

.fig-art svg {
  display: block;
  width: 100%;
  height: 100%;
}

.fig-label {
  display: inline-flex;
  align-items: baseline;
  gap: 10px;
  padding: 3px 10px;
  background: var(--ak-bg);
  color: var(--ak-ink);
  font-size: 14px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}

.fig-count {
  min-width: 1.2em;
  font: 800 22px/1 var(--ak-font-display);
  letter-spacing: 0;
  text-align: right;
}

.caption {
  margin: 0;
  padding: 12px 16px;
  border-top: 1px solid var(--ak-ink);
  background: var(--ak-bg);
  color: var(--ak-ink);
  font: 500 clamp(18px, 1vw + 14px, 24px)/1.35 var(--ak-font-body);
}

.caption strong {
  font-weight: 700;
}

.got-it {
  min-height: 56px;
  padding: 0 24px;
  border: 0;
  border-radius: 2px;
  background: var(--ak-btn-fill);
  color: var(--ak-btn-ink);
  font: 800 20px/1 var(--ak-font-display);
  letter-spacing: 0.06em;
  cursor: pointer;
  touch-action: manipulation;
}

.got-it:active {
  background: var(--ak-btn-active);
}

.got-it:focus-visible,
.advance:focus-visible {
  outline: 3px solid var(--ak-focus);
  outline-offset: 3px;
}

.advance {
  position: fixed;
  inset: 0;
  z-index: 20;
  margin: 0;
  padding: 0;
  border: 0;
  background: transparent;
  cursor: pointer;
  touch-action: manipulation;
}

.advance:focus-visible {
  outline-offset: -6px;
}

/* ---- The ending: the house lights come up on the ten odd stairs. ---- */

.gallery {
  grid-area: gallery;
  position: relative;
  z-index: 3;
  align-self: end;
  width: min(100%, 400px);
}

.gallery-row {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  column-gap: 0;
  row-gap: 12px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.gallery-row.is-apart {
  column-gap: clamp(7px, 2vw, 14px);
}

.gallery-row li {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  min-width: 0;
}

.gallery-row svg {
  display: block;
  width: 100%;
  aspect-ratio: 1;
}

.gallery-count {
  padding: 0 6px;
  background: var(--ak-bg);
  color: var(--ak-ink);
  font: 800 16px/1.2 var(--ak-font-display);
}

.gallery-row li.is-clean .gallery-count {
  background: var(--ak-btn-fill);
  color: var(--ak-btn-ink);
}

.gallery-row li.is-guessed .gallery-count {
  outline: 2px solid var(--ak-ink);
  outline-offset: -2px;
}

.climber {
  position: absolute;
  top: 0;
  left: 0;
  z-index: 1;
  clip-path: circle(30% at 50% 50%);
  pointer-events: none;
  user-select: none;
}

/* The site's ending chips land at the bottom, so the stairs and the reason sit above them. */
.stage.is-ending {
  grid-template-rows: var(--logo-h) auto auto minmax(0, 1fr);
  grid-template-areas: "logo" "gallery" "bench" ".";
}

.stage.is-ending .gallery {
  align-self: start;
  width: min(calc(100% - 24px), 400px, calc((100dvh - var(--ac-status-h, 60px) - 470px) * 2.5));
}

.stage.is-ending .board-wrap,
.stage.is-ending .pair {
  display: none;
}

.stage.is-ending .bench {
  justify-content: flex-start;
  padding-bottom: 0;
}

.fig-name {
  white-space: nowrap;
}

/* The pair takes whatever height the bench has left; too little for a readable stair, and only
   the labels and the sign stay. */
.pair {
  container-type: size;
}

@container (max-height: 110px) {
  .fig-art {
    display: none;
  }
}

/* On the narrowest phones the labels tighten so each stays on one line. */
@media (max-width: 380px) {
  .fig-label {
    gap: 6px;
    padding: 3px 8px;
    letter-spacing: 0.08em;
  }
}

/* = when the two counts match, ≠ beside the odd one: the comparison in one mark. */
.pair-sign {
  display: grid;
  place-items: center;
  min-width: 40px;
  height: 40px;
  padding: 0 6px;
  background: var(--ak-bg);
  color: var(--ak-ink);
  font: 800 28px/1 var(--ak-font-display);
}

/* ---- Sideways: the board on one side; the words first, then the counted pair, on the other. ---- */

@media (orientation: landscape) {
  .stage {
    --logo-h: 40px;
    --toast-room: 56px;
    /* A one-line toast sits at the bottom centre and may reach the board's corner. */
    --toast-low: 52px;
    --board: min(
      calc(100dvh - var(--ac-status-h, 60px) - 4px - var(--toast-low) - var(--edge-b)),
      54dvw,
      720px
    );
    grid-template-columns: var(--board) minmax(0, 460px);
    grid-template-rows: minmax(0, 1fr);
    grid-template-areas: "board bench";
    /* The board sits under the status chips and the bench hugs its side, so they read as one block. */
    justify-content: start;
    justify-items: start;
    column-gap: 16px;
    padding-left: max(12px, env(safe-area-inset-left));
    padding-right: max(12px, env(safe-area-inset-right));
  }

  /* Sideways there is width to spare, so the corner chips read a size up. */
  html #activity-chrome-status.site-expercepth,
  html #activity-chrome-toast.site-expercepth {
    font-size: 14px;
    letter-spacing: 0.18em;
  }

  /* The logo moves up into the free space between the status chips and the help button. */
  .logo {
    position: absolute;
    top: max(12px, env(safe-area-inset-top));
    left: 50%;
    translate: -50% 0;
  }

  .board-wrap {
    align-self: start;
  }

  .bench {
    align-self: start;
    justify-content: flex-start;
    gap: 10px;
    width: 100%;
    height: var(--board);
    padding: 0;
  }

  .track {
    order: -1;
  }

  .caption {
    order: 0;
    padding: 10px 16px;
    font-size: clamp(20px, 1.2vw + 10px, 26px);
  }

  .got-it {
    order: 1;
  }

  .pair {
    order: 2;
  }

  /* Sideways the ending chips take the bottom left: the reason sits above them, the stairs to the right. */
  .stage.is-ending {
    grid-template-columns: minmax(0, 1fr) minmax(0, 320px);
    grid-template-rows: minmax(0, 1fr);
    grid-template-areas: "bench gallery";
  }

  .stage.is-ending .gallery {
    width: min(100%, 280px, calc((100dvh - var(--ac-status-h, 60px) - 140px) * 1.9));
  }

  .stage.is-ending .bench {
    align-self: start;
  }
}

/* A wide screen has room for a bigger row of stairs beside the ending chips. */
@media (orientation: landscape) and (min-width: 1000px) {
  .stage {
    --logo-h: 56px;
  }

  .stage.is-ending {
    grid-template-columns: minmax(0, 1fr) minmax(0, 460px);
  }

  .stage.is-ending .gallery {
    width: min(100%, 440px, calc((100dvh - var(--ac-status-h, 60px) - 140px) * 1.9));
  }
}

/* ---- Motion: slow light, pieces that settle. Only when motion is welcome. ---- */

@media (prefers-reduced-motion: no-preference) {
  :root:not(.ac-still) .spot {
    transition:
      --spot-x 1.1s ease-in-out,
      --spot-y 1.1s ease-in-out,
      --spot-r 1.1s ease-in-out,
      opacity 2.4s ease-in-out;
  }

  :root:not(.ac-still) .board.is-fresh {
    animation: fade-in 700ms ease-out both;
  }

  :root:not(.ac-still) .st-num.on {
    animation: fade-in 200ms ease-out both;
  }

  :root:not(.ac-still) .st-mark.on,
  :root:not(.ac-still) .st-notch.on,
  :root:not(.ac-still) .st-ghost.on {
    animation: settle 560ms cubic-bezier(0.34, 1.4, 0.64, 1) both;
    transform-box: fill-box;
    transform-origin: center bottom;
  }

  :root:not(.ac-still) .fig.is-twin {
    animation: fade-in 700ms 250ms ease-out both;
  }

  :root:not(.ac-still) .tile.is-found::after {
    animation: fade-in 600ms ease-out both;
  }

  :root:not(.ac-still) .gallery-row {
    transition: column-gap 1.4s ease-in-out;
  }

  :root:not(.ac-still) .gallery-row li {
    animation: settle 620ms cubic-bezier(0.34, 1.3, 0.64, 1) both;
    animation-delay: calc(var(--i, 0) * 90ms);
  }

  @keyframes fade-in {
    from {
      opacity: 0;
    }
  }

  @keyframes settle {
    from {
      opacity: 0;
      transform: translateY(-14px);
    }
  }
}
