/* ==========================================================================
   World Geography Games — design system
   Tokens, reset, layout primitives, header, footer, buttons, cards, ads.
   ========================================================================== */

/* --- Tokens: light (default) ------------------------------------------- */
:root {
  --primary: #2563eb;
  --primary-dark: #1d4ed8;
  --primary-soft: #dbeafe;
  --on-primary: #ffffff;

  --background: #f8fafc;
  --surface: #ffffff;
  --surface-secondary: #f1f5f9;

  --text: #0f172a;
  --text-secondary: #64748b;

  --success: #16a34a;
  --success-soft: #dcfce7;
  --error: #dc2626;
  --error-soft: #fee2e2;
  --warning: #f59e0b;
  --purple: #7c3aed;

  --border: #e2e8f0;

  /* Map games: land must read lighter than sea in both themes. */
  --map-sea: #dbeafe;
  --map-land: #ffffff;
  --map-line: #94a3b8;
  --map-inert: #eef2f7;
  --scroll-shadow: rgba(15, 23, 42, .28);

  --shadow-sm: 0 1px 2px rgba(15, 23, 42, .06);
  --shadow: 0 4px 12px rgba(15, 23, 42, .07);
  --shadow-lg: 0 12px 32px rgba(15, 23, 42, .10);

  --radius-sm: 8px;
  --radius: 12px;
  --radius-lg: 16px;
  --radius-xl: 20px;

  --header-height: 64px;
  --wrap: 1120px;

  --font: "Inter", system-ui, -apple-system, "Segoe UI", Roboto, Arial, sans-serif;

  color-scheme: light;
}

/* --- Tokens: dark ------------------------------------------------------- */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --primary: #60a5fa;
    --primary-dark: #3b82f6;
    --primary-soft: #1e3a5f;
    --on-primary: #0b1220;

    --background: #0f172a;
    --surface: #1e293b;
    --surface-secondary: #334155;

    --text: #f8fafc;
    --text-secondary: #94a3b8;

    --success: #4ade80;
    --success-soft: #14532d;
    --error: #f87171;
    --error-soft: #4c1d1d;
    --warning: #fbbf24;
    --purple: #a78bfa;

    --border: #334155;

    --map-sea: #0b1220;
    --map-land: #3f5068;
    --map-line: #64748b;
    --map-inert: #1c2740;
    --scroll-shadow: rgba(0, 0, 0, .65);

    --shadow-sm: 0 1px 2px rgba(0, 0, 0, .3);
    --shadow: 0 4px 12px rgba(0, 0, 0, .35);
    --shadow-lg: 0 12px 32px rgba(0, 0, 0, .45);

    color-scheme: dark;
  }
}

:root[data-theme="dark"] {
  --primary: #60a5fa;
  --primary-dark: #3b82f6;
  --primary-soft: #1e3a5f;
  --on-primary: #0b1220;

  --background: #0f172a;
  --surface: #1e293b;
  --surface-secondary: #334155;

  --text: #f8fafc;
  --text-secondary: #94a3b8;

  --success: #4ade80;
  --success-soft: #14532d;
  --error: #f87171;
  --error-soft: #4c1d1d;
  --warning: #fbbf24;
  --purple: #a78bfa;

  --border: #334155;

  --map-sea: #0b1220;
  --map-land: #3f5068;
  --map-line: #64748b;
  --map-inert: #1c2740;
  --scroll-shadow: rgba(0, 0, 0, .65);

  --shadow-sm: 0 1px 2px rgba(0, 0, 0, .3);
  --shadow: 0 4px 12px rgba(0, 0, 0, .35);
  --shadow-lg: 0 12px 32px rgba(0, 0, 0, .45);

  color-scheme: dark;
}

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

* { margin: 0; padding: 0; }

/* The UA rule for [hidden] is `display: none` at the lowest specificity, so any
   component that sets `display` silently defeats it — an element toggled with
   `el.hidden = true` stays on screen. That has bitten this codebase three times
   (.progress-dots, .review-callout, .results-new-best), so it is stated once,
   globally, rather than patched per component. */
[hidden] { display: none !important; }

html {
  scroll-behavior: smooth;
  -webkit-text-size-adjust: 100%;
}

body {
  font-family: var(--font);
  background: var(--background);
  color: var(--text);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  transition: background-color .2s ease, color .2s ease;
}

img,
svg { max-width: 100%; display: block; }

a {
  color: var(--primary);
  text-decoration: none;
}

a:hover { text-decoration: underline; }

ul, ol { list-style: none; }

button,
input,
select,
textarea {
  font: inherit;
  color: inherit;
}

