/* ═══════════════════════════════════════════════════════════════════════════
   Clean Arcade — the framed game page.

   One sheet for the standard game layout: the frame the game runs in, the
   control row under it, the fact cards and the fine print. It replaces the
   block of page-local <style> each game page used to carry its own copy of,
   so a change to the game frame is one edit rather than fifteen.

   The game itself is a same-origin <iframe>. Nothing in this file reaches
   inside it: the games are integrated, never modified.
   ═════════════════════════════════════════════════════════════════════════ */

.stage { padding-block: calc(var(--sec-y) * 0.5) var(--space-8); }

.game-frame-box {
  position: relative;
  width: 100%;
  height: min(82vh, 680px);
  min-height: 520px;
  overflow: hidden;
  border-radius: var(--radius-lg);
  background: var(--ground-3);
}
.game-frame-box > iframe {
  display: block;
  width: 100%;
  height: 100%;
  border: 0;
  background: transparent;
}

/* ── the shell ───────────────────────────────────────────────────────────
   The frame and its control row are one element, because that element is
   what goes full screen. Promoting the frame alone put the player inside a
   document with no way out but Escape — which a phone does not have. */
.game-shell { position: relative; display: flex; flex-direction: column; }

/* Full screen: the shell becomes the viewport. The frame takes everything
   left after the control row, and the row stays on screen throughout. */
.game-shell:fullscreen,
.game-shell:-webkit-full-screen {
  width: 100vw;
  height: 100vh;
  height: 100dvh;
  padding: 0 0 max(4px, env(safe-area-inset-bottom));
  background: var(--ground-3);
}
.game-shell:fullscreen .game-frame-box,
.game-shell:-webkit-full-screen .game-frame-box {
  flex: 1 1 auto;
  height: auto;
  min-height: 0;
  max-height: none;             /* the page's 860px cap would leave a band empty */
  border-radius: 0;
  border: 0 !important;
}
/* ── the deck in full screen ─────────────────────────────────────────────
   The frame takes every pixel the deck does not: the deck becomes a slim
   strip UNDER the game (pills 30px, the strip ~38px) instead of a rail
   floating over it, so it can never cover a game's own HUD — Sarout Kart's
   POS / LAP / KM included. The pills sit at the inline end (right, or left in
   Arabic), clear of the centre of the view. */
.game-shell:fullscreen .game-controls,
.game-shell:-webkit-full-screen .game-controls,
body.ca-pseudo-fs .game-controls {
  flex: none;
  flex-wrap: nowrap;
  justify-content: flex-end;
  gap: 6px;
  margin: 0;
  padding: 4px max(10px, env(safe-area-inset-right)) 0 max(10px, env(safe-area-inset-left));
}
.game-shell:fullscreen .game-controls .ctl,
.game-shell:-webkit-full-screen .game-controls .ctl,
body.ca-pseudo-fs .game-controls .ctl {
  flex: 0 0 auto;
  min-height: 30px;
  padding: 0 12px;
  font-size: 11.5px;
}
.game-shell:fullscreen .game-controls .ctl svg,
.game-shell:-webkit-full-screen .game-controls .ctl svg,
body.ca-pseudo-fs .game-controls .ctl svg { width: 14px; height: 14px; }
/* a phone on its side keeps the icons and drops the words: 28px pills */
@media (max-width: 680px), (max-height: 500px) {
  .game-shell:fullscreen .game-controls .ctl span,
  .game-shell:-webkit-full-screen .game-controls .ctl span,
  body.ca-pseudo-fs .game-controls .ctl span {
    position: absolute; width: 1px; height: 1px;
    overflow: hidden; clip-path: inset(50%); white-space: nowrap;
  }
  .game-shell:fullscreen .game-controls .ctl,
  .game-shell:-webkit-full-screen .game-controls .ctl,
  body.ca-pseudo-fs .game-controls .ctl { min-height: 28px; min-width: 40px; padding: 0 10px; }
}

/* Full screen: the frame box becomes the viewport, so the game inside gets
   every pixel and the rounded corner that would letterbox it is dropped. */
.game-frame-box:fullscreen,
.game-frame-box:-webkit-full-screen {
  height: 100%;
  min-height: 0;
  max-height: none;
  border-radius: 0;
  border: 0 !important;
}

