/* ==========================================================
   OpenPlay website styles (shared by index.html and roadmap.html)
   The colours, font, corners and glossy panels match the OpenPlay app
   (see the app's src/styles/base.css).

   Contents:
   1. Colours and sizes (variables)
   2. Page defaults
   3. Shared pieces
   4. Header
   5. Introduction
   6. Download button
   7. Slideshow (coverflow)
   8. Features
   9. About
   10. Roadmap page
   11. Footer
   12. Download mini-game
   13. Glitch effect
   14. Animation and reduced motion
   15. Tablet and phone layouts
   ========================================================== */


/* ===== 1. Colours and sizes (variables) =====
   Variables are named values we set once and reuse everywhere, with var(--name).
   These are the same names and colours the OpenPlay app uses. */
:root {
  /* Surfaces, darkest to lightest */
  --window: #151b22;                       /* Page background */
  --panel: #1d242d;                        /* Solid panels */
  --button: rgba(255, 255, 255, 0.06);     /* See-through white for buttons and tags */
  --button-hover: rgba(255, 255, 255, 0.11);
  --highlight: #2e3552;                    /* Selected things, like the current page (the app's highlight) */

  /* Text */
  --text: #e0e2e5;
  --muted: #a7afb7;

  /* Lines and accents */
  --border: rgba(255, 255, 255, 0.07);       /* Soft edge around panels */
  --border-strong: rgba(255, 255, 255, 0.16);
  --divider: rgba(76, 88, 117, 0.72);
  --accent: #7c8cff;                         /* The app's blue accent (base.css --accent) */
  --accent-text: #aab5ff;                    /* Lighter blue, easier to read as text */
  --accent-soft: rgba(124, 140, 255, 0.16);  /* Blue as a background tint */
  --play: #28aa3d;                           /* The app's green Play button */
  --play-hover: #31b847;
  --play-ink: #0b210f;                       /* Dark text that's easy to read on the green */

  /* Background effects: a charcoal blue, taken from the app's blue-grey dividers */
  --glow: rgba(64, 84, 120, 0.45);            /* The soft haze at the top and under the slideshow */
  --grid-line: rgba(130, 150, 185, 0.07);     /* The faint isometric grid lines */

  /* Glossy panels: a faint light line along the top edge, plus a soft shadow */
  --gloss: inset 0 1px 0 rgba(255, 255, 255, 0.05);
  --shadow: 0 8px 24px rgba(0, 0, 0, 0.22);

  --radius: 12px;        /* Panels */
  --radius-small: 8px;   /* Buttons */

  /* Inter is the app's font. Segoe UI (built into Windows) is the backup. */
  --font: "Inter", "Segoe UI", system-ui, sans-serif;
}


/* ===== 2. Page defaults ===== */
*,
*::before,
*::after {
  box-sizing: border-box; /* Includes padding and borders in an element's width */
}

/* Smooth scrolling when a menu link is clicked, unless the visitor asked for less motion */
@media (prefers-reduced-motion: no-preference) {
  html {
    scroll-behavior: smooth;
  }
}

body {
  position: relative; /* So the background layer (below) is placed from the top of the page */
  margin: 0;

  background-color: var(--window);
  color: var(--text);

  font-family: var(--font);
  font-size: 16px;
  line-height: 1.6;
}

/* Background effects at the top of every page: a charcoal-blue glow and an isometric grid.
   ::before adds an extra layer to the body without any extra HTML. */
body::before {
  content: ""; /* Needed for ::before to show, even when empty */
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  z-index: -1; /* Sits behind all the page content */
  height: 900px;
  pointer-events: none; /* Clicks go straight through it */

  /* Several backgrounds stacked, separated by commas. The first one is on top. */
  background-image:
    /* 1. The glow: a wide oval of charcoal blue at the top that fades to see-through */
    radial-gradient(ellipse 70% 75% at 50% 0%, var(--glow), transparent 70%),
    /* 2 and 3. The grid: two sets of thin stripes at 30 and 150 degrees cross to make
       diamond shapes, the same angles as the 3D sides of the logo */
    repeating-linear-gradient(30deg, var(--grid-line) 0 1px, transparent 1px 40px),
    repeating-linear-gradient(150deg, var(--grid-line) 0 1px, transparent 1px 40px);

  /* mask-image fades the whole layer out: fully visible at the top middle,
     invisible towards the edges and the bottom */
  mask-image: radial-gradient(ellipse 75% 90% at 50% 0%, black 35%, transparent 80%);
}