/* Visible focus for keyboard users on every interactive element. */
:focus-visible {
  outline: 3px solid var(--primary);
  outline-offset: 2px;
  border-radius: 4px;
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
}

/* --- Typography --------------------------------------------------------- */
h1, h2, h3, h4 {
  line-height: 1.2;
  font-weight: 800;
  letter-spacing: -.02em;
}

h1 { font-size: clamp(2rem, 5vw, 3.25rem); }
h2 { font-size: clamp(1.5rem, 3vw, 2.125rem); }
h3 { font-size: 1.25rem; }

p { max-width: 70ch; }

.lead {
  font-size: 1.125rem;
  color: var(--text-secondary);
}

.muted { color: var(--text-secondary); }

.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

.skip-link {
  position: absolute;
  left: 8px;
  top: -60px;
  z-index: 100;
  background: var(--primary);
  color: var(--on-primary);
  padding: 10px 16px;
  border-radius: var(--radius-sm);
  transition: top .15s ease;
}

.skip-link:focus { top: 8px; }

/* --- Layout ------------------------------------------------------------- */
.wrap {
  width: 100%;
  max-width: var(--wrap);
  margin-inline: auto;
  padding-inline: 20px;
}

main { flex: 1 0 auto; }

/* padding-block, not the shorthand: many elements are `class="section wrap"`,
   and `padding: 56px 0` would zero the inline padding .wrap sets — same
   specificity, so whichever rule comes last would win. */
.section { padding-block: 56px; }

.section-narrow { max-width: 760px; }

.section-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 24px;
  flex-wrap: wrap;
}

.section-head p { margin-top: 6px; }

/* Section links ("All games →") are primary navigation on mobile. */
.section-head a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  font-weight: 600;
}

/* --- Header / navigation ------------------------------------------------ */
.site-header {
  position: sticky;
  top: 0;
  z-index: 40;
  background: color-mix(in srgb, var(--surface) 88%, transparent);
  backdrop-filter: blur(12px);
  border-bottom: 1px solid var(--border);
}

.nav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  height: var(--header-height);
}

.brand {
  display: flex;
  align-items: center;
  gap: 10px;
  /* The logo is a link, so it needs a real tap target, not just text height. */
  min-height: 44px;
  font-weight: 800;
  font-size: 1.0625rem;
  color: var(--text);
  white-space: nowrap;
}

.brand:hover { text-decoration: none; }
.brand .globe { font-size: 1.5rem; line-height: 1; }
.brand-short { display: none; }

.nav-links {
  display: flex;
  align-items: center;
  gap: 4px;
  margin-left: auto;
}

.nav-links a {
  color: var(--text-secondary);
  font-weight: 600;
  font-size: .9375rem;
  padding: 8px 12px;
  border-radius: var(--radius-sm);
}

.nav-links a:hover {
  color: var(--text);
  background: var(--surface-secondary);
  text-decoration: none;
}

.nav-links a[aria-current="page"] {
  color: var(--primary);
  background: var(--primary-soft);
}

.nav-actions {
  display: flex;
  align-items: center;
  gap: 8px;
}

.icon-btn {
  width: 44px;
  height: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  cursor: pointer;
  font-size: 1.125rem;
  line-height: 1;
  transition: background-color .15s ease, border-color .15s ease;
}

.icon-btn:hover { background: var(--surface-secondary); }

/* Icon buttons draw SVGs, not emoji: emoji cannot take a colour, render
   differently on every platform, and the theme toggle in particular looked
   like a different control on Windows than on iOS. */
.icon-btn svg {
  width: 20px;
  height: 20px;
  fill: none;
  stroke: var(--text-secondary);
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  transition: stroke .15s ease;
}

.icon-btn:hover svg { stroke: var(--text); }

/* Which state each button shows is pure CSS, so the correct icon is painted
   on the first frame — before any script runs. */
.icon-sun { display: none; }
:root[data-theme="dark"] .icon-sun { display: block; }
:root[data-theme="dark"] .icon-moon { display: none; }

.icon-close { display: none; }
.nav-toggle[aria-expanded="true"] .icon-menu { display: none; }
.nav-toggle[aria-expanded="true"] .icon-close { display: block; }

.nav-toggle { display: none; }

/* Mobile drawer — a sibling of <header>, never a child of it. */
.nav-drawer {
  position: fixed;
  inset: var(--header-height) 0 0 0;
  background: var(--background);
  padding: 8px 20px calc(40px + env(safe-area-inset-bottom));
  overflow-y: auto;
  overscroll-behavior: contain;
  z-index: 39;
  display: none;
}

.nav-drawer[data-open="true"] { display: block; }