/* ── the iPhone fallback ─────────────────────────────────────────────────
   iOS Safari on iPhone ships no Element.requestFullscreen, so the button
   would be dead on the most common device in the arcade. ca-tools.js puts
   .ca-pseudo-fs on <body> instead and the frame becomes the viewport — the
   same result, reached with CSS. Everything else on the page is hidden so a
   stray scroll cannot reveal the header underneath. */
body.ca-pseudo-fs { overflow: hidden; }
body.ca-pseudo-fs > *:not(main),
body.ca-pseudo-fs main > *:not(.stage),
body.ca-pseudo-fs .stage > *:not(.game-shell) { display: none !important; }
body.ca-pseudo-fs .stage { padding: 0; margin: 0; max-width: none; }
body.ca-pseudo-fs .game-shell {
  position: fixed;
  inset: 0;
  z-index: 10001;
  height: 100dvh;
  padding-block-end: max(8px, env(safe-area-inset-bottom));
  background: var(--ground-3);
}
body.ca-pseudo-fs .game-frame-box {
  flex: 1 1 auto;
  height: auto;
  min-height: 0;
  max-height: none;
  border: 0 !important;
  border-radius: 0;
}
/* the rail rides along inside the shell, so Exit full screen and the way
   home are both still there — the geometry is the full-screen rail's above */
body.ca-pseudo-fs .game-controls { display: flex !important; }

.game-controls .ctl[disabled] { opacity: .42; cursor: default; box-shadow: none; }
.game-controls .ctl[disabled]:hover { background: color-mix(in srgb, var(--card-face) 72%, transparent); }

/* the placeholder the frame paints until the game's first frame arrives */
.frame-loading {
  position: absolute; inset: 0;
  display: flex; align-items: center; justify-content: center;
  gap: var(--space-3);
  font-size: 13px; font-weight: 600; letter-spacing: 0.04em;
  color: color-mix(in srgb, var(--color-text) 60%, transparent);
  pointer-events: none;
  transition: opacity .3s ease;
}
.frame-loading[hidden] { display: none; }
.frame-loading i {
  width: 16px; height: 16px; border-radius: 50%;
  border: 2px solid color-mix(in srgb, var(--neon) 35%, transparent);
  border-top-color: var(--neon);
  animation: frame-spin .8s linear infinite;
}
@keyframes frame-spin { to { transform: rotate(360deg); } }

/* ── the deck ────────────────────────────────────────────────────────────
   The Halal Ninja cabinet's deck, shared by all 25 games: Full screen,
   Restart and Exit as three lit pills, each in its own tube colour, directly
   under the frame. 36px rather than 44px, so it reads as a control strip
   and not as a second footer. */
.game-controls {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  margin-block-start: var(--space-3);
}
.game-controls .ctl {
  --pill: var(--n-cyan);
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  min-height: 36px; padding: 0 14px;
  border-radius: 999px;
  font-family: inherit; font-size: 12.5px; font-weight: 700; white-space: nowrap;
  text-decoration: none; cursor: pointer;
  color: var(--pill);
  background: color-mix(in srgb, var(--pill) 8%, transparent);
  border: 1px solid color-mix(in srgb, var(--pill) 55%, transparent);
  box-shadow: 0 0 18px -10px var(--pill), inset 0 0 16px -13px var(--pill);
  transition: background .16s ease, box-shadow .16s ease, transform .16s ease;
}
.game-controls .ctl:hover { background: color-mix(in srgb, var(--pill) 17%, transparent); box-shadow: 0 0 24px -8px var(--pill); }
.game-controls .ctl:active { transform: translateY(1px); background: color-mix(in srgb, var(--pill) 26%, transparent); }
.game-controls .ctl:focus-visible { outline: 2px solid var(--pill); outline-offset: 3px; }
.game-controls .ctl svg { width: 15px; height: 15px; flex: none; }
.game-controls .ctl[hidden] { display: none; }
.game-controls .ctl-fs { --pill: var(--n-cyan); }
.game-controls .ctl-restart { --pill: var(--n-violet); }
.game-controls .ctl-home { --pill: var(--n-magenta); }
[dir="rtl"] .game-controls .ctl-home svg { transform: scaleX(-1); }

.fine {
  margin-block-start: var(--space-4);
  font-size: 12.5px; font-weight: 400; line-height: 1.55; max-width: 84ch;
  color: color-mix(in srgb, var(--color-text) 58%, transparent);
}

