/* play/embed.css — a phone playing itself, as a link to the real thing.
 *
 * Shared by every game page. Nothing in here names a game: the colours are
 * custom properties with One Shot's palette as their defaults, so a page with a
 * different palette overrides four values rather than forking the file.
 *
 * ===========================================================================
 * THE SHAPE, AND WHY IT IS NOT A MODERN IPHONE
 * ===========================================================================
 * An hour before the first version of this, an inline frame holding Lunar
 * Aspect was pulled off its own marketing page (commit 7177116): *"the app lays
 * its panels out against the viewport, and the viewport an inline frame on a
 * marketing page can give it is not one it was built for."* That is the failure
 * this file exists to avoid.
 *
 * Which phone was measured. One Shot's board sizes itself to
 * min(width, height − HUD), so a taller box does not make a bigger board — it
 * makes bigger empty bands, exactly as a real phone does. At a current iPhone's
 * 9:19.5 the height cap left a 260px board on a laptop, which is a demo you
 * squint at. 9:16 is an iPhone SE and most Androids, still unmistakably a
 * phone, and buys a board a fifth wider from the same height budget.
 *
 * ===========================================================================
 * THE HEIGHT IS CAPPED BEFORE THE WIDTH IS CHOSEN
 * ===========================================================================
 * A 9:16 box 400px wide is 711px tall, which does not fit a laptop once the
 * page around it is counted. So the height is decided first — the smaller of a
 * hard ceiling and a share of the viewport — and the width is derived from it,
 * then clamped to the column. One expression, and the box can never be taller
 * than the screen it is on.
 */

.game-embed {
  /* --- the four a different game would change --- */
  --ge-bg: #0A0E16;        /* the game's own background, so the box never flashes white */
  --ge-accent: #4de0e0;
  --ge-ink: #e8e8f0;
  --ge-dim: #9a9ab0;

  --ge-line: color-mix(in srgb, var(--ge-accent) 22%, transparent);
  --ge-radius: 22px;
  --ge-max-height: 780px;

  /* These two are the same number twice and must stay that way: `aspect-ratio`
     shapes the box, `--ge-ratio` is the same ratio in a form calc() can use to
     turn the capped height back into a width. 9 / 16 = 0.5625. */
  --ge-ratio: 0.5625;

  /* vh first, svh second: a browser old enough to fail the WasmGC check may not
     know svh, and this box still has to hold that browser's fallback card. */
  width: min(100%, calc(min(var(--ge-max-height), 76vh) * var(--ge-ratio)));
  width: min(100%, calc(min(var(--ge-max-height), 76svh) * var(--ge-ratio)));
  aspect-ratio: 9 / 16;
  /* Only reachable on a browser without `aspect-ratio` (Safari 14 and older),
     where it is the difference between a short box and a box of no height. */
  min-height: 420px;

  position: relative;
  margin-inline: auto;
  overflow: hidden;
  border: 1px solid var(--ge-line);
  border-radius: var(--ge-radius);
  background: var(--ge-bg);
  /* The glow the game's own lit tiles have, at the scale of a whole device.
     It is what stops the box reading as a screenshot pasted onto the page. */
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.6), 0 26px 70px -28px rgba(0, 0, 0, 0.95),
              0 0 60px -14px color-mix(in srgb, var(--ge-accent) 32%, transparent);
  color: var(--ge-ink);
  font: 15px/1.6 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
}

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

/* FIXED 390x693, ALWAYS, and scaled to fit by embed.js.
 *
 * `width=device-width` inside an iframe does not mean the iframe's width — on
 * iOS Safari it resolves to the DEVICE's width. So a 390px phone holding a
 * 310px box laid the game out for 390px inside a 310px hole, and the bottom of
 * the board went over the edge. That was the reported "scaling looks wrong on
 * the phone screen", and no amount of sizing the iframe in percentages fixes
 * it, because the page inside is not listening to the iframe.
 *
 * Giving it one viewport and scaling the result means the game lays out against
 * the same 390x693 phone on every device there is — which is also the only way
 * this can be checked once instead of on every screen anybody owns.
 *
 * `transform-origin: top left` so the scale grows from the corner the frame is
 * pinned to, rather than from the middle of a box it no longer fills. */
