/* ============================================================
   AIS GAMES — web player page (play.html)
   Page head with the game's name, the player card (frame + cover +
   toolbar), two info cards and a grid of more games.
   Requires: tokens.css, main.css — every value here is a token.
   ============================================================ */

/* ---------- Page head ---------- */
.play-head { padding-bottom: var(--sp-5); }
.back-link {
  display: inline-block;
  margin-bottom: var(--sp-5);
}
.play-head .card-eyebrow {
  margin-bottom: var(--sp-4);
  /* The same pill as on the artwork cards; only its backdrop follows the
     theme, since here it sits on the bare page (the art scrim is black and
     vanished on the dark theme). */
  background: var(--scrim-page);
}

/* ---------- Player card ---------- */
.player.container-wide { width: var(--w-cards); }

.player-shell {
  background: var(--surface);
  border-radius: var(--radius-lg);
  overflow: hidden;
}

/* Black screen band spanning the whole card; the game scales itself
   inside. Portrait games get a taller band. */
.player-screen { background: var(--player-bg); }
.player-stage {
  position: relative;
  width: 100%;
  height: var(--h-player);
  background: var(--player-bg);
}
.player-stage.is-portrait { height: var(--h-player-tall); }
.player-stage:fullscreen {
  width: 100%;
  height: 100%;
}
/* The fallback where the Fullscreen API does not reach (iPhone Safari): the
   stage is lifted out of the page and pinned over everything. */
.player-stage.is-pseudo-full {
  position: fixed;
  inset: 0;
  z-index: var(--z-player-full);
  width: 100%;
  height: 100%;
  height: 100dvh;
}
.player-locked,
.player-locked body { overflow: hidden; }
/* The frame fills the stage. When the stage is smaller than the game was laid
   out for, js/play.js gives the frame the game's own minimum size and scales
   it down to the stage, so the whole game shows instead of the part of it
   that fits. */
.player-stage iframe {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
  background: var(--player-bg);
  transform-origin: 0 0;
}
/* The fallback fullscreen has no system way out, so it gets a strip of its
   own above the game — above, not over: every game keeps buttons in its top
   corners, and a close button laid on them would be pressed by mistake. The
   real fullscreen leaves through the system (back gesture, Escape). */
.player-stage.is-pseudo-full iframe {
  top: calc(var(--tap) + var(--safe-top));
  height: calc(100% - var(--tap) - var(--safe-top));
}
.player-exit {
  position: absolute;
  top: var(--safe-top);
  right: var(--safe-right);
  z-index: var(--z-caption);
  color: var(--ink-on-art);
  background: transparent;
}

/* Cover: the game's art, its icon and one big play button */
.player-cover {
  position: absolute;
  inset: 0;
  display: grid;
  place-content: center;
  gap: var(--sp-4);
  text-align: center;
  padding: var(--sp-5);
  background: var(--grad-stat-dark);
  color: var(--ink-on-art);
}
.player-cover-art {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.player-cover::before {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--scrim-soft);
  z-index: 1;
}
.player-cover > * { position: relative; z-index: 1; }
.player-cover > .player-cover-art { z-index: 0; }
.player-cover-icon {
  width: var(--icon-cover);
  margin-inline: auto;
  border-radius: var(--radius-icon);
  box-shadow: var(--shadow-pop);
}
.player-hint {
  color: var(--ink-on-art-soft);
  font-size: var(--text-sm);
}
.btn-lg {
  font-size: var(--text-nav);
  padding: var(--sp-4) var(--btn-pad-x-lg);
}
/* While the game is missing from the server the cover stays, without the button */
.player-cover.is-unavailable .btn { display: none; }

/* Toolbar under the frame */
.player-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-4);
  flex-wrap: wrap;
  padding: var(--sp-4) var(--sp-5);
}
.player-meta {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  min-width: 0;
}
.player-meta img {
  width: var(--tap);
  border-radius: var(--radius-icon);
  flex-shrink: 0;
}
.player-meta strong {
  display: block;
  font-size: var(--text-md);
  line-height: var(--lh-snug);
}
.player-meta span {
  color: var(--ink-dim);
  font-size: var(--text-sm);
}
.player-actions {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
}
/* Round icon buttons come from main.css (.icon-btn) */
/* Like / dislike carry their count: the round button widens into a pill. */
.vote-btn:has(.vote-count:not([hidden])) {
  width: auto;
  gap: var(--sp-2);
  padding-inline: var(--sp-3);
}
.vote-count {
  font-size: var(--text-sm);
  font-weight: var(--w-sub);
  font-variant-numeric: tabular-nums;
}

/* "How to play" slides open under the toolbar (js/play.js). The padding sits
   on an inner box so the panel itself can fold all the way to nothing. */