h1,
h2,
h3,
h4,
p,
ul,
ol {
  margin: 0; /* We control all spacing ourselves */
}

h1,
h2,
h3,
h4 {
  font-weight: 700;
  line-height: 1.15;
  text-wrap: balance; /* Keeps wrapped headings visually balanced */
}

p {
  color: var(--muted);
}

img {
  display: block;
  max-width: 100%;
  height: auto;
}

a {
  color: inherit;
}

/* A clear outline when keyboard users Tab to a link */
a:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
}

/* Leaves space above a section when a link jumps to it, so the header doesn't cover it */
section {
  scroll-margin-top: 72px;
}


/* ===== 3. Shared pieces ===== */
.container {
  width: min(100% - 48px, 1160px); /* Leaves side space and limits the content width */
  margin: 0 auto; /* Centres the content */
}

/* Heading and short intro at the top of a section */
.section-heading {
  max-width: 620px;
  margin: 0 auto 44px;

  text-align: center;
}

.section-heading h2,
.about-text h2,
.roadmap h2,
.updates h2 {
  font-size: clamp(28px, 3.2vw, 38px); /* Grows with the screen, between 28px and 38px */
  letter-spacing: -0.8px;
}

.section-heading p {
  margin-top: 10px;

  font-size: 18px;
}

/* A glossy panel, the same style as the app's panels */
.feature,
.slide-screen {
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background-color: var(--panel);
  box-shadow: var(--gloss), var(--shadow); /* Two shadows, separated by a comma */
}


/* ===== 4. Header ===== */
.site-header {
  position: sticky; /* Stays stuck to the top of the screen while scrolling */
  top: 0;
  z-index: 20; /* Keeps it above the page, including the slideshow */

  border-bottom: 1px solid var(--border);
  background-color: rgba(21, 27, 34, 0.85); /* --window, slightly see-through */
  backdrop-filter: blur(12px); /* Blurs the page underneath, like frosted glass */
}

.header-inner {
  display: flex;
  align-items: center;
  justify-content: space-between; /* Logo on the left, menu on the right */
  min-height: 64px;
}

.brand {
  display: flex;
  align-items: center;
  gap: 10px;

  text-decoration: none;
}

.brand-logo {
  width: 30px;
}

.brand-name {
  font-size: 18px;
  font-weight: 700;
}

.nav-list {
  display: flex;
  gap: 4px;
  padding: 0;

  list-style: none;
}

.nav-link {
  display: block;
  padding: 8px 14px;

  border-radius: var(--radius-small);
  color: var(--muted);

  font-size: 15px;
  font-weight: 600;
  text-decoration: none;

  transition: background-color 0.15s ease, color 0.15s ease;
}

.nav-link:hover {
  background-color: var(--button-hover);
  color: var(--text);
}

/* The page you're on is highlighted, like the selected page in the app's sidebar.
   [aria-current="page"] picks links that have that attribute. */
.nav-link[aria-current="page"] {
  background-color: var(--highlight);
  color: var(--text);
}


/* ===== 5. Introduction ===== */
.intro {
  padding: 40px 0 72px;

  text-align: center;
}

/* A soft charcoal-blue glow behind the logo */
.intro-logo-wrap {
  display: grid;
  place-items: center; /* Centres the logo both ways */
  width: 220px;
  height: 220px;
  margin: 0 auto 4px;

  border-radius: 50%;
  background: radial-gradient(circle, var(--glow) 0%, transparent 70%);
}

.intro-logo {
  width: 150px;

  animation: logo-rise 0.9s ease-out both; /* See section 12 */
}

.intro h1 {
  font-size: clamp(48px, 7vw, 84px); /* Scales between a minimum and maximum size */
  line-height: 1;
  letter-spacing: -2.5px;
}

.tagline {
  margin-top: 14px;

  color: var(--text);

  font-size: clamp(22px, 2.6vw, 30px);
  font-weight: 600;
  line-height: 1.25;
  letter-spacing: -0.5px;
}

.intro-description {
  max-width: 34em;
  margin: 12px auto 0;

  font-size: 18px;
}

.download-note {
  margin-top: 12px;

  font-size: 14px;
}

