/* Every colour on the site is one of these nine, and every one of them is
   re-set further down for each season, so a season is a palette and nothing
   else. What is here is the default the page wears if the season is never
   worked out: the arcade's own purple and pumpkin. */
:root {
  --bg: #0b0613;
  --bg-glow: #2a1240;
  --bg-raise: #1a0f2a;
  --ink: #fff3e2;
  --ink-soft: #cdbfdc;
  --accent: #ff9a3d;
  --accent-deep: #e0691a;
  --edge: #3d2456;
  /* Ink for the one place words sit on --accent: the button on the 404. */
  --on-accent: #2a1240;

  /* The seasonal dressing: the emoji beside the name, the line under the
     strapline, and the three things that drift through the header. With no
     season known there is nothing to dress for, so the name keeps the
     arcade's own joystick and the rest of it is empty. */
  --mark: "🕹️";
  --season-note: "";
  --flake-a: "";
  --flake-b: "";
  --flake-c: "";
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  background: radial-gradient(circle at 50% 0%, var(--bg-glow) 0%, var(--bg) 60%) fixed;
  color: var(--ink);
  font-family: "Trebuchet MS", "Comic Sans MS", system-ui, sans-serif;
  -webkit-text-size-adjust: 100%;
}

a { color: inherit; }

/* The header holds the drifting motif, so it is the thing that positions
   and clips it: a piece that wanders past an edge is simply cut off. */
.masthead {
  position: relative;
  overflow: hidden;
  text-align: center;
  padding: 2rem 1rem 1rem;
}
/* The brand is the page's one <h1>, so the h1 defaults (a fat margin and a
   2em font size) are reset here and the look stays exactly as it was. */
.brand {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  margin: 0;
  text-decoration: none;
  font-size: clamp(1.8rem, 5vw, 2.8rem);
  font-weight: bold;
  color: var(--accent);
  text-shadow: 0 0.15em 0 var(--accent-deep);
}
.brand a {
  display: inline-flex;
  align-items: center;
  gap: inherit;
  color: inherit;
  text-decoration: none;
}
/* Everything the header says sits above the motif drifting behind it. It is
   positioned and these are not, which without this would paint the leaves
   over the words rather than behind them. */
.brand,
.strap,
.season-note {
  position: relative;
  z-index: 1;
}
/* The emoji is a --mark rather than a character in the HTML, so that the
   season changes it without a line of JavaScript touching the page. */
.brand-mark { font-size: 1.1em; }
.brand-mark::before { content: var(--mark); }
.strap {
  margin: 0.5rem 0 0;
  color: var(--ink-soft);
}

/* The season said out loud, under the strapline. It is decoration, and it
   only appears once a season is known, so it is a --season-note rather than
   words in the HTML that would be wrong eleven months of the year. */
.season-note {
  display: none;
  margin: 0.8rem 0 0;
  color: var(--ink-soft);
  font-size: 0.85rem;
}
:root[data-season] .season-note {
  display: block;
}
.season-note::before {
  content: var(--season-note);
  display: inline-block;
  padding: 0.15rem 0.8rem;
  border-radius: 1rem;
  background: var(--bg-raise);
  border: 0.1rem solid var(--edge);
}

main {
  max-width: 64rem;
  margin: 0 auto;
  padding: 0 1rem 2rem;
}

.games h2,
.about h2,
.faq h2 {
  font-size: 1.4rem;
  margin: 1.5rem 0 1rem;
}

.game-grid {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(16rem, 1fr));
  gap: 1.2rem;
}

/* The tiles in a row are as tall as the tallest, so the row of cards has one
   straight bottom edge whatever the length of a description. */
.game-tile {
  display: flex;
}
.game-tile a {
  display: flex;
  flex-direction: column;
  width: 100%;
  background: var(--bg-raise);
  border: 0.2rem solid var(--edge);
  border-radius: 1rem;
  overflow: hidden;
  text-decoration: none;
  transition: transform 120ms ease, border-color 120ms ease;
}
.game-tile a:hover,
.game-tile a:focus-visible {
  transform: translateY(-0.2rem);
  border-color: var(--accent);
  outline: none;
}
.game-tile img {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 10;
  object-fit: cover;
  background: var(--bg);
}
.game-tile .tile-body {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  padding: 0.9rem 1rem 1rem;
}
.game-tile h3 {
  margin: 0 0 0.3rem;
  font-size: 1.2rem;
  color: var(--accent);
}
.game-tile p {
  margin: 0;
  color: var(--ink-soft);
  font-size: 0.95rem;
}
/* The search-engine description. Smaller and quieter than the tagline, which
   is the line a child's grown-up reads first. */
.game-tile .tile-body .desc {
  margin: 0.4rem 0 0.6rem;
  font-size: 0.85rem;
  color: var(--ink-soft);
  opacity: 0.85;
}
/* margin-top: auto in the flex column pins the badge to the bottom of the
   card, so every tile in a row lines its ages up on the same line. */