.nav-drawer a {
  display: flex;
  align-items: center;
  min-height: 56px;
  padding: 12px 4px;
  font-size: 1.125rem;
  font-weight: 600;
  color: var(--text);
  border-bottom: 1px solid var(--border);
}

.nav-drawer a:last-child { border-bottom: 0; }
.nav-drawer a:hover { color: var(--primary); text-decoration: none; }
.nav-drawer a[aria-current="page"] { color: var(--primary); }

body[data-nav-open="true"] { overflow: hidden; }

/* --- Search ------------------------------------------------------------- */
.search {
  position: relative;
  flex: 0 1 240px;
}

.search input {
  width: 100%;
  height: 44px;
  padding: 0 14px 0 38px;
  background: var(--surface-secondary);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  color: var(--text);
}

.search input::placeholder { color: var(--text-secondary); }

/* An SVG rather than an emoji: emoji render differently on every platform,
   cannot take a colour, and sit on the text baseline rather than centring. */
.search-icon {
  position: absolute;
  left: 13px;
  top: 50%;
  transform: translateY(-50%);
  width: 17px;
  height: 17px;
  fill: none;
  stroke: var(--text-secondary);
  stroke-width: 2;
  stroke-linecap: round;
  pointer-events: none;
  transition: stroke .15s ease;
}

.search:focus-within .search-icon { stroke: var(--primary); }

.search-results {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  right: 0;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-lg);
  max-height: 340px;
  overflow-y: auto;
  z-index: 50;
}

.search-results:empty { display: none; }

.search-results a {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 14px;
  color: var(--text);
  border-bottom: 1px solid var(--border);
}

.search-results a:last-child { border-bottom: 0; }
.search-results a:hover { background: var(--surface-secondary); text-decoration: none; }
.search-results .flag { font-size: 1.375rem; }
.search-results .meta { font-size: .8125rem; color: var(--text-secondary); }
.search-results .empty { padding: 14px; color: var(--text-secondary); font-size: .9375rem; }

/* --- Buttons ------------------------------------------------------------ */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: 48px;
  padding: 12px 24px;
  border: 1px solid transparent;
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--text);
  font-weight: 700;
  font-size: 1rem;
  cursor: pointer;
  text-align: center;
  transition: transform .12s ease, background-color .15s ease, box-shadow .15s ease;
}

.btn:hover { text-decoration: none; }
.btn:active { transform: translateY(1px); }

/* Icons inherit the button's text colour, so they stay correct on every
   variant and in both themes without a per-variant rule. */
.icon {
  width: 20px;
  height: 20px;
  flex-shrink: 0;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.icon .solid {
  fill: currentColor;
  stroke: none;
}

.btn-lg .icon { width: 22px; height: 22px; }

/* The daily button flips to "Play Again" once today's round is done. Both
   icons ship in the markup and CSS picks one, so the script never has to
   rewrite the button's contents. */
.icon-refresh { display: none; }
[data-done="true"] .icon-play { display: none; }
[data-done="true"] .icon-refresh { display: block; }

.btn-primary {
  background: var(--primary);
  color: var(--on-primary);
  box-shadow: var(--shadow);
}

.btn-primary:hover { background: var(--primary-dark); }

.btn-secondary {
  background: var(--surface);
  border-color: var(--border);
  color: var(--text);
}

.btn-secondary:hover { background: var(--surface-secondary); }

.btn-ghost {
  background: transparent;
  border-color: var(--border);
}

.btn-ghost:hover { background: var(--surface-secondary); }

.btn-lg {
  min-height: 58px;
  padding: 16px 36px;
  font-size: 1.125rem;
  border-radius: var(--radius-lg);
}

.btn-block { width: 100%; }

.btn-row {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
}

/* --- Cards -------------------------------------------------------------- */
.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 24px;
  box-shadow: var(--shadow-sm);
}

.card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: 20px;
}

/* --- Tables (SEO content pages) ----------------------------------------- */
.table-wrap {
  overflow-x: auto;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  /* Scroll shadows: the two `local` layers sit on the content and slide away
     at each end, so the `scroll` shadow layers are only visible while there is
     more table to reach. Without this, a cut-off column on a phone reads as a
     broken layout rather than a scrollable one. */
  background:
    linear-gradient(to right, var(--surface) 30%, transparent) left center / 40px 100% no-repeat,
    linear-gradient(to left, var(--surface) 30%, transparent) right center / 40px 100% no-repeat,
    radial-gradient(farthest-side at 0 50%, var(--scroll-shadow), transparent) left center / 16px 100% no-repeat,
    radial-gradient(farthest-side at 100% 50%, var(--scroll-shadow), transparent) right center / 16px 100% no-repeat,
    var(--surface);
  background-attachment: local, local, scroll, scroll, scroll;
  -webkit-overflow-scrolling: touch;
}