/* The row of platform names */
.platform-list {
  display: flex;
  flex-wrap: wrap; /* Moves names onto a new line if there isn't room */
  justify-content: center;
  gap: 8px;
  margin-top: 32px;
  padding: 0;

  list-style: none;
}

.platform-list li {
  padding: 6px 14px;

  border: 1px solid var(--border);
  border-radius: 999px; /* A very big radius makes a pill shape */
  background-color: var(--button);
  color: var(--muted);

  font-size: 14px;
  font-weight: 500;
}


/* ===== 6. Download button ===== */
.download-button {
  display: inline-flex; /* Places the icon and text beside each other */
  align-items: center;
  justify-content: center;
  gap: 12px;
  max-width: 100%;
  min-height: 54px;
  margin-top: 32px;
  padding: 14px 30px;

  border-radius: 10px;
  background-color: var(--play);
  box-shadow: var(--gloss), var(--shadow);
  color: var(--play-ink);

  font-size: 17px;
  font-weight: 700;
  line-height: 1.4;
  text-decoration: none;

  transition: background-color 0.15s ease, transform 0.15s ease;
}

.download-button:hover {
  background-color: var(--play-hover);
  transform: translateY(-2px); /* Lifts the button up slightly */
}

.download-button:focus-visible {
  outline: 3px solid var(--text);
  outline-offset: 5px;
}

/* The small "download without playing" link under the big button */
.skip-game-link {
  display: block; /* Puts it on its own line, under the button */
  width: fit-content;
  margin: 12px auto 0; /* auto on the left and right centres it */

  color: var(--muted);
  font-size: 13px;
  text-decoration: underline;
  text-underline-offset: 3px; /* A little gap between the text and its underline */
}

.skip-game-link:hover {
  color: var(--text);
}

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

.download-icon {
  flex-shrink: 0;
  width: 24px;
  height: 24px;
}


/* ===== 7. Slideshow (coverflow) ===== */
.showcase {
  padding: 72px 0 80px;

  border-top: 1px solid var(--border);
}

.coverflow {
  position: relative; /* Lets us place the arrows on top */
  overflow: hidden; /* Cuts off slides that go past the edge of the page */
  padding: 8px 0 4px;

  --slide-width: min(640px, 70vw); /* How wide the middle slide is */
}

/* Spotlight: a soft charcoal-blue glow on the "floor" under the middle slide,
   as if it's lit from above. It sits behind the slides. */
.coverflow::before {
  content: "";
  position: absolute;
  top: calc(8px + var(--slide-width) * 9 / 16 - 70px); /* Just above the bottom edge of the middle slide */
  left: 50%;
  width: calc(var(--slide-width) * 1.5);
  height: 160px;

  transform: translateX(-50%); /* Centres it */
  background: radial-gradient(ellipse at center, var(--glow), transparent 70%);
  pointer-events: none;
}

/* Hide the radio buttons, but keep them usable with the keyboard
   (Tab to them, then use the arrow keys to change slide). */
.slide-radio {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}

/* Which slide is in the middle? --active is set to the checked slide's number.
   ~ means "a later brother or sister of", so this reaches .slides. */
#slide-1:checked ~ .slides { --active: 1; }
#slide-2:checked ~ .slides { --active: 2; }
#slide-3:checked ~ .slides { --active: 3; }
#slide-4:checked ~ .slides { --active: 4; }
#slide-5:checked ~ .slides { --active: 5; }
#slide-6:checked ~ .slides { --active: 6; }
#slide-7:checked ~ .slides { --active: 7; }

/* All slides sit in the same grid cell, stacked on top of each other */
.slides {
  display: grid;
  justify-items: center;
}

.slide {
  grid-area: 1 / 1; /* Row 1, column 1, so every slide is in the same spot */
  width: var(--slide-width);
  cursor: pointer;

  /* --offset: how far this slide is from the middle one: -3 to 3.
     mod() wraps around, so after slide 7 comes slide 1 again. */
  --offset: calc(mod(var(--i) - var(--active) + 10, 7) - 3);
  /* --distance: the same number without the minus sign (0 to 3) */
  --distance: max(var(--offset), -1 * var(--offset));

  /* Move it sideways, shrink it and fade it the further it is from the middle.
     The sideways step gets smaller for the slides at the back (58%, then 88% in total),
     so they peek out from behind the side slides instead of going off the page. */
  transform:
    translateX(calc(var(--offset) * (72% - var(--distance) * 14%)))
    scale(calc(1 - var(--distance) * 0.21));
  opacity: max(0, 1 - var(--distance) * 0.3); /* 1, then 0.7, then 0.4, then 0.1 */
  filter: brightness(calc(1 - var(--distance) * 0.2)); /* Darker further away */
  z-index: calc(10 - var(--distance)); /* The middle slide sits on top */

  transition: transform 0.5s ease, opacity 0.5s ease, filter 0.5s ease;
}