.game-tile .ages {
  display: inline-block;
  margin-top: auto;
  padding: 0.1rem 0.6rem;
  border-radius: 1rem;
  background: var(--edge);
  font-size: 0.8rem;
}

/* The two blocks of words on the page. A comfortable measure and a little
   more line height than the tiles, because these are read, not scanned. */
.about,
.faq {
  margin: 2.5rem 0 0;
}
.about p {
  margin: 0 0 0.9rem;
  max-width: 44rem;
  line-height: 1.6;
  color: var(--ink-soft);
}
.about p:last-child {
  margin-bottom: 0;
}

.faq details {
  background: var(--bg-raise);
  border: 0.15rem solid var(--edge);
  border-radius: 0.8rem;
  margin: 0 0 0.7rem;
  overflow: hidden;
}
.faq details[open] {
  border-color: var(--accent);
}
/* Big enough to hit with a thumb, and obviously a control: the marker turns
   with the panel and the whole row is the target. */
.faq summary {
  padding: 0.9rem 1rem;
  min-height: 2.75rem;
  display: flex;
  align-items: center;
  gap: 0.6rem;
  cursor: pointer;
  font-weight: bold;
  color: var(--ink);
  list-style: none;
}
.faq summary::-webkit-details-marker {
  display: none;
}
.faq summary::before {
  content: "+";
  flex: 0 0 auto;
  width: 1.4rem;
  height: 1.4rem;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: var(--edge);
  color: var(--accent);
  font-size: 1.1rem;
  line-height: 1;
}
.faq details[open] summary::before {
  content: "\2212";
}
.faq summary:hover,
.faq summary:focus-visible {
  color: var(--accent);
  outline: none;
}
.faq summary:focus-visible {
  box-shadow: inset 0 0 0 0.15rem var(--accent);
}
.faq details p {
  margin: 0;
  padding: 0 1rem 1rem;
  max-width: 44rem;
  line-height: 1.6;
  color: var(--ink-soft);
}