.game-embed iframe {
  position: absolute;
  top: 0;
  left: 0;
  width: 390px;
  height: 693px;
  border: 0;
  display: block;
  transform-origin: top left;
  /* The box is a link. Every pointer event belongs to the <a> over the top,
     including the ones that land on the board — a tap on the poster goes to
     the full-screen game, which is the whole point of the poster. */
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.45s ease;
}

.game-embed[data-state="live"] iframe { opacity: 1; }

/* --- the link over the whole thing ---------------------------------------- */

/* The call to action is an <a> in the page's own markup, not a button painted
   inside an iframe. It is focusable, announced, right-clickable,
   middle-clickable and visible in the status bar before it is pressed; a
   picture of a button is none of those. */
.game-embed-link {
  position: absolute;
  inset: 0;
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: center;
  text-decoration: none;
}

/* Only while there is something to look at. Before that the box is showing a
   loading state or a store card, and a transparent link over a store card
   would swallow the badge underneath it. */
.game-embed:not([data-state="live"]) .game-embed-link { display: none; }

/* 74%, and the number was arrived at by looking. The game draws its mark, name
   and two-line tagline centred in the poster; that block runs to about 64% of
   the frame, and the first attempt at 62% put the button straight through the
   tagline. 74% clears it with air, and lands where the game's own button sits
   on the screen this links to — so the thing you press does not move when you
   arrive.
   Percentages are safe here because the frame inside is always exactly
   390x693 and only ever scaled, so this offset means the same place on every
   screen rather than drifting with the viewport. */
.game-embed-cta {
  position: absolute;
  left: 50%;
  top: 74%;
  transform: translate(-50%, -50%);
  white-space: nowrap;
  font-size: 0.88rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  font-weight: 700;
  color: var(--ge-bg);
  background: var(--ge-accent);
  border-radius: 999px;
  padding: 0.85rem 1.7rem;
  /* 44px, Apple's own minimum target. */
  min-height: 44px;
  display: flex;
  align-items: center;
  box-shadow: 0 0 30px -4px var(--ge-accent);
  transition: transform 0.18s ease, box-shadow 0.18s ease;
}

.game-embed-link:hover .game-embed-cta {
  transform: translate(-50%, -50%) scale(1.04);
  box-shadow: 0 0 44px -2px var(--ge-accent);
}

.game-embed-link:focus-visible {
  outline: 2px solid var(--ge-accent);
  outline-offset: -4px;
  border-radius: var(--ge-radius);
}

@media (prefers-reduced-motion: no-preference) {
  /* A slow breath, far slower than anything a reader would track. It is there
     so the button reads as live rather than as part of the picture. */
  .game-embed[data-state="live"] .game-embed-cta {
    animation: ge-breathe 2.6s ease-in-out infinite;
  }
}

@keyframes ge-breathe {
  0%, 100% { box-shadow: 0 0 30px -4px var(--ge-accent); }
  50%      { box-shadow: 0 0 46px 0 var(--ge-accent); }
}

/* --- what sits over the box before it is live ----------------------------- */

.game-embed-over {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1rem;
  padding: 1.5rem 1.25rem;
  text-align: center;
}

.game-embed[data-state="live"] .game-embed-over { display: none; }

/* --- loading -------------------------------------------------------------- */

.game-embed-status {
  margin: 0;
  font-size: 0.74rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ge-dim);
  font-family: ui-monospace, SFMono-Regular, "SF Mono", "Cascadia Mono", Menlo,
               Consolas, monospace;
}

/* Three tiles lighting in sequence — the game's own chain, at the size of a
   progress indicator. A spinner would have been the generic answer; this is
   the only loading state this product could have. */