/* The picture area: 16:9, the shape of a widescreen screenshot */
.slide-screen {
  display: block;
  border-color: rgba(255, 255, 255, 0.12); /* A slightly brighter edge so faded slides still show their shape */
  aspect-ratio: 16 / 9;
  overflow: hidden;
}

/* The screenshots fill the frame */
.slide-screen img {
  width: 100%;
  height: 100%;
  object-fit: cover; /* Fills the frame without stretching, trimming the edges if needed */
}

/* The caption under each slide. Only the middle slide's caption shows. */
.slide-caption {
  display: block;
  margin-top: 18px;

  text-align: center;

  opacity: calc(1 - var(--distance)); /* 1 for the middle slide, 0 for the others */
  transition: opacity 0.3s ease;
}

.slide-title {
  display: block;

  font-size: 20px;
  font-weight: 700;
}

.slide-text {
  display: block;
  margin-top: 4px;

  color: var(--muted);
}

/* Arrows: placed at the middle of the slide's height, on each side of it */
.arrows {
  position: absolute;
  top: calc(8px + var(--slide-width) * 9 / 32); /* Half the slide's 16:9 height */
  left: 50%;
  display: flex;
  justify-content: space-between;
  width: calc(var(--slide-width) + 72px);

  z-index: 15; /* Above the slides */

  transform: translate(-50%, -50%); /* Centres the arrow row on that point */
  pointer-events: none; /* Clicks go through the gap between the arrows */
}

.arrow {
  display: none; /* Hidden until its slide is checked (below) */
  place-items: center;
  width: 48px;
  height: 48px;

  border: 1px solid var(--border-strong);
  border-radius: 50%;
  background-color: rgba(29, 36, 45, 0.85); /* --panel, slightly see-through */
  backdrop-filter: blur(8px);
  box-shadow: var(--shadow);
  cursor: pointer;
  pointer-events: auto;

  font-size: 30px;
  line-height: 1;

  transition: background-color 0.15s ease;
}

.arrow:hover {
  background-color: var(--highlight);
}

/* Show only the arrow pair that belongs to the checked slide */
#slide-1:checked ~ .arrows .arrows-1,
#slide-2:checked ~ .arrows .arrows-2,
#slide-3:checked ~ .arrows .arrows-3,
#slide-4:checked ~ .arrows .arrows-4,
#slide-5:checked ~ .arrows .arrows-5,
#slide-6:checked ~ .arrows .arrows-6,
#slide-7:checked ~ .arrows .arrows-7 {
  display: grid;
}

/* Dots */
.dots {
  display: flex;
  justify-content: center;
  gap: 10px;
  margin-top: 24px;
}

.dot {
  width: 10px;
  height: 10px;

  border-radius: 999px;
  background-color: var(--border-strong);
  cursor: pointer;

  transition: width 0.3s ease, background-color 0.3s ease;
}

.dot:hover {
  background-color: var(--muted);
}

/* The dot for the checked slide becomes a longer blue pill */
#slide-1:checked ~ .dots .dot-1,
#slide-2:checked ~ .dots .dot-2,
#slide-3:checked ~ .dots .dot-3,
#slide-4:checked ~ .dots .dot-4,
#slide-5:checked ~ .dots .dot-5,
#slide-6:checked ~ .dots .dot-6,
#slide-7:checked ~ .dots .dot-7 {
  width: 28px;
  background-color: var(--accent);
}

/* When a keyboard user is on the hidden radio buttons, outline the matching dot */
#slide-1:focus-visible ~ .dots .dot-1,
#slide-2:focus-visible ~ .dots .dot-2,
#slide-3:focus-visible ~ .dots .dot-3,
#slide-4:focus-visible ~ .dots .dot-4,
#slide-5:focus-visible ~ .dots .dot-5,
#slide-6:focus-visible ~ .dots .dot-6,
#slide-7:focus-visible ~ .dots .dot-7 {
  outline: 2px solid var(--text);
  outline-offset: 4px;
}