/* ── fact cards ──────────────────────────────────────────────────────── */
.info-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr));
  gap: var(--space-4);
}
.info-card { padding: var(--space-6); border-radius: var(--radius-lg); }
.info-card h3 { font-size: 17px; font-weight: 700; margin: 0 0 var(--space-2); letter-spacing: -0.015em; }
.info-card p { margin: 0; font-size: 14px; font-weight: 400; line-height: 1.55; color: color-mix(in srgb, var(--color-text) 78%, transparent); }

/* ── the fact-card link ──────────────────────────────────────────────────
   A fact card that points somewhere real ends in a link the size of a
   control, not a sentence with an underline in it. Outlined in the section's
   accent, 44px tall, and it wraps rather than overflowing a narrow card. */
.fact-link {
  display: inline-flex; align-items: center; gap: 8px;
  align-self: flex-start;
  min-height: 44px; padding: 0 var(--space-4);
  margin-block-start: var(--space-3);
  border-radius: 999px;
  font-size: 13.5px; font-weight: 600; text-decoration: none;
  color: var(--neon);
  background: color-mix(in srgb, var(--card-face) 72%, transparent);
  border: 1px solid color-mix(in srgb, var(--neon) 50%, transparent);
  transition: background-color .15s ease, transform .15s ease;
}
.fact-link:hover { background: color-mix(in srgb, var(--neon) 14%, transparent); }
.fact-link:active { transform: translateY(1px); }
.fact-link:focus-visible { outline: 2px solid var(--neon); outline-offset: 2px; }
.fact-link svg { width: 15px; height: 15px; flex: none; }
.info-card:has(.fact-link) { display: flex; flex-direction: column; }
@media (prefers-reduced-motion: reduce) { .fact-link { transition: none; } }

.neon-text-cyan { color: var(--n-cyan); text-shadow: 0 0 16px color-mix(in srgb, var(--n-cyan) 55%, transparent); }
.neon-text-magenta { color: var(--n-magenta); text-shadow: 0 0 16px color-mix(in srgb, var(--n-magenta) 55%, transparent); }
.neon-text-lime { color: var(--n-lime); text-shadow: 0 0 16px color-mix(in srgb, var(--n-lime) 55%, transparent); }
.neon-text-violet { color: var(--n-violet); text-shadow: 0 0 16px color-mix(in srgb, var(--n-violet) 55%, transparent); }
/* by day the tubes are ink, and ink does not glow */
:root[data-theme="day"] .neon-text-cyan,
:root[data-theme="day"] .neon-text-magenta,
:root[data-theme="day"] .neon-text-lime,
:root[data-theme="day"] .neon-text-violet { text-shadow: none; }

.back-pill {
  border-radius: 999px; min-height: 44px; font-size: 13.5px; font-weight: 600; white-space: nowrap;
  color: var(--n-cyan); border: 1px solid color-mix(in srgb, var(--n-cyan) 55%, transparent);
  box-shadow: 0 0 20px -10px var(--n-cyan), inset 0 0 18px -14px var(--n-cyan);
}
.back-pill:hover { background: color-mix(in srgb, var(--n-cyan) 12%, transparent); }

/* ── phones and tablets ──────────────────────────────────────────────────
   A shorter frame: fewer device pixels for the game to push per frame, and
   the control row still lands above the fold. The frame never exceeds the
   viewport width, so no game can introduce a horizontal scrollbar. */
@media (max-width: 900px) {
  .game-frame-box { height: min(72vh, 600px); min-height: 440px; }
}
@media (max-width: 760px) {
  .game-frame-box { height: min(68vh, 520px); min-height: 380px; }
  .game-controls .ctl { padding: 0 12px; font-size: 12px; }
}
@media (max-width: 560px) {
  .game-frame-box { height: min(66vh, 460px); min-height: 340px; }
  .game-controls .ctl { flex: 1 1 0; min-width: 0; padding: 0 8px; }
  .game-controls .ctl span { overflow: hidden; text-overflow: ellipsis; }
}
/* a short landscape phone: the frame takes what is left after the chrome */
@media (max-height: 520px) and (orientation: landscape) {
  .game-frame-box { height: 78vh; min-height: 260px; }
}
@media (hover: none) {
  .info-card, .game-frame-box, .game-controls .ctl { transition: none; }
}
@media (prefers-reduced-motion: reduce) {
  .frame-loading i { animation: none; }
}