table {
  width: 100%;
  border-collapse: collapse;
  font-size: .9375rem;
}

th, td {
  text-align: left;
  padding: 12px 16px;
  border-bottom: 1px solid var(--border);
  white-space: nowrap;
}

th {
  background: var(--surface-secondary);
  font-weight: 700;
  position: sticky;
  top: 0;
}

tbody tr:last-child td { border-bottom: 0; }
tbody tr:hover { background: var(--surface-secondary); }

/* --- Ads ---------------------------------------------------------------- */
/* Space is reserved up front so live ads cannot shift the layout. */
.ad-container {
  width: 100%;
  /* Space is reserved before the ad loads. Responsive units run taller on
     narrow screens (rectangles) than wide ones (leaderboards), so the
     reservation follows that rather than being a single number. */
  min-height: 130px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  margin: 24px 0;
  background: var(--surface-secondary);
  border: 1px dashed var(--border);
  border-radius: var(--radius);
  color: var(--text-secondary);
  font-size: .75rem;
  letter-spacing: .08em;
  text-transform: uppercase;
}

/* Live slots reserve the real height; placeholders stay compact in dev. */
.ad-container[data-ad] {
  min-height: 290px;
  border: 0;
  background: transparent;
  display: block;
  padding-top: 4px;
}

.ad-container[data-ad] .ad-label {
  display: block;
  text-align: center;
  margin-bottom: 6px;
}

.ad-container[data-ad] .adsbygoogle { min-height: 260px; }

/* Measured against live fill: a responsive unit serves ~280px tall in this
   column at every breakpoint, so the reservation does not shrink on desktop.
   Over-reserving costs whitespace; under-reserving costs CLS, which is the
   one that hurts rankings. */

/* --- Side rail ----------------------------------------------------------- */
/* A responsive unit takes its shape from its container, so the tall ad needs
   a narrow column. Only wide screens have room for one. */
.has-rail { display: block; }
.has-rail-main { min-width: 0; }
.ad-rail { display: none; }

@media (min-width: 1240px) {
  :root { --wrap: 1400px; }

  .has-rail {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 300px;
    gap: 40px;
    align-items: start;
  }

  /* The page bodies carry their own .wrap elements; inside the grid column
     they must not re-apply a max-width or a second gutter. */
  .has-rail-main .wrap {
    max-width: none;
    padding-inline: 0;
  }

  .ad-rail { display: block; }

  .ad-rail-sticky {
    position: sticky;
    top: calc(var(--header-height) + 24px);
  }

  .ad-rail .ad-label {
    display: block;
    text-align: center;
    font-size: .75rem;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--text-secondary);
    margin-bottom: 6px;
  }

  .ad-container-rail {
    min-height: 600px;
    margin: 0;
    border: 0;
    background: transparent;
    display: block;
  }

  .ad-container-rail .adsbygoogle {
    min-height: 600px;
    width: 300px;
  }
}

/* --- Footer ------------------------------------------------------------- */
.site-footer {
  flex-shrink: 0;
  margin-top: 48px;
  border-top: 1px solid var(--border);
  background: var(--surface);
  padding: 48px 0 24px;
}

.footer-grid {
  display: grid;
  grid-template-columns: 1.4fr repeat(3, 1fr);
  gap: 32px;
}

.footer-brand .brand { margin-bottom: 10px; }
.footer-brand p { color: var(--text-secondary); font-size: .9375rem; }

.site-footer h3 {
  font-size: .8125rem;
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--text-secondary);
  margin-bottom: 12px;
}

.site-footer li { margin-bottom: 2px; }

.site-footer li a {
  display: inline-block;
  /* 24px of line box + 20px padding = the 44px minimum target. */
  padding: 10px 0;
  color: var(--text);
  font-size: .9375rem;
}

.footer-bottom {
  margin-top: 40px;
  padding-top: 20px;
  border-top: 1px solid var(--border);
  color: var(--text-secondary);
  font-size: .875rem;
  display: flex;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
}

/* --- Misc --------------------------------------------------------------- */
.pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 12px;
  border-radius: 999px;
  background: var(--surface-secondary);
  border: 1px solid var(--border);
  font-size: .8125rem;
  font-weight: 600;
  color: var(--text-secondary);
}

.breadcrumbs {
  font-size: .875rem;
  color: var(--text-secondary);
  padding-top: 24px;
}

.breadcrumbs a { color: var(--text-secondary); }
.breadcrumbs span { margin: 0 6px; }