/* ===== 8. Features ===== */
.features {
  padding: 80px 0;

  border-top: 1px solid var(--border);
}

.feature-list {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr)); /* Three equal columns */
  gap: 18px;
  padding: 0;

  list-style: none;
}

.feature {
  padding: 28px 26px;
}

/* Hexagon behind each icon, to match the logo's shape.
   clip-path cuts the square into a hexagon using six corner points. */
.feature-icon-frame {
  display: grid;
  place-items: center;
  width: 56px;
  height: 60px;
  margin-bottom: 20px;

  background-color: var(--accent-soft);
  clip-path: polygon(50% 0, 100% 25%, 100% 75%, 50% 100%, 0 75%, 0 25%);
}

.feature-icon {
  width: 28px;
  height: 28px;

  color: var(--accent-text); /* SVG currentColor uses this colour for the icon lines */
}

.feature h3 {
  font-size: 19px;
}

.feature p {
  margin-top: 8px;

  font-size: 15px;
}


/* ===== 9. About ===== */
.about {
  padding: 80px 0 88px;

  border-top: 1px solid var(--border);
}

.about-inner {
  display: grid;
  grid-template-columns: 1.2fr 1fr;
  align-items: center;
  gap: 64px;
}

.about-text p {
  max-width: 48ch; /* ch = the width of one character, so lines stay easy to read */
  margin-top: 16px;

  font-size: 18px;
}

.check-list {
  padding: 0;

  list-style: none;
}

.check-list li {
  display: flex;
  align-items: flex-start; /* Ticks line up with the first line when text wraps */
  gap: 14px;
  padding: 18px 0;

  border-bottom: 1px solid var(--border-strong);

  font-size: 17px;
  font-weight: 500;
}

.check-list li:first-child {
  border-top: 1px solid var(--border-strong);
}

.check-icon {
  flex-shrink: 0;
  width: 24px;
  height: 24px;
  margin-top: 1px;

  color: var(--play);
}


/* ===== 10. Roadmap page ===== */
.page-intro {
  padding: 56px 0 8px;
}

.page-intro h1 {
  font-size: clamp(40px, 5vw, 60px);
  letter-spacing: -1.5px;
}

.page-intro p {
  max-width: 60ch;
  margin-top: 14px;

  font-size: 18px;
}

/* Quick links to each group and to Recent updates. flex-wrap lets them go onto a second line. */
.page-tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 28px;
  padding: 0;

  list-style: none;
}

.page-tabs a {
  display: block;
  padding: 7px 14px;

  border: 1px solid var(--border);
  border-radius: 999px;
  background-color: var(--button);
  color: var(--muted);

  font-size: 14px;
  font-weight: 600;
  text-decoration: none;

  transition: background-color 0.15s ease, color 0.15s ease;
}

.page-tabs a:hover {
  background-color: var(--button-hover);
  color: var(--text);
}

.roadmap {
  padding: 56px 0 24px;
}

/* One group: a glossy panel split into two columns,
   the group's name on the left and its features on the right */
.roadmap-group {
  display: grid;
  grid-template-columns: 280px 1fr;
  gap: 40px;
  margin-top: 20px;
  padding: 28px 32px;

  border: 1px solid var(--border);
  border-radius: var(--radius);
  background-color: var(--panel);
  box-shadow: var(--gloss), var(--shadow);
}

.roadmap h2 + .roadmap-group {
  margin-top: 28px;
}

.group-info .feature-icon-frame {
  margin-bottom: 16px;
}

.group-info h3 {
  font-size: 21px;
}

.group-info p {
  margin-top: 6px;

  font-size: 15px;
}

/* The blue "Planned" tag (and "Latest" on the newest update) */
.status {
  display: inline-block;
  margin-top: 14px;
  padding: 3px 10px;

  border-radius: 999px;
  background-color: var(--accent-soft);
  color: var(--accent-text);

  font-size: 13px;
  font-weight: 600;
}

/* The features in a group, with a thin line between each one */
.roadmap-list {
  padding: 0;

  list-style: none;
}

.roadmap-item {
  padding: 16px 0;
}

.roadmap-item:first-child {
  padding-top: 4px;
}

.roadmap-item:last-child {
  padding-bottom: 0;
}

.roadmap-item + .roadmap-item {
  border-top: 1px solid var(--border);
}

.roadmap-item h4 {
  font-size: 17px;
}