/* ── the site footer on a game page ──────────────────────────────────────
   Same as the homepage: a fixed strip on the bottom edge, always visible,
   with the prayer pill resting on it (footer.js measures it and pads the
   body, so the last thing on the page is never under it). In full screen
   (and the iPhone pseudo-full-screen) the frame IS the viewport, so the bar
   stands down completely. */
body.ca-pseudo-fs #sa-footer,
body.ca-pseudo-fs #sa-disclaimer-panel { display: none !important; }

/* ── the game page header ────────────────────────────────────────────────
   A framed game page carries more chrome than the homepage does: brand,
   language row, theme switch, refresh, full screen and the back pill. Below
   the desktop width the least load-bearing pieces step aside in order —
   badge first, then the back pill's label (the icon and its aria-label stay,
   so the control is still there and still named). */
@media (max-width: 1180px) {
  .ca-framed .brand-badge { display: none; }
}
@media (max-width: 1000px) {
  .ca-framed .back-pill span {
    position: absolute; width: 1px; height: 1px;
    overflow: hidden; clip-path: inset(50%); white-space: nowrap;
  }
  .ca-framed .back-pill { padding-inline: var(--space-4); }
}
@media (max-width: 620px) {
  .ca-framed .brand-name { font-size: 16px; }
  .ca-framed .head-tools { gap: 4px; }
}
/* Under ~560px the framed pages use the arcade's own two-row phone header
   (logo + timer, then the tool row): the back pill and the header's
   full-screen icon both come out, because the control row under the frame
   already carries Full screen, Exit full screen and Back to Clean Arcade at
   thumb size. What is left — refresh, the theme switch and the five
   languages — fits one row without scrolling. */
@media (max-width: 560px) {
  .ca-framed #ca-fs-btn { display: none; }
}

/* ── the brand: the lit edge ─────────────────────────────────────────────
   The game frame wears the one lit edge the brand book allows per page: a
   4px tube at 135°, magenta → cyan → yellow → green → magenta, glowing cyan
   and magenta by night and casting a warm shadow by day. */

.ca-framed .game-frame-box {
  border: 4px solid transparent !important;
  border-radius: 26px;
  background:
    linear-gradient(var(--ground-3), var(--ground-3)) padding-box,
    var(--edge-lit) border-box !important;
  box-shadow:
    0 0 44px -12px color-mix(in srgb, var(--n-cyan) 60%, transparent),
    0 0 90px -30px color-mix(in srgb, var(--n-magenta) 70%, transparent) !important;
}
:root[data-theme="day"] .ca-framed .game-frame-box {
  box-shadow: 0 26px 50px -24px rgba(58, 46, 30, .42), 0 2px 6px rgba(58, 46, 30, .12) !important;
}
@media (max-width: 600px) {
  .ca-framed .game-frame-box { border-width: 3px !important; border-radius: 20px; }
}

/* ── v3.19.0: the frame fits the screen ──────────────────────────────────
   Scrolled to the game, the frame and its control row fill exactly what the
   sticky header (--ca-head-h, measured by ca-tools.js) and the fixed footer
   (--sa-foot-h, measured by footer.js) leave, so neither ever covers the
   game or its buttons. They did: the footer sat on the control row on
   laptops, and a phone held sideways saw barely half the game. The stage is
   at least one screen tall, so it can always be scrolled to the top. */
.ca-framed .stage { padding-top: 10px; min-height: calc(100dvh - var(--ca-head-h, 64px)); }
/* the site's scroll-padding already clears the header by --head-h + 16px;
   on a game page it clears the measured header exactly */
html:has(body.ca-framed) { scroll-padding-top: var(--ca-head-h, 64px); }
.ca-framed .game-frame-box {
  height: calc(100dvh - var(--ca-head-h, 64px) - var(--sa-foot-h, 28px) - 68px);
  min-height: 300px; max-height: 860px;
}
/* a phone on its side: the header scrolls away with the page and the game
   takes the whole screen above the footer; its control row sits just below */
@media (max-height: 520px) and (orientation: landscape) {
  .ca-framed .site-head { position: relative; }
  .ca-framed .stage { padding-top: 4px; min-height: 100dvh; }
  html:has(body.ca-framed) { scroll-padding-top: 0; }
  .ca-framed .game-frame-box { height: calc(100dvh - var(--sa-foot-h, 28px) - 10px); min-height: 0; max-height: none; }
}
