/* =========================================================================
   Pythonation Games — base styles copied from pythonation.com/assets/css/site.css
   Brand: October 2026. Paper #E6E6E7 · crimson #B32351 · blue #4F72A2 ·
   wire #496A95 · ink #1F2A3D · night #141A2A · light blue #8FB0DA.
   Type: IBM Plex Sans Arabic (Arabic + Latin), IBM Plex Mono (labels),
   IBM Plex Sans SC (Chinese). Self-hosted, subset. Logical properties only.
   ========================================================================= */

/* ---------------- Fonts ---------------- */
@font-face { font-family: "Plex Arabic"; font-weight: 400; font-display: swap;
  src: url("../fonts/plex-arabic-ar-400.woff2") format("woff2");
  unicode-range: U+0600-06FF, U+200C-200F, U+2010-2011, U+204F, U+2E41, U+FB50-FDFF, U+FE70-FEFC; }
@font-face { font-family: "Plex Arabic"; font-weight: 600; font-display: swap;
  src: url("../fonts/plex-arabic-ar-600.woff2") format("woff2");
  unicode-range: U+0600-06FF, U+200C-200F, U+2010-2011, U+204F, U+2E41, U+FB50-FDFF, U+FE70-FEFC; }
@font-face { font-family: "Plex Arabic"; font-weight: 400; font-display: swap;
  src: url("../fonts/plex-arabic-latin-400.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+2013-2014, U+2018-201D, U+2022, U+2026, U+20AC, U+2122; }
@font-face { font-family: "Plex Arabic"; font-weight: 600; font-display: swap;
  src: url("../fonts/plex-arabic-latin-600.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+2013-2014, U+2018-201D, U+2022, U+2026, U+20AC, U+2122; }
@font-face { font-family: "Plex Mono"; font-weight: 400; font-display: swap;
  src: url("../fonts/plex-mono-400.woff2") format("woff2"); }
@font-face { font-family: "Plex Mono"; font-weight: 500; font-display: swap;
  src: url("../fonts/plex-mono-500.woff2") format("woff2"); }

/* ---------------- Tokens ---------------- */
:root {
  --paper: #E6E6E7;
  --crimson: #B32351;
  --blue: #4F72A2;
  --wire: #496A95;
  --ink: #1F2A3D;
  --night: #141A2A;
  --lightblue: #8FB0DA;

  --bg: var(--paper);
  --text: var(--ink);
  --muted: #4A5568;
  --accent: var(--crimson);
  --accent-ink: #fff;
  --link: var(--blue);
  --card: #EFEFF0;
  --card-line: rgba(31, 42, 61, 0.10);
  --shadow: 0 1px 2px rgba(20, 26, 42, 0.05), 0 12px 40px -12px rgba(20, 26, 42, 0.16);
  --field: #fff;
  --dot: 79, 114, 162; /* blue, as rgb for the canvas */
  --word: var(--blue);
  --wire-stroke: var(--wire);

  --font: "Plex Arabic", system-ui, -apple-system, "Segoe UI", sans-serif;
  --mono: "Plex Mono", ui-monospace, "SFMono-Regular", Menlo, monospace;
  --radius: 28px;
  --radius-lg: 40px;
  --maxw: 1080px;
  --ease: cubic-bezier(0.22, 1, 0.36, 1);
}
:lang(zh-Hans) { --font: "Plex SC", "Plex Arabic", "PingFang SC", "Microsoft YaHei", sans-serif; }

@media (prefers-color-scheme: dark) {
  :root {
    --bg: var(--night);
    --text: var(--paper);
    --muted: #A9B4C6;
    --link: var(--lightblue);
    --card: #1A2134;
    --card-line: rgba(143, 176, 218, 0.14);
    --shadow: 0 1px 2px rgba(0, 0, 0, 0.3), 0 16px 48px -16px rgba(0, 0, 0, 0.6);
    --field: #0F1422;
    --dot: 143, 176, 218;
    --word: var(--lightblue);
    --wire-stroke: var(--lightblue);
  }
}

/* ---------------- Base ---------------- */
*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; }
html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; }
body {
  min-height: 100vh;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font);
  font-size: 17px;
  line-height: 1.7;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}
:lang(zh-Hans) body, body:lang(zh-Hans) { line-break: strict; word-break: normal; }
a { color: var(--link); text-underline-offset: 3px; }
img, svg { display: block; max-width: 100%; }
.mono { font-family: var(--mono); font-weight: 500; letter-spacing: 0; }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; border-radius: 6px; }
::selection { background: var(--crimson); color: #fff; }

.wrap { width: min(100% - 32px, var(--maxw)); margin-inline: auto; }
.sr, .hp { position: absolute !important; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.skip { position: absolute; inset-inline-start: 16px; top: -60px; z-index: 10; padding: 8px 14px;
  background: var(--ink); color: #fff; border-radius: 10px; }
.skip:focus { top: 12px; }

/* The moving dot grid sits behind everything. */
.dots { position: fixed; inset: 0; width: 100%; height: 100%; z-index: 0; pointer-events: none; }
header, main, footer { position: relative; z-index: 1; }

/* ---------------- Header ---------------- */
.top { display: flex; align-items: center; justify-content: space-between; gap: 16px; padding-block: 20px; }
.brand { display: inline-flex; align-items: center; gap: 10px; color: var(--text); text-decoration: none; }
.brand img { border-radius: 9px; }
.brand .mono { font-size: 15px; }
.langs ul { display: flex; gap: 4px; padding: 4px; list-style: none;
  background: var(--card); border: 1px solid var(--card-line); border-radius: 999px; }
.langs a { display: block; padding: 6px 14px; border-radius: 999px; color: var(--muted);
  text-decoration: none; font-size: 14px; line-height: 1.4; }
.langs a { white-space: nowrap; }
@media (max-width: 420px) {
  .brand .mono { display: none; }
  .langs a { padding: 6px 11px; font-size: 13px; }
}
.langs a:hover { color: var(--text); }
.langs a[aria-current="page"] { background: var(--ink); color: var(--paper); }
@media (prefers-color-scheme: dark) { .langs a[aria-current="page"] { background: var(--paper); color: var(--night); } }
.langs a[lang="ar"] { font-family: "Plex Arabic", sans-serif; }
.langs a[lang="zh-Hans"] { font-family: "Plex SC", sans-serif; }

/* ---------------- Hero ---------------- */
.hero { display: flex; flex-direction: column; align-items: center; text-align: center;
  padding-block: clamp(8px, 3vw, 32px) clamp(48px, 8vw, 88px); }
.logo-wrap { width: clamp(190px, 34vw, 290px); aspect-ratio: 1; margin-block-end: 8px; outline: none; }
.logo { width: 100%; height: 100%; overflow: visible; }

.eyebrow { color: var(--blue); font-size: 13px; margin-block-end: 14px; }
.eyebrow span { color: var(--crimson); }
@media (prefers-color-scheme: dark) { .eyebrow { color: var(--lightblue); } }

/* Bilingual titles: lead language on top, English underneath. */
.bi { display: flex; flex-direction: column; align-items: center; gap: 4px; font-weight: 600; }
.bi-1 { line-height: 1.35; }
.bi-2 { font-family: var(--mono); font-weight: 400; font-size: 0.42em; color: var(--muted);
  letter-spacing: 0; line-height: 1.5; }
h1.bi { font-size: clamp(30px, 5.6vw, 52px); max-width: 18ch; }
:lang(zh-Hans) h1.bi { max-width: 16em; }
h1.bi .bi-2 { font-size: clamp(14px, 1.8vw, 17px); margin-block-start: 6px; }

.lede { max-width: 54ch; margin-block: 18px 30px; color: var(--muted); font-size: clamp(17px, 2vw, 19px); }

/* ---------------- Cards ---------------- */
.grid { display: grid; grid-template-columns: 1.15fr 1fr; gap: 20px; padding-block-end: 56px; }
@media (max-width: 860px) { .grid { grid-template-columns: 1fr; } }
.card { padding: clamp(22px, 3.4vw, 34px); background: var(--card); border: 1px solid var(--card-line);
  border-radius: var(--radius-lg); box-shadow: var(--shadow); }
.card .bi { align-items: flex-start; font-size: 24px; margin-block-end: 18px; text-align: start; }
.card .bi .bi-2 { font-size: 13px; }
.card .bi.small { font-size: 20px; margin-block-end: 8px; }
.card hr { border: 0; border-block-start: 1px solid var(--card-line); margin-block: 26px; }
.muted { color: var(--muted); font-size: 15px; }

/* Night window — the episode card, like the brand code window. */
.card-night { background: var(--night); color: var(--paper); border-color: rgba(143, 176, 218, .16); }
.card-night .bi-2 { color: var(--lightblue); }
@media (prefers-color-scheme: dark) { .card-night { background: #0D1220; } }
.win-bar { display: flex; align-items: center; gap: 7px; margin-block-end: 20px; }
.win-bar i { width: 11px; height: 11px; border-radius: 50%; background: #2A3550; }
.win-bar i:first-child { background: var(--crimson); }
.win-bar span { margin-inline-start: auto; font-size: 12px; color: var(--lightblue); opacity: .8; }

/* Small standalone pages (confirm link, no-JS form result). */
.standalone { min-height: 100vh; justify-content: center; }
.standalone-mark { border-radius: 18px; margin-block-end: 24px; }
.form-msg.big { font-size: 20px; max-width: 36ch; }

/* ---------------- Footer ---------------- */
.foot { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 8px 24px;
  padding-block: 24px 40px; border-block-start: 1px solid var(--card-line); color: var(--muted); font-size: 14px; }
.foot-links { display: flex; flex-wrap: wrap; gap: 4px 18px; list-style: none; padding: 0; margin: 0; }
.foot-links a { color: var(--muted); }
.foot-links a:hover { color: var(--text); }

/* ---------------- Logo: drawn like a pen ----------------
   1. the wireframe draws in, 2. the brain outline is drawn,
   3. the ink fills the brain from the bottom, 4. the wordmark settles in.
   The brain never pops or scales in. */
.logo .wire path { fill: none; stroke: var(--wire-stroke); stroke-opacity: .34; stroke-width: 1.1;
  stroke-linejoin: round; stroke-dasharray: 100; stroke-dashoffset: 100;
  animation: pyn-draw 1.4s var(--ease) forwards; animation-delay: calc(var(--i, 0) * 16ms); }
.logo .sig path { fill: none; stroke: var(--crimson); stroke-width: 2.6; stroke-linecap: round;
  stroke-dasharray: 14 100; stroke-dashoffset: 14; opacity: 0; }
.logo .brain-line { fill: none; stroke: var(--crimson); stroke-width: 3; stroke-linejoin: round;
  stroke-dasharray: 100; stroke-dashoffset: 100; animation: pyn-draw 1.6s cubic-bezier(.45,.05,.35,1) .35s forwards,
  pyn-fade .6s ease 2.6s forwards; }
.logo .brain-ink { fill: var(--crimson); }
.logo .ink-rect { transform: translateY(460px); animation: pyn-ink 1.2s cubic-bezier(.55,.1,.3,1) 1.55s forwards; }
.logo .word path { fill: var(--word); }
.logo .word { opacity: 0; animation: pyn-word .9s var(--ease) 2.3s forwards; }
.logo .brain { transform-box: view-box; transform-origin: 336.4px 543.1px; }

@keyframes pyn-draw { to { stroke-dashoffset: 0; } }
@keyframes pyn-fade { to { stroke-opacity: 0; } }
@keyframes pyn-ink { to { transform: translateY(0); } }
@keyframes pyn-word { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
@keyframes pyn-sig { 0% { stroke-dashoffset: 14; opacity: 0; } 15% { opacity: .9; } 85% { opacity: .9; } 100% { stroke-dashoffset: -100; opacity: 0; } }
@keyframes pyn-beat { 0%, 40%, 100% { transform: scale(1); } 12% { transform: scale(1.045); } 24% { transform: scale(1.015); } 32% { transform: scale(1.03); } }

/* After the intro, hover plays the brand hover animation (signals + heartbeat). */
.logo-wrap.ready:hover .sig path { animation: pyn-sig 1.6s linear infinite; animation-delay: calc(.2s + var(--s, 0) * .2s); }
.logo-wrap.ready:hover .brain { animation: pyn-beat 1.6s ease-in-out .15s infinite; }

@media (prefers-reduced-motion: reduce) {
  .logo *, .logo-wrap * { animation: none !important; transition: none !important; }
  .logo .wire path, .logo .brain-line { stroke-dashoffset: 0; }
  .logo .brain-line { stroke-opacity: 0; }
  .logo .ink-rect { transform: none; }
  .logo .word { opacity: 1; }
  .btn, .social a, .yt-play img { transition: none; }
}

/* =========================================================================
   Pythonation Games — what the games hub adds on top of the base styles.
   Same tokens, type and components as pythonation.com.
   ========================================================================= */

/* Buttons, exactly as on pythonation.com. */
.btn { display: inline-flex; align-items: center; justify-content: center; gap: 10px;
  padding: 12px 22px; border-radius: 999px; border: 1px solid transparent;
  font: 600 16px/1.3 var(--font); cursor: pointer; text-decoration: none; white-space: nowrap;
  transition: background-color .2s var(--ease), border-color .2s var(--ease), color .2s var(--ease); }
.btn-primary { background: var(--accent); color: var(--accent-ink); }
.btn-primary:hover { background: #9B1D46; }
.btn-ghost { background: transparent; border-color: var(--card-line); color: var(--text); }
.btn-ghost:hover { border-color: var(--blue); }
@media (prefers-reduced-motion: reduce) { .btn { transition: none; } }

/* Header pills: the same shape as the language switcher on pythonation.com. */
.pills ul { display: flex; gap: 4px; padding: 4px; list-style: none;
  background: var(--card); border: 1px solid var(--card-line); border-radius: 999px; }
.pills a { display: block; padding: 6px 14px; border-radius: 999px; color: var(--muted);
  text-decoration: none; font-size: 14px; line-height: 1.4; white-space: nowrap; }
.pills a:hover { color: var(--text); }
.pills a[aria-current="page"] { background: var(--ink); color: var(--paper); }
@media (prefers-color-scheme: dark) { .pills a[aria-current="page"] { background: var(--paper); color: var(--night); } }
.pills a.mono { font-size: 13px; }
@media (max-width: 560px) { .pills .opt { display: none; } }

/* A shorter hero than the homepage: the catalogue is the point. */
.hero.compact { padding-block: clamp(4px, 2vw, 16px) clamp(32px, 5vw, 56px); }
.hero.compact .logo-wrap { width: clamp(132px, 20vw, 176px); }
.lede-en { max-width: 60ch; margin-block: -18px 0; color: var(--muted); font: 400 14px/1.6 var(--mono); }
.stats { display: flex; flex-wrap: wrap; justify-content: center; gap: 8px; margin-block-start: 26px;
  list-style: none; padding: 0; }
.stats li { padding: 6px 14px; border: 1px solid var(--card-line); border-radius: 999px; background: var(--card);
  color: var(--muted); font-size: 14px; }
.stats b { color: var(--text); font: 500 14px var(--mono); margin-inline-end: 6px; }

/* Sections */
.shelf { padding-block-end: 48px; scroll-margin-top: 16px; }
.shelf-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 16px; margin-block-end: 18px; }
.shelf-head .bi { align-items: flex-start; font-size: 26px; text-align: start; }
.shelf-head .bi .bi-2 { font-size: 13px; }
.shelf-head .count { font: 500 13px var(--mono); color: var(--muted); white-space: nowrap; }

.items { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 440px), 1fr)); gap: 20px; }

/* A shelf with a single entry shows it wide: cover beside the text. */
.items.solo { grid-template-columns: 1fr; }
@media (min-width: 860px) {
  .items.solo .item { display: grid; grid-template-columns: 1.3fr 1fr; column-gap: 32px; align-items: start; }
  .items.solo .item .win-bar { grid-column: 1 / -1; }
  .items.solo .item .item-meta { margin-block-start: 0; height: 100%; }
}

/* A game card is the night window from the homepage, with the cover where the video sits. */
.item { display: flex; flex-direction: column; }
.cover { position: relative; display: block; aspect-ratio: 16 / 9; border-radius: var(--radius); overflow: hidden;
  background: #0A0E19; border: 1px solid rgba(143, 176, 218, .14); }
.cover img { width: 100%; height: 100%; object-fit: cover; opacity: .88; transition: opacity .3s var(--ease); }
.cover:hover img, .cover:focus-visible img { opacity: 1; }
.cover .play { position: absolute; inset-block-start: 50%; inset-inline-start: 50%; width: 68px; height: 68px;
  margin: -34px; border-radius: 50%; background: var(--crimson); display: grid; place-items: center; }
.cover .play::before { content: ""; margin-inline-start: 5px; border-block: 12px solid transparent; border-inline-start: 20px solid #fff; }
html[dir="rtl"] .cover .play::before { margin-inline-start: 0; margin-inline-end: 5px; border-inline-start: 0; border-inline-end: 20px solid #fff; }
.cover .badge { position: absolute; inset-block-start: 14px; inset-inline-end: 14px; padding: 5px 10px; border-radius: 999px;
  background: rgba(13, 18, 32, .82); color: var(--paper); font: 500 12px/1.2 var(--mono); }

.item-meta { display: flex; flex-direction: column; gap: 12px; flex: 1; margin-block-start: 18px; }
.kicker { font: 500 12px/1.4 var(--mono); color: var(--lightblue); letter-spacing: .04em; }
.kicker span { color: #F07A9C; }
.item h3.bi { align-items: flex-start; font-size: 28px; text-align: start; }
.item h3.bi .bi-2 { font-size: 13px; color: var(--lightblue); letter-spacing: .14em; }
.desc { color: #C9D2E0; font-size: 16px; }
.desc-en { color: #8893A5; font: 400 13px/1.6 var(--mono); }

.tags { display: flex; flex-wrap: wrap; gap: 6px; list-style: none; padding: 0; }
.tags li { padding: 5px 11px; border-radius: 999px; border: 1px solid rgba(143, 176, 218, .22);
  color: var(--lightblue); font: 500 12px/1.3 var(--mono); }
.tags li.model { background: var(--crimson); border-color: var(--crimson); color: #fff; }

.actions { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; margin-block-start: auto; padding-block-start: 10px; }
.card-night .btn-ghost { color: var(--paper); border-color: rgba(143, 176, 218, .24); }
.card-night .btn-ghost:hover { border-color: var(--lightblue); }
.btn .arrow { font-family: var(--mono); font-weight: 500; }
.needs { font-size: 13px; color: #8893A5; }

/* How to play: a native disclosure, no script needed. */
.keys { border-block-start: 1px solid rgba(143, 176, 218, .14); padding-block-start: 12px; }
.keys summary { cursor: pointer; color: var(--lightblue); font-size: 15px; list-style: none; display: flex; gap: 8px; align-items: center; }
.keys summary::-webkit-details-marker { display: none; }
.keys summary::before { content: "+"; font: 500 15px var(--mono); width: 1ch; }
.keys[open] summary::before { content: "−"; }
.keys ul { display: grid; grid-template-columns: 1fr 1fr; gap: 6px 16px; list-style: none; padding: 0; margin-block-start: 12px; }
@media (max-width: 480px) { .keys ul { grid-template-columns: 1fr; } }
.keys li { display: flex; align-items: center; gap: 10px; font-size: 14px; color: #C9D2E0; }
.keys kbd { flex: none; min-width: 3.2em; padding: 2px 8px; border: 1px solid rgba(143, 176, 218, .3); border-radius: 8px;
  text-align: center; color: var(--paper); font: 500 12px/1.6 var(--mono); }

/* An empty shelf still says what will land there. */
.empty { display: flex; flex-direction: column; align-items: center; gap: 6px; text-align: center; padding: clamp(28px, 5vw, 48px); }
.empty .bi { font-size: 20px; }
.empty .bi .bi-2 { font-size: 13px; }
.empty .win-bar { align-self: stretch; }

@media (prefers-reduced-motion: reduce) { .cover img { transition: none; } }