.roadmap-item p {
  max-width: 70ch;
  margin-top: 4px;

  font-size: 15px;
}

/* Recent updates */
.updates {
  padding: 56px 0 88px;
}

.updates-intro {
  margin-top: 10px;
}

/* The timeline: a line down the left with a dot for each update */
.timeline {
  margin-top: 32px;
  padding: 0 0 0 32px;

  border-left: 2px solid var(--divider);
  list-style: none;
}

.timeline-item {
  position: relative; /* So the dot (below) is placed relative to this item */
}

.timeline-item + .timeline-item {
  margin-top: 20px;
}

/* The dot on the line, lined up with the card's heading */
.timeline-item::before {
  content: "";
  position: absolute;
  top: 28px;
  left: -40px; /* Pulls it back over the line */
  width: 14px;
  height: 14px;

  border: 3px solid var(--window);
  border-radius: 50%;
  background-color: var(--accent);
}

/* Each update is a glossy panel */
.update-card {
  padding: 22px 28px 24px;

  border: 1px solid var(--border);
  border-radius: var(--radius);
  background-color: var(--panel);
  box-shadow: var(--gloss), var(--shadow);
}

/* Title and tag on the left, date pushed to the right */
.update-top {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 12px;
}

.update-top h3 {
  font-size: 20px;
}

.update-top .status {
  margin-top: 0;
}

.update-top time {
  margin-left: auto; /* Pushes the date to the far right */

  color: var(--muted);

  font-size: 14px;
  font-weight: 500;
}

.update-card ul {
  margin-top: 14px;
  padding-left: 20px;

  color: var(--muted);

  font-size: 15px;
}

.update-card li + li {
  margin-top: 6px; /* Space between bullet points */
}


/* ===== 11. Footer ===== */
.site-footer {
  padding: 28px 0;

  border-top: 1px solid var(--border);
}

.footer-inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 12px 32px;
}

.site-footer .brand-logo {
  width: 24px;
}

.site-footer .brand-name {
  font-size: 16px;
}

.site-footer p {
  font-size: 14px;
}


/* ===== 12. Download mini-game =====
   No panel: just the arrow boxes floating over the glitching page. */

/* The <dialog> itself is see-through, with no border, so only its contents show */
.game {
  width: 100%;
  max-width: 100%;
  padding: 24px;

  border: none;
  background: transparent;
  color: var(--text);

  text-align: center;
}

/* No outline on the box itself when it gets focus */
.game:focus {
  outline: none;
}

/* ::backdrop is the layer behind an open <dialog>. Dark enough to read the arrows,
   but see-through so the glitching page still shows. */
.game::backdrop {
  background-color: rgba(10, 13, 17, 0.62);
}

/* Hides something on screen but keeps it for screen readers */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* Mute and close: fixed to the top-right corner of the screen */
.game-controls {
  position: fixed;
  top: 20px;
  right: 20px;
  display: flex;
  gap: 8px;
}

.game-icon-button {
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  padding: 0;

  border: 1px solid var(--border-strong);
  border-radius: var(--radius-small);
  background-color: rgba(29, 36, 45, 0.85);
  color: var(--muted);
  cursor: pointer; /* Shows the hand pointer */
}

.game-icon-button:hover {
  background-color: var(--highlight);
  color: var(--text);
}

.game-icon-button:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.game-icon-button svg {
  width: 18px;
  height: 18px;
}

/* The mute icon: waves when the sound is on, a cross when it's off */
.sound-off {
  display: none;
}

.game-icon-button[aria-pressed="true"] .sound-waves {
  display: none;
}

.game-icon-button[aria-pressed="true"] .sound-off {
  display: inline;
}

/* The arrows to press */
.game-sequence {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 14px;
  padding: 0;

  list-style: none;
}

/* Each arrow box glitches on its own: it twitches sideways, its colours split
   into red and blue, and now and then a slice of it goes missing */
.arrow-tile {
  display: grid;
  place-items: center;
  width: 76px;
  height: 84px;

  border: 2px solid var(--border-strong);
  border-radius: var(--radius-small);
  background-color: var(--window);
  color: var(--muted);

  font-family: Consolas, "Courier New", monospace; /* A "typewriter" font for the hacker feel */
  font-size: 40px;
  font-weight: 700;
  text-shadow: -2px 0 rgba(255, 40, 90, 0.7), 2px 0 rgba(40, 200, 255, 0.7);

  animation: tile-glitch 1.6s steps(1) infinite;
}