.player-controls { border-top: var(--border-thin) solid var(--line); }
.player-controls-body { padding: var(--sp-4) var(--sp-5) var(--sp-5); }
.player-controls h2 {
  font-size: var(--text-md);
  margin-bottom: var(--sp-2);
}

/* ---------- Reel: this game's trailer + screenshots ----------
   Sideways strip of portrait cards (store-listing style) with snap
   scrolling, arrow buttons and an inline video. Sits right under the
   player, before the description, like a store listing. */
.reel { padding-block: var(--section-pad) 0; }
.reel-head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--sp-5);
  width: var(--w-cards);
  margin: 0 auto var(--sp-5);
}
.reel-head h2 {
  font-size: var(--text-h2);
  font-stretch: var(--stretch-display);
  letter-spacing: var(--tracking-display);
}
.reel-sub {
  margin-top: var(--sp-2);
  color: var(--ink-dim);
  font-weight: var(--w-ui);
}
.reel-nav {
  display: flex;
  gap: var(--sp-2);
  flex-shrink: 0;
}
.reel-prev svg { transform: scaleX(-1); }

/* Full-bleed track whose padding lines the first card up with the card sections */
.reel-track {
  display: flex;
  gap: var(--gap-cards);
  padding-inline: max(var(--gutter), (100% - var(--w-cards)) / 2);
  padding-bottom: var(--sp-3);
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-padding-inline: max(var(--gutter), (100% - var(--w-cards)) / 2);
  scrollbar-width: none;
}
.reel-track::-webkit-scrollbar { display: none; }
.reel-track:focus-visible { outline-offset: calc(var(--focus-offset) * -1); }

.reel-card {
  position: relative;
  flex: 0 0 var(--reel-card-w);
  aspect-ratio: 9 / 16;
  border-radius: var(--radius-lg);
  overflow: hidden;
  background: var(--surface);
  scroll-snap-align: start;
}
/* A landscape game is captured in 16:9. Cropped into a portrait card it keeps
   a narrow strip down the middle and throws the rest of the frame away, which
   for a game whose subject is a battlefield is most of the picture. */
.reel.is-landscape .reel-card {
  flex-basis: var(--reel-card-w-wide);
  aspect-ratio: 16 / 9;
}
.reel-card.is-openable { cursor: zoom-in; }
/* --edge is how much of the card the track's edge has taken, 0 to 1; js/play.js
   sets it as the strip scrolls. The card fades as it leaves (no blur: it looked
   smudged), so the row reads as running past the screen instead of stopping
   at it. The second selector outranks `.js .reveal.in { opacity: 1 }`, which
   otherwise wins once a card has revealed and cancels the fade. */
.reel-card,
.js .reel-card.reveal.in {
  opacity: calc(1 - var(--edge, 0) * var(--reel-edge-fade));
  transition: opacity var(--dur-fast) var(--ease);
}
/* Dragging the strip: the cursor says so, and the images do not start a
   native image drag of their own halfway through. */