.game-embed-chain { display: flex; gap: 7px; }

.game-embed-chain i {
  width: 11px;
  height: 11px;
  border-radius: 3px;
  background: color-mix(in srgb, var(--ge-accent) 22%, transparent);
}

@media (prefers-reduced-motion: no-preference) {
  .game-embed-chain i { animation: ge-chain 1.35s ease-in-out infinite; }
  .game-embed-chain i:nth-child(2) { animation-delay: 0.15s; }
  .game-embed-chain i:nth-child(3) { animation-delay: 0.3s; }
}

@keyframes ge-chain {
  0%, 60%, 100% { background: color-mix(in srgb, var(--ge-accent) 22%, transparent);
                  box-shadow: none; }
  25%           { background: var(--ge-accent);
                  box-shadow: 0 0 14px var(--ge-accent); }
}

/* --- the card: held, and unsupported -------------------------------------- */

/* The game's own download wall drawn in HTML. Deliberately the same object: a
   surface in the game's colours with the cyan edge, the mark at the top, the
   badge at the bottom. A visitor whose browser is too old and a visitor who
   reaches the end of the demo should not feel they met two products. */
.game-embed-card {
  max-width: 19rem;
  padding: 1.5rem 1.35rem;
  border: 1px solid var(--ge-line);
  border-radius: 16px;
  background: rgba(16, 20, 32, 0.92);
  box-shadow: 0 18px 50px -22px #000;
}

.game-embed-card img.game-embed-mark {
  width: 54px;
  height: 54px;
  border-radius: 12px;
  margin-bottom: 0.9rem;
  box-shadow: 0 0 22px color-mix(in srgb, var(--ge-accent) 20%, transparent);
}

.game-embed-card h3 {
  margin: 0 0 0.5rem;
  font-size: 1.05rem;
  line-height: 1.25;
  color: var(--ge-ink);
  letter-spacing: -0.01em;
}

.game-embed-card p {
  margin: 0 0 1.1rem;
  font-size: 0.86rem;
  line-height: 1.55;
  color: var(--ge-dim);
}

/* Apple's artwork, under Apple's terms: never recoloured, never stretched,
   scaled only in proportion, never under the 40px minimum height. The link
   moves on hover; the badge does not. */
.game-embed-badge { display: inline-block; text-decoration: none; }
.game-embed-badge img { display: block; width: 148px; height: 49px; }
.game-embed-badge:hover { transform: translateY(-1px); }

.game-embed-soon {
  margin: 0.8rem 0 0;
  font-size: 0.68rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: #6f6f88;
  /* Without this it breaks as "COMING SOON ON GOOGLE / PLAY", which orphans
     the one word carrying the meaning. */
  text-wrap: balance;
  font-family: ui-monospace, SFMono-Regular, "SF Mono", "Cascadia Mono", Menlo,
               Consolas, monospace;
}

/* --- the load button (Save-Data only) ------------------------------------- */

.game-embed-load {
  font: inherit;
  font-size: 0.82rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  font-weight: 700;
  color: var(--ge-bg);
  background: var(--ge-accent);
  border: 0;
  border-radius: 999px;
  padding: 0.8rem 1.6rem;
  min-height: 44px;
  cursor: pointer;
  box-shadow: 0 0 26px -4px var(--ge-accent);
}

.game-embed-load:hover { filter: brightness(1.08); }

.game-embed :focus-visible {
  outline: 2px solid var(--ge-accent);
  outline-offset: 3px;
}

/* --- phones ---------------------------------------------------------------- */

/* A shorter box, so a third of the screen is always page and there is always
   somewhere to put a thumb that is not the poster. */
@media (max-width: 34rem) {
  .game-embed {
    width: min(100%, calc(min(var(--ge-max-height), 66vh) * var(--ge-ratio)));
    width: min(100%, calc(min(var(--ge-max-height), 66svh) * var(--ge-ratio)));
  }
}