/* Each box starts its glitch at a different time, so they don't all twitch together.
   :nth-child(3n + 2) picks boxes 2, 5, 8 and so on. */
.arrow-tile:nth-child(3n + 2) {
  animation-delay: -0.5s;
}

.arrow-tile:nth-child(3n + 3) {
  animation-delay: -1.1s;
}

@keyframes tile-glitch {
  0% {
    transform: translate(0, 0);
    clip-path: inset(0 0 0 0);
  }
  10% {
    transform: translate(-3px, 0);
    text-shadow: -4px 0 rgba(255, 40, 90, 0.9), 4px 0 rgba(40, 200, 255, 0.9);
  }
  12% {
    transform: translate(2px, 0);
    clip-path: inset(30% 0 40% 0);
  }
  14% {
    transform: translate(0, 0);
    clip-path: inset(0 0 0 0);
    text-shadow: -2px 0 rgba(255, 40, 90, 0.7), 2px 0 rgba(40, 200, 255, 0.7);
  }
  60% {
    transform: translate(1px, -1px);
  }
  62% {
    transform: translate(0, 0);
    clip-path: inset(0 0 65% 0);
  }
  64% {
    clip-path: inset(0 0 0 0);
  }
}

/* The arrow to press next */
.arrow-tile.current {
  border-color: var(--accent);
  box-shadow: 0 0 0 4px var(--accent-soft), 0 0 24px rgba(124, 140, 255, 0.35);
  color: var(--text);
}

/* Arrows already pressed correctly: green, and they stop glitching */
.arrow-tile.done {
  border-color: rgba(40, 170, 61, 0.7);
  background-color: #12301a;
  color: #6fdc80;
  text-shadow: none;

  animation: none;
}

/* Level and timer, under the arrows */
.game-status {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 14px;
  margin-top: 24px;
}

.game-level {
  color: var(--accent-text);
  text-shadow: 0 1px 8px rgba(0, 0, 0, 0.9); /* Easier to read over the page */

  font-family: Consolas, "Courier New", monospace;
  font-size: 14px;
  font-weight: 600;
}

.game-timer {
  width: 200px;
  height: 6px;
  overflow: hidden;

  border-radius: 999px;
  background-color: rgba(255, 255, 255, 0.12);
}

.game-timer-bar {
  width: 100%;
  height: 100%;

  background-color: var(--accent);

  transition: width 0.1s linear, background-color 0.2s ease;
}

.game-timer-bar.low {
  background-color: #e5534b; /* Red for the last 3 seconds */
}

/* "Level cleared!", "Wrong key!" and so on */
.game-message {
  min-height: 26px; /* Keeps its space even when empty, so nothing jumps */
  margin-top: 16px;

  font-size: 18px;
  font-weight: 600;
  text-shadow: 0 1px 8px rgba(0, 0, 0, 0.8); /* Easier to read over the page */
}

.game-message.good {
  color: #6fdc80;
}

.game-message.bad {
  color: #ff7b72;
}

.game-download {
  margin-top: 18px;
}

/* .download-button sets display: inline-flex, which would beat the hidden attribute,
   so we hide it again here while it has "hidden" */
.game-download[hidden] {
  display: none;
}

/* After winning, only the message and the download button are left */
.game.won .game-status {
  display: none;
}

/* The arrows shake when you get it wrong */
.game.shake .game-sequence {
  animation: game-shake 0.4s ease;
}

@keyframes game-shake {
  0%, 100% { transform: translateX(0); }
  20% { transform: translateX(-12px); }
  40% { transform: translateX(12px); }
  60% { transform: translateX(-7px); }
  80% { transform: translateX(7px); }
}


/* ===== 13. Glitch effect =====
   JavaScript adds the class "glitching" to <html> while the game is open.
   The website behind the game then gets the SVG glitch filter from index.html:
   slices of the page slide sideways and the colours split into pink and cyan. */