.ad {
  margin: 1.5rem 0;
}
.ad-placeholder {
  min-height: 5.6rem;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px dashed var(--edge);
  border-radius: 0.6rem;
  color: var(--ink-soft);
  font-size: 0.8rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

.footer {
  text-align: center;
  padding: 1rem;
  color: var(--ink-soft);
  font-size: 0.85rem;
}
.footer p {
  margin: 0 0 0.4rem;
}
.footer p:last-child {
  margin-bottom: 0;
}
.footer a {
  color: var(--ink-soft);
}

/* The 404 and privacy pages: one column of prose under the same masthead. */
.page {
  max-width: 44rem;
}
.page h2 {
  font-size: 1.4rem;
  margin: 1.5rem 0 1rem;
}
.page h3 {
  font-size: 1.05rem;
  margin: 1.6rem 0 0.4rem;
  color: var(--accent);
}
.page p,
.page li {
  line-height: 1.6;
  color: var(--ink-soft);
}
.page a {
  color: var(--accent);
}
.page-lost {
  text-align: center;
}
/* The one picture on the 404 page: big enough to read as a picture. */
.lost-mark {
  margin: 1rem 0 0;
  font-size: 3rem;
  line-height: 1;
}
/* Beats the .page a colour above, which would otherwise paint the label the
   same orange as the button. */
.page a.home-link {
  display: inline-block;
  margin-top: 1rem;
  padding: 0.7rem 1.4rem;
  border-radius: 1rem;
  background: var(--accent);
  border: 0.2rem solid var(--accent-deep);
  color: var(--on-accent);
  font-weight: bold;
  text-decoration: none;
}
.page a.home-link:hover,
.page a.home-link:focus-visible {
  background: var(--ink);
  outline: none;
}
kbd {
  padding: 0 0.3em;
  border: 1px solid var(--edge);
  border-radius: 0.3em;
  font-family: inherit;
}

/* ---------------------------------------------------------------------------
   The seasons

   site/js/season.js works out the month and puts it on <html> as, say,
   data-season="fall". Everything below is what that attribute means: six
   palettes, the emoji beside the name, the line under the strapline, and the
   three things that drift through the header. Nothing else in the site knows
   which season it is, so a season is changed here and nowhere else.

   Every palette is dark, because the arcade is dark and a child's eye should
   land on the game tiles rather than the page. What moves between them is the
   hue: purple for Halloween, amber for autumn, blue for winter, green and
   blossom for spring, sea and sunshine for summer, evergreen and gold for
   Christmas.
   ------------------------------------------------------------------------ */

/* The motif. The header clips it, so a piece is only ever a suggestion of
   weather at the edge of the page; it is aria-hidden and cannot be tapped. */
.season-sky {
  position: absolute;
  inset: 0;
  z-index: 0;
  overflow: hidden;
  pointer-events: none;
}
.season-sky span {
  position: absolute;
  top: 0;
  left: var(--x, 50%);
  font-size: var(--size, 1.1rem);
  line-height: 1;
  opacity: 0;
  animation: season-fall var(--span, 12s) linear var(--wait, 0s) infinite;
}
/* Three glyphs to a season, handed out along the row so no two neighbours
   are the same thing. */
.season-sky span::before { content: var(--flake-a); }
.season-sky span:nth-child(3n + 2)::before { content: var(--flake-b); }
.season-sky span:nth-child(3n)::before { content: var(--flake-c); }

/* Leaves, petals and snow come down. */
@keyframes season-fall {
  0% { transform: translate3d(0, -2.5rem, 0) rotate(0deg); opacity: 0; }
  12% { opacity: 0.5; }
  85% { opacity: 0.5; }
  100% { transform: translate3d(1.6rem, 15rem, 0) rotate(170deg); opacity: 0; }
}
/* Bats and butterflies do not: they cross the header instead, starting just
   off the left edge, so right: 100% rather than a left of their own. */
:root[data-season="halloween"] .season-sky span,
:root[data-season="summer"] .season-sky span {
  left: auto;
  right: 100%;
  top: var(--y, 40%);
  animation-name: season-drift;
}
@keyframes season-drift {
  0% { transform: translate3d(0, 0, 0) rotate(-8deg); opacity: 0; }
  12% { opacity: 0.5; }
  50% { transform: translate3d(50vw, -1.2rem, 0) rotate(8deg); }
  85% { opacity: 0.5; }
  100% { transform: translate3d(calc(100vw + 5rem), 0.6rem, 0) rotate(-8deg); opacity: 0; }
}
/* Asked for stillness, the header is still. There is nothing in the motif
   that the page needs, so it simply is not drawn. */
@media (prefers-reduced-motion: reduce) {
  .season-sky { display: none; }
}

/* September and November. */
:root[data-season="fall"] {
  --bg: #140b06;
  --bg-glow: #3c210d;
  --bg-raise: #24150c;
  --ink: #fff2e0;
  --ink-soft: #e0c6a6;
  --accent: #ffae4d;
  --accent-deep: #c05a1a;
  --edge: #4a2d15;
  --on-accent: #2a1608;
  --mark: "🍁";
  --season-note: "🍁 The leaves are falling";
  --flake-a: "🍂";
  --flake-b: "🍁";
  --flake-c: "🌰";
}

/* October, all of it. The arcade's own colours, because this is the palette
   the site was drawn in to begin with. */
:root[data-season="halloween"] {
  --bg: #0b0613;
  --bg-glow: #2a1240;
  --bg-raise: #1a0f2a;
  --ink: #fff3e2;
  --ink-soft: #cdbfdc;
  --accent: #ff9a3d;
  --accent-deep: #e0691a;
  --edge: #3d2456;
  --on-accent: #2a1240;
  --mark: "🎃";
  --season-note: "🎃 It is Halloween";
  --flake-a: "🦇";
  --flake-b: "✨";
  --flake-c: "🦇";
}

/* December. Evergreen and gold; the red stays on the tree. */
:root[data-season="christmas"] {
  --bg: #08150f;
  --bg-glow: #123f24;
  --bg-raise: #10251a;
  --ink: #fff6ea;
  --ink-soft: #cddcc9;
  --accent: #ffd97a;
  --accent-deep: #b8863a;
  --edge: #1f4830;
  --on-accent: #16240f;
  --mark: "🎄";
  --season-note: "🎄 Merry Christmas";
  --flake-a: "❄️";
  --flake-b: "⭐";
  --flake-c: "❄️";
}

/* January, February and March. */
:root[data-season="winter"] {
  --bg: #060d18;
  --bg-glow: #14345c;
  --bg-raise: #102138;
  --ink: #f0f7ff;
  --ink-soft: #bcd3ea;
  --accent: #86dcff;
  --accent-deep: #2f86b8;
  --edge: #22456e;
  --on-accent: #06202f;
  --mark: "⛄";
  --season-note: "❄️ Wrapped up for winter";
  --flake-a: "❄️";
  --flake-b: "❄";
  --flake-c: "❄️";
}

/* April, May and June. */
:root[data-season="spring"] {
  --bg: #08150c;
  --bg-glow: #1a4a26;
  --bg-raise: #12271a;
  --ink: #f3ffee;
  --ink-soft: #c3ddc0;
  --accent: #ffb3d9;
  --accent-deep: #d4568f;
  --edge: #2b5233;
  --on-accent: #330f20;
  --mark: "🌷";
  --season-note: "🌷 Everything is growing";
  --flake-a: "🌸";
  --flake-b: "🌼";
  --flake-c: "🍃";
}

/* July and August. */
:root[data-season="summer"] {
  --bg: #041318;
  --bg-glow: #0d4859;
  --bg-raise: #0b2833;
  --ink: #f0fdff;
  --ink-soft: #b3d6e0;
  --accent: #ffd447;
  --accent-deep: #d98f1c;
  --edge: #174a5c;
  --on-accent: #2b2305;
  --mark: "🏖️";
  --season-note: "🦋 Out in the sunshine";
  --flake-a: "🦋";
  --flake-b: "✨";
  --flake-c: "🦋";
}