.reel-track { cursor: grab; }
.reel-track.is-dragging,
.reel-track.is-dragging .reel-card { cursor: grabbing; }
.reel-track.is-dragging { user-select: none; }
.reel-card video,
.reel-art {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.reel-label {
  position: absolute;
  left: var(--sp-4);
  bottom: var(--sp-4);
  color: var(--ink-on-art);
  font-weight: var(--w-sub);
  text-shadow: var(--shadow-text);
}
/* Round play button; hides while the video runs, the card itself pauses it */
.reel-play {
  position: absolute;
  left: 50%;
  top: 50%;
  width: var(--reel-play);
  height: var(--reel-play);
  transform: translate(-50%, -50%);
  border: 0;
  border-radius: var(--radius-pill);
  background: var(--accent);
  color: var(--on-accent);
  box-shadow: var(--shadow-pop);
  cursor: pointer;
  transition: transform var(--dur-fast) var(--ease-pop), opacity var(--dur-fast) var(--ease);
}
.reel-play svg {
  width: 50%;
  height: 50%;
  margin: auto;
}
.reel-play:hover { transform: translate(-50%, -50%) scale(var(--scale-hover)); }
.reel-video.is-playing .reel-play { opacity: 0; pointer-events: none; }
.reel-video.is-playing { cursor: pointer; }

/* ---------- Info card ---------- */
.play-info {
  display: grid;
  gap: var(--gap-cards);
  padding-block: var(--section-pad);
}
.play-info.container-wide { width: var(--w-cards); }
.info-card {
  background: var(--surface);
  border-radius: var(--radius-lg);
  padding: var(--pad-card);
}
.info-card h2 {
  font-size: var(--text-h3);
  font-stretch: var(--stretch-display);
  letter-spacing: var(--tracking-display);
  margin-bottom: var(--sp-3);
}
.info-card p {
  color: var(--ink-dim);
  line-height: var(--lh-copy);
}
/* The description runs to a few paragraphs for the games that ship with the
   site; they need space between them, but not before the first. */
.info-card p + p { margin-top: var(--sp-4); }
/* A long description folds to its first lines and fades out; Show more opens
   it. js/play.js adds .is-clamped only when the text is really longer, so
   without script (or with a short text) everything shows. */
.about-text.is-clamped {
  max-height: var(--h-about-clamp);
  overflow: hidden;
  -webkit-mask-image: var(--mask-fade-bottom);
  mask-image: var(--mask-fade-bottom);
}
.text-toggle {
  margin-top: var(--sp-4);
  padding: 0;
  border: 0;
  background-color: transparent;
  color: var(--accent-text);
  font: inherit;
  font-weight: var(--w-ui);
  letter-spacing: var(--tracking-ui);
  cursor: pointer;
}
.controls {
  margin: 0;
  padding-left: var(--list-indent);
  color: var(--ink-dim);
  line-height: var(--lh-copy);
}
.controls li + li { margin-top: var(--sp-2); }
.controls li::marker { color: var(--accent-text); }

/* ---------- More games ---------- */
.more-games {
  padding-block: var(--section-pad) var(--pad-section);
}
.more-games.container-wide { width: var(--w-cards); }
.more-games h2 {
  font-size: var(--text-h2);
  font-stretch: var(--stretch-display);
  letter-spacing: var(--tracking-display);
  margin-bottom: var(--sp-5);
}
/* ---------- Lightbox ---------- */
/* A screenshot is a picture of a game; at thumbnail size in the reel it is
   barely a picture of anything. Clicking one opens it as it was taken. */
.lightbox {
  position: fixed;
  inset: 0;
  z-index: var(--z-lightbox);
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: var(--sp-4);
  padding: var(--lightbox-pad);
  background: var(--scrim-full);
  /* Fades in and out; display waits for the fade before it drops. Browsers
     without @starting-style simply open and close it at once. */
  transition: opacity var(--dur-fast) var(--ease), display var(--dur-fast) allow-discrete;
}
.lightbox[hidden] { opacity: 0; }
@starting-style { .lightbox { opacity: 0; } }
.lightbox-figure {
  margin: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--sp-3);
  min-width: 0;
}
#lightbox-img {
  max-width: 100%;
  max-height: var(--lightbox-max-h);
  object-fit: contain;
  border-radius: var(--radius-lg);
}
#lightbox-caption {
  color: var(--ink-on-art);
  font-size: var(--text-sm);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
}
.lightbox-close {
  position: absolute;
  top: var(--lightbox-pad);
  right: var(--lightbox-pad);
}
/* The chevron points right; the previous button is the same glyph turned.
   Disabled styling comes from .icon-btn:disabled in main.css. */
.lightbox-prev svg { transform: rotate(180deg); }

/* ---------- Responsive ---------- */
@media (max-width: 860px) {
  /* Arrows move under the picture: at this width a column of controls on each
     side leaves the screenshot too narrow to read. */
  .lightbox {
    grid-template-columns: 1fr 1fr;
    grid-template-rows: minmax(0, 1fr) auto;
    justify-items: center;
  }
  .lightbox-figure { grid-column: 1 / -1; }

  .player.container-wide,
  .play-info.container-wide,
  .more-games.container-wide { width: calc(100% - var(--gutter) * 2); }
  .player-stage.is-portrait { height: var(--h-player-m); }
  /* A landscape game in a portrait-shaped box was cut to its middle. The
     stage takes the game's own shape instead; fullscreen is where it grows. */
  .player-stage:not(.is-portrait) {
    height: auto;
    aspect-ratio: 16 / 9;
  }
  .player-stage:fullscreen,
  .player-stage.is-pseudo-full { height: 100%; aspect-ratio: auto; }
  .player-stage.is-pseudo-full { height: 100dvh; }
  /* The 16:9 stage on a phone is short: the cover keeps its icon and button
     and drops the hint, which the button already says. */
  .player-stage:not(.is-portrait) .player-cover {
    gap: var(--sp-3);
    padding: var(--sp-3);
  }
  .player-stage:not(.is-portrait) .player-cover-icon { width: var(--icon-cover-m); }
  .player-stage:not(.is-portrait) .player-hint { display: none; }
  .player-stage:not(.is-portrait) .is-unavailable .player-hint { display: block; }
  .player-bar { padding: var(--sp-3) var(--sp-4); }
  .reel-head {
    width: calc(100% - var(--gutter) * 2);
    align-items: flex-start;
    flex-direction: column;
  }
}

/* ---------- Reduced motion ---------- */
@media (prefers-reduced-motion: reduce) {
  .reel-play, .lightbox { transition: none; }
  .reel-track { scroll-behavior: auto; }
}