.glitching .site-header,
.glitching main,
.glitching .site-footer {
  filter: url(#glitch-filter); /* url(#id) points to the <filter> with that id */

  /* A tiny constant jitter. It also makes sure the browser redraws the filter every frame. */
  animation: glitch-jitter 0.1s steps(2) infinite;
}

@keyframes glitch-jitter {
  0% { transform: translate(0, 0); }
  50% { transform: translate(-2px, 1px); }
  100% { transform: translate(1px, 0); }
}

/* The canvas JavaScript draws the broken pixel bits on. Hidden until glitching. */
.glitch-bits {
  position: fixed;
  inset: 0;
  z-index: 40;
  display: none;
  width: 100%;
  height: 100%;
  pointer-events: none; /* Clicks go through it */
}

.glitching .glitch-bits {
  display: block;
}

/* Lines across the whole screen, like an old monitor, that flicker.
   body::after is an extra layer on top of the page (body::before is the background glow). */
.glitching body::after {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 50;
  pointer-events: none; /* Clicks go through it */

  background: repeating-linear-gradient(0deg, rgba(0, 0, 0, 0.28) 0 1px, transparent 1px 3px);

  animation: glitch-flicker 0.15s steps(2) infinite;
}

@keyframes glitch-flicker {
  0% { opacity: 0.5; }
  100% { opacity: 1; }
}


/* ===== 14. Animation and reduced motion =====
   @keyframes describes an animation from start (from) to finish (to).
   The logo rises up and fades in once when the page loads. */
@keyframes logo-rise {
  from {
    opacity: 0;
    transform: translateY(20px);
  }

  to {
    opacity: 1;
    transform: translateY(0);
  }
}

/* Turns off movement for visitors who've asked for less motion in their computer settings */
@media (prefers-reduced-motion: reduce) {
  .intro-logo {
    animation: none;
  }

  .download-button,
  .nav-link,
  .slide,
  .slide-caption,
  .dot,
  .arrow {
    transition: none;
  }

  .download-button:hover {
    transform: none;
  }

  /* A calmer glitch: the slices and colour split stay still (game.js doesn't move them),
     and nothing jitters or flickers */
  .glitching .site-header,
  .glitching main,
  .glitching .site-footer {
    animation: none;
  }

  .glitching body::after {
    animation: none;
    opacity: 0.6;
  }

  .game.shake .game-sequence,
  .arrow-tile {
    animation: none;
  }
}


/* ===== 15. Tablet and phone layouts ===== */

/* Tablets: 900px wide or narrower */
@media (max-width: 900px) {
  .feature-list {
    grid-template-columns: repeat(2, minmax(0, 1fr)); /* Two columns */
  }

  .about-inner {
    grid-template-columns: 1fr;
    gap: 40px;
  }

  .roadmap-group {
    grid-template-columns: 1fr; /* Group info on top, features underneath */
    gap: 20px;
  }

  .coverflow {
    --slide-width: 72vw;
  }
}

/* Phones: 640px wide or narrower */
@media (max-width: 640px) {
  .container {
    width: calc(100% - 40px);
  }

  .brand-name {
    display: none; /* Just the logo, so the menu fits */
  }

  .nav-link {
    padding: 8px 12px;
  }

  .intro {
    padding: 28px 0 56px;
  }

  .intro-logo-wrap {
    width: 180px;
    height: 180px;
  }

  .intro-logo {
    width: 124px;
  }

  .intro-description,
  .section-heading p,
  .about-text p,
  .check-list li,
  .page-intro p {
    font-size: 16px;
  }

  .download-button {
    width: 100%; /* Full-width button is easier to tap */
    font-size: 16px;
  }

  .showcase,
  .features,
  .about {
    padding: 56px 0;
  }

  .section-heading {
    margin-bottom: 32px;
  }

  .coverflow {
    --slide-width: 80vw;
  }

  .arrow {
    width: 40px;
    height: 40px;

    font-size: 26px;
  }

  .arrows {
    width: calc(var(--slide-width) + 16px); /* Arrows overlap the slide edges on small screens */
  }

  .feature-list {
    grid-template-columns: 1fr;
  }

  .feature {
    padding: 22px;
  }

  .game-sequence {
    gap: 8px;
  }

  .arrow-tile {
    width: 48px;
    height: 54px;

    font-size: 26px;
  }

  .roadmap-group {
    padding: 22px;
  }

  .timeline {
    padding-left: 22px;
  }

  .timeline-item::before {
    left: -30px;
  }

  .update-card {
    padding: 18px 20px 20px;
  }

  .update-top time {
    margin-left: 0; /* Date goes under the title on phones */
    width: 100%;
  }

  .site-footer .brand-name {
    display: inline; /* Bring the name back in the footer */
  }
}
