/* Cool Apps — site stylesheet. One file, no external fonts, light and dark themes from prefers-color-scheme.
   The build appends one --plugin-accent rule per plugin and per game and serves the file under a content hash.
   (A game's play page does not use this file: see games-play.css.)
   Order matters: base, then article typography (low specificity through :where), then components. */

:root {
  color-scheme: light dark;
  --bg: #ffffff;
  --surface: #f5f7fb;
  --surface-2: #eef2f8;
  --text: #0f1729;
  --muted: #4a5568;
  --border: #dde3ec;
  --border-strong: #c3ccda;
  --accent: #0b5cad;
  --accent-hover: #094c8f;
  --accent-soft: #e7f0fb;
  --on-accent: #ffffff;
  --ok: #1f7a4d;
  --code-bg: #f3f5f9;
  --code-text: #1c2536;
  --note-bg: #eef5fd;
  --note-border: #9cc3ec;
  --tip-bg: #ecf8f1;
  --tip-border: #8fd1ad;
  --warn-bg: #fff8e6;
  --warn-border: #e9c46a;
  --warn-text: #8a5a00;
  --shadow: 0 1px 2px rgba(15, 23, 41, 0.06), 0 4px 16px rgba(15, 23, 41, 0.06);
  --radius: 12px;
  --radius-sm: 8px;
  --gutter: 16px;
  --font: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif;
  --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace;
  --plugin-accent: var(--accent);
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg: #0b1220;
    --surface: #111b2d;
    --surface-2: #16223a;
    --text: #e6ecf5;
    --muted: #9fb0c8;
    --border: #233149;
    --border-strong: #31415e;
    --accent: #5cc8ff;
    --accent-hover: #8ed9ff;
    --accent-soft: #10263d;
    --on-accent: #04111f;
    --ok: #3ddc97;
    --code-bg: #0f1828;
    --code-text: #dbe4f0;
    --note-bg: #0f2033;
    --note-border: #24527c;
    --tip-bg: #0f2620;
    --tip-border: #23664a;
    --warn-bg: #1c1608;
    --warn-border: #6b5114;
    --warn-text: #f5c76a;
    --shadow: 0 1px 2px rgba(0, 0, 0, 0.3), 0 6px 20px rgba(0, 0, 0, 0.25);
  }
}

/* ------------------------------------------------------------------------------------------------ base */

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

/* --header-h: how much of the top of the screen the sticky header (.site-header) covers, for anchors and sticky asides. */
html {
  --header-h: 66px;
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  scroll-padding-top: calc(var(--header-h) + 12px);
}
@media (max-width: 880px) {
  html { --header-h: 96px; }
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font: 16px/1.6 var(--font);
  overflow-wrap: break-word;
}

img, svg { max-width: 100%; height: auto; }

a { color: var(--accent); text-underline-offset: 0.18em; }
a:hover { color: var(--accent-hover); }
a:focus-visible, .btn:focus-visible, summary:focus-visible {
  outline: 3px solid var(--accent);
  outline-offset: 2px;
  border-radius: 4px;
}

.container {
  width: 100%;
  max-width: 72rem;
  margin-inline: auto;
  padding-inline: var(--gutter);
}

@media (min-width: 900px) {
  :root { --gutter: 24px; }
}

.visually-hidden {
  position: absolute !important;
  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: var(--gutter);
  top: -100px;
  z-index: 40; /* above the sticky header */
  padding: 8px 14px;
  background: var(--accent);
  color: var(--on-accent);
  border-radius: var(--radius-sm);
  font-weight: 600;
  text-decoration: none;
}
.skip-link:focus { top: 8px; color: var(--on-accent); }

code {
  padding: 0.1em 0.35em;
  background: var(--code-bg);
  border: 1px solid var(--border);
  border-radius: 6px;
  color: var(--code-text);
  font: 0.875em/1.5 var(--mono);
  overflow-wrap: break-word;
}

/* ------------------------------------------------------------------------------------------------ header */

/* The header stays at the top of the screen while the page scrolls, on every page that has it (the play pages have none). */
.site-header {
  position: sticky;
  top: 0;
  z-index: 30;
  border-bottom: 1px solid var(--border);
  background: var(--bg);
}
.header-inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 8px 24px;
  min-height: 64px;
  padding-block: 10px;
}
.brand {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  color: var(--text);
  font-weight: 700;
  font-size: 1.125rem;
  letter-spacing: -0.01em;
  text-decoration: none;
}
.brand:hover { color: var(--text); }
.brand svg { width: 32px; height: 32px; flex: none; }

.site-nav ul {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  margin: 0;
  padding: 0;
  list-style: none;
}
.site-nav a {
  display: block;
  padding: 6px 12px;
  border-radius: 999px;
  color: var(--muted);
  font-weight: 500;
  text-decoration: none;
}
.site-nav a:hover { color: var(--text); background: var(--surface); }
.site-nav a[aria-current="page"], .site-nav a.is-active { color: var(--text); background: var(--surface-2); }

/* The player account entry of the games pages, after the main navigation: "Sign in" or the player tag. */
.account-link {
  display: inline-flex;
  align-items: center;
  min-height: 36px;
  padding: 5px 14px;
  border: 1px solid var(--border-strong);
  border-radius: 999px;
  color: var(--text);
  font-weight: 600;
  font-size: 0.9375rem;
  text-decoration: none;
  white-space: nowrap;
}
.account-link:hover { background: var(--surface); color: var(--text); }
.account-link[aria-current="page"] { background: var(--surface-2); }
.account-link:focus-visible { outline: 3px solid var(--accent); outline-offset: 2px; }
.header-end { display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: 8px 12px; }

/* The language switcher (lib/layout.mjs langSwitch): the current language's code, which opens the list of both languages.
   A <details>, so it works without JavaScript; lang.js closes it on a click elsewhere or with Escape. */
.lang-switch { position: relative; }
.lang-current {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 36px;
  padding: 5px 12px;
  border: 1px solid var(--border-strong);
  border-radius: 999px;
  color: var(--text);
  font-weight: 600;
  font-size: 0.875rem;
  letter-spacing: 0.02em;
  list-style: none;
  cursor: pointer;
  user-select: none;
  white-space: nowrap;
}
.lang-current::-webkit-details-marker { display: none; }
.lang-current::after {
  content: "";
  width: 0.4em;
  height: 0.4em;
  border-right: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  transform: translateY(-2px) rotate(45deg);
}
.lang-switch[open] .lang-current::after { transform: translateY(2px) rotate(-135deg); }
.lang-current:hover, .lang-switch[open] .lang-current { background: var(--surface); }
.lang-menu {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  z-index: 20;
  min-width: 10.5rem;
  margin: 0;
  padding: 6px;
  list-style: none;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow);
}
.lang-menu a {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 10px;
  border-radius: 6px;
  color: var(--text);
  font-weight: 500;
  text-decoration: none;
}
.lang-menu a:hover { background: var(--surface); }
.lang-menu a[aria-current="true"] { background: var(--surface-2); font-weight: 600; }
.lang-code { min-width: 1.75em; color: var(--muted); font-size: 0.8125rem; font-weight: 600; letter-spacing: 0.04em; }

/* On a phone or a narrow window the account link and the language switcher join the brand's row, and the navigation gets
   a row of its own: one line that scrolls sideways when it does not fit, so the sticky header stays two rows high. */
@media (max-width: 880px) {
  .header-inner { min-height: 0; padding-block: 8px 6px; gap: 6px 12px; }
  .header-end { display: contents; }
  .header-end .account-link { order: 1; margin-left: auto; }
  .header-end .lang-switch { order: 1; }
  .header-end .site-nav { order: 2; flex-basis: 100%; min-width: 0; margin-inline: calc(-1 * var(--gutter)); }
  /* A long player tag never pushes the brand's row onto two lines. */
  .header-end .account-link { display: inline-block; max-width: 9rem; overflow: hidden; text-overflow: ellipsis; line-height: 24px; }
  .site-nav ul {
    flex-wrap: nowrap;
    overflow-x: auto;
    padding-inline: calc(var(--gutter) - 8px) 32px;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
    /* The right edge fades, so a row that goes on past the screen shows that it does. */
    -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 32px), transparent);
    mask-image: linear-gradient(to right, #000 calc(100% - 32px), transparent);
  }
  .site-nav ul::-webkit-scrollbar { display: none; }
  .site-nav li { flex: none; }
  .site-nav a { padding: 6px 10px; white-space: nowrap; }
}
/* The smallest phones: a little less room around the brand's row, so it stays one line. */
@media (max-width: 360px) {
  .header-inner { column-gap: 8px; }
  .brand { gap: 8px; }
  .brand svg { width: 28px; height: 28px; }
  .header-end .account-link { padding-inline: 10px; max-width: 7.5rem; }
  .lang-current { padding-inline: 8px; }
}

/* ------------------------------------------------------------------------------------------------ buttons */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: 44px;
  padding: 10px 20px;
  border: 1px solid transparent;
  border-radius: 999px;
  font: inherit;
  font-weight: 600;
  line-height: 1.2;
  text-align: center;
  text-decoration: none;
  cursor: pointer;
}
.btn-primary { background: var(--accent); color: var(--on-accent); }
.btn-primary:hover { background: var(--accent-hover); color: var(--on-accent); }
.btn-secondary { background: var(--bg); color: var(--text); border-color: var(--border-strong); }
.btn-secondary:hover { background: var(--surface); color: var(--text); }
.btn-block { width: 100%; }
/* In place of a Buy button while a plugin's checkout is not open yet: same size, dashed, not a link. */
.soon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  padding: 10px 20px;
  border: 1px dashed var(--border-strong);
  border-radius: 999px;
  color: var(--muted);
  font-weight: 600;
  line-height: 1.2;
  text-align: center;
}

.actions {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin-top: 24px;
}

/* ------------------------------------------------------------------------------------------------ article typography
   Rendered Markdown lives in .prose. Every rule here goes through :where() so its specificity stays at one class:
   the components further down override it without fighting. */

.prose { min-width: 0; max-width: 50rem; }
.prose > :first-child { margin-top: 0; }
.prose :where(h1) {
  margin: 0 0 16px;
  font-size: clamp(1.75rem, 4.5vw, 2.25rem);
  line-height: 1.2;
  letter-spacing: -0.02em;
}
.prose :where(h2) {
  margin: 48px 0 12px;
  font-size: 1.5rem;
  line-height: 1.3;
  letter-spacing: -0.01em;
}
.prose :where(h3) { margin: 32px 0 8px; font-size: 1.1875rem; line-height: 1.35; }
.prose :where(h4) { margin: 24px 0 8px; font-size: 1rem; }
.prose :where(h2, h3) { scroll-margin-top: 16px; }
.prose :where(p, ul, ol, dl, pre, blockquote, .table-wrap) { margin: 0 0 16px; }
.prose :where(ul, ol) { padding-left: 1.5rem; }
.prose :where(li) { margin: 4px 0; }
.prose :where(li > ul, li > ol) { margin: 4px 0 0; }
.prose :where(li > p) { margin: 0 0 8px; }
.prose :where(hr) { margin: 40px 0; border: 0; border-top: 1px solid var(--border); }
.prose :where(blockquote) {
  padding: 4px 16px;
  border-left: 4px solid var(--border-strong);
  color: var(--muted);
}
.prose :where(.lead) { margin-top: 0; }

.anchor {
  margin-left: 6px;
  color: var(--border-strong);
  font-weight: 400;
  text-decoration: none;
  opacity: 0;
}
h2:hover .anchor, h3:hover .anchor, .anchor:focus { opacity: 1; }
.anchor:hover { color: var(--accent); }

pre.code {
  padding: 16px 18px;
  overflow-x: auto;
  background: var(--code-bg);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  line-height: 1.55;
}
pre.code code {
  padding: 0;
  background: none;
  border: 0;
  font-size: 0.875rem;
  overflow-wrap: normal;
  white-space: pre;
}

.table-wrap {
  overflow-x: auto;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
}
table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.9375rem;
}
th, td {
  padding: 10px 14px;
  border-bottom: 1px solid var(--border);
  text-align: left;
  vertical-align: top;
}
thead th {
  background: var(--surface);
  font-size: 0.875rem;
  font-weight: 700;
  white-space: nowrap;
}
tbody tr:last-child > * { border-bottom: 0; }
/* The top 10 of a game page ({{> top-ten}}, top10.js): a tab for each board, then the table. */
.top10 { margin: 0 0 16px; }
.top10-tabs { display: flex; flex-wrap: wrap; gap: 8px; margin: 0 0 12px; }
.top10-tab {
  font: inherit; font-size: 0.9375rem; padding: 6px 14px; border-radius: 999px; cursor: pointer;
  border: 1px solid var(--border); background: var(--bg); color: var(--muted);
}
.top10-tab[aria-selected="true"] { background: var(--surface-2); color: var(--text); font-weight: 600; }
.top10-table .top10-rank { width: 3em; color: var(--muted); font-variant-numeric: tabular-nums; }
.top10-table .top10-tag { font-weight: 600; overflow-wrap: anywhere; }
.top10-table .top10-num, .top10-table thead th:nth-child(n+3) { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.top10-table .top10-you > * { background: var(--surface); }
.top10-table .top10-apart > * { border-top: 2px solid var(--border); }
.top10-note { color: var(--muted); font-size: 0.9375rem; }
tbody th { font-weight: 500; }
td code, th code { white-space: normal; }
.align-center { text-align: center; }
.align-right { text-align: right; }

.callout {
  margin: 0 0 16px;
  padding: 14px 18px;
  border: 1px solid var(--note-border);
  border-left-width: 4px;
  border-radius: var(--radius-sm);
  background: var(--note-bg);
}
.callout > :last-child { margin-bottom: 0; }
.callout-title { margin: 0 0 6px; font-weight: 700; }
.callout-tip { background: var(--tip-bg); border-color: var(--tip-border); }
.callout-warning { background: var(--warn-bg); border-color: var(--warn-border); }
.callout-warning .callout-title { color: var(--warn-text); }

/* ------------------------------------------------------------------------------------------------ page + toc */

.page-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 32px;
  padding-block: 32px 64px;
}
.page-grid.has-toc .toc-desktop { display: none; }

@media (min-width: 1100px) {
  .page-grid.has-toc { grid-template-columns: minmax(0, 1fr) 15rem; }
  .page-grid.has-toc .toc-desktop { display: block; }
  .page-grid.has-toc .toc-mobile { display: none; }
}

.toc ul { margin: 0; padding: 0; list-style: none; }
.toc li { margin: 0; }
.toc a { display: block; padding: 3px 0; color: var(--muted); text-decoration: none; }
.toc a:hover { color: var(--accent); }

.toc-desktop {
  position: sticky;
  top: calc(var(--header-h) + 20px);
  align-self: start;
  max-height: calc(100vh - var(--header-h) - 40px);
  overflow-y: auto;
  padding-left: 16px;
  border-left: 1px solid var(--border);
  font-size: 0.875rem;
}
.toc-title {
  margin: 0 0 8px;
  color: var(--muted);
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.toc-mobile {
  margin: 0 0 24px;
  padding: 12px 16px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  font-size: 0.9375rem;
}
.toc-mobile summary { cursor: pointer; font-weight: 600; }
.toc-mobile ul { margin-top: 8px; columns: 2 12rem; column-gap: 24px; }
.toc-mobile li { break-inside: avoid; }

/* ------------------------------------------------------------------------------------------------ home */

.hero {
  padding-block: 56px 48px;
  border-bottom: 1px solid var(--border);
  background:
    radial-gradient(60rem 24rem at 85% -10%, var(--accent-soft), transparent 70%),
    var(--bg);
}
.hero-inner {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  align-items: center;
  gap: 32px;
}
.hero-art { display: none; }
@media (min-width: 900px) {
  .hero-inner { grid-template-columns: minmax(0, 1fr) 20rem; }
  .hero-art { display: block; width: 100%; height: auto; }
}

/* The hero pyramid of the home page and the plugins hub (lib/brand.mjs heroCubes): the decorative cubes in one SVG and,
   over each plugin's cube, a link as large as that cube with the cube drawn again in the plugin's colours and a card
   (logo and name) that opens on hover and on keyboard focus. Only the cube's faces take the pointer (a link's box is a
   rectangle, the cube is not). The build appends each link's box and where its card opens. Unlike the other hero art it
   also shows on phones, smaller, under the text. */
.hero-cubes {
  display: block;
  position: relative;
  width: min(100%, 18rem);
  margin-inline: auto;
}
@media (min-width: 900px) {
  .hero-cubes { width: 100%; margin-inline: 0; }
}
.hero-cubes-base { display: block; width: 100%; height: auto; }
.cube-link {
  position: absolute;
  pointer-events: none;
  text-decoration: none;
}
.cube-svg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: visible; /* the focus ring goes round the cube, outside its box */
  transition: filter 0.18s ease;
}
.cube-lift { transition: transform 0.18s ease; }
.cube-faces { pointer-events: auto; }
.cube-ring, .cube-ring-halo {
  fill: none;
  stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
  opacity: 0;
}
/* Two rings, light and dark, so the focus shows on any cube colour and in both themes. */
.cube-ring-halo { stroke: var(--bg); stroke-width: 7px; }
.cube-ring { stroke: var(--text); stroke-width: 3px; }
.cube-card {
  position: absolute;
  display: flex;
  align-items: center;
  gap: 8px;
  width: max-content;
  padding: 6px 12px 6px 6px;
  background: var(--bg);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow);
  color: var(--text);
  font-size: 0.875rem;
  font-weight: 600;
  line-height: 1.25;
  transform: translate(var(--card-x, 0%), var(--card-y, -50%));
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.15s ease, visibility 0.15s;
}
.cube-card img { flex: none; width: 24px; height: 24px; border-radius: 6px; }
.cube-link:focus-visible { z-index: 2; outline: none; }
.cube-link:focus-visible .cube-ring, .cube-link:focus-visible .cube-ring-halo { opacity: 1; }
.cube-link:focus-visible .cube-card { opacity: 1; visibility: visible; }
.cube-link:focus-visible .cube-svg { filter: brightness(1.08); }
.cube-link:focus-visible .cube-lift { transform: translateY(-3px); }
/* Hover only where there is a real pointer: on touch screens a tap goes straight to the plugin. */
@media (hover: hover) {
  .cube-link:hover { z-index: 3; }
  .cube-link:hover .cube-card { opacity: 1; visibility: visible; }
  .cube-link:hover .cube-svg { filter: brightness(1.08); }
  .cube-link:hover .cube-lift { transform: translateY(-3px); }
}
@media (prefers-reduced-motion: reduce) {
  .cube-svg, .cube-lift, .cube-card { transition: none; }
  .cube-link:hover .cube-lift, .cube-link:focus-visible .cube-lift { transform: none; }
}
@media (forced-colors: active) {
  .cube-ring { stroke: Highlight; }
  .cube-ring-halo { stroke: Canvas; }
}
.eyebrow {
  margin: 0 0 12px;
  color: var(--accent);
  font-size: 0.875rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
.hero h1 {
  margin: 0;
  max-width: 20ch;
  font-size: clamp(2rem, 6vw, 3.25rem);
  line-height: 1.1;
  letter-spacing: -0.02em;
}
.lead {
  max-width: 44rem;
  margin: 16px 0 0;
  color: var(--muted);
  font-size: 1.125rem;
}

/* The two entry blocks of the home page: plugins and games. */
.entries {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 16px;
  margin-top: 28px;
}
@media (min-width: 640px) {
  .entries { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
.entry {
  display: flex;
  flex-direction: column;
  padding: 20px 22px;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow), inset 0 4px 0 var(--accent);
}
.entry h2 { margin: 0; font-size: 1.375rem; line-height: 1.3; letter-spacing: -0.01em; }
.entry h2 a { color: var(--text); text-decoration: none; }
.entry h2 a:hover { color: var(--accent); }
.entry p { margin: 6px 0 16px; color: var(--muted); font-size: 0.9375rem; }
.entry .btn { align-self: flex-start; margin-top: auto; }

.section { padding-block: 48px; }
.section + .section { border-top: 1px solid var(--border); }
.section-title {
  margin: 0 0 8px;
  font-size: 1.5rem;
  letter-spacing: -0.01em;
}
.section-intro { margin: 0 0 24px; color: var(--muted); max-width: 44rem; }
.section-actions { margin-top: 8px; }
.empty-note { margin: 0 0 16px; color: var(--muted); }

/* Search boxes (assets/browse.js): on the home page, in the hero, with a list of links under it; on the games hub, between
   the hero and the categories, hiding the cards that do not match. Hidden until the script shows them. */
.site-search { position: relative; max-width: 32rem; margin-top: 24px; }
.games-search .site-search { margin-top: 0; }
.site-search-input {
  width: 100%;
  min-height: 48px;
  padding: 10px 16px;
  border: 1px solid var(--border-strong);
  border-radius: 999px;
  background: var(--bg);
  color: var(--text);
  font: inherit;
  font-size: 1rem;
}
.site-search-input::placeholder { color: var(--muted); }
.site-search-input:focus-visible { outline: 3px solid var(--accent); outline-offset: 2px; }
.search-results {
  margin: 8px 0 0;
  padding: 6px;
  list-style: none;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
}
.search-results a {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  min-height: 44px;
  padding: 8px 12px;
  border-radius: var(--radius-sm);
  color: var(--text);
  text-decoration: none;
}
.search-results a:hover, .search-results a:focus-visible { background: var(--surface); }
.search-result-name { font-weight: 600; }
.search-result-kind { color: var(--muted); font-size: 0.875rem; }
.search-empty { margin: 10px 0 0; color: var(--muted); }
.games-search { padding-block: 24px; }
/* Hidden by the search (or until there is something to show): the card layouts set display, so [hidden] needs help. */
.site-search[hidden], .search-results[hidden], .search-empty[hidden], .card[hidden], .games-category[hidden],
.played-recently[hidden] { display: none; }

/* "Played recently" on the games hub: the games this browser opened last, as small links to their play pages. */
.played-recently { padding-block: 28px; }
.recent-games {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin: 12px 0 0;
  padding: 0;
  list-style: none;
}
.recent-game {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  min-height: 44px;
  padding: 6px 16px 6px 6px;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 999px;
  box-shadow: var(--shadow);
  color: var(--text);
  font-weight: 600;
  text-decoration: none;
}
.recent-game:hover { border-color: var(--border-strong); color: var(--accent); }
.recent-game img { width: 40px; height: 40px; border-radius: 10px; }

/* ------------------------------------------------------------------------------------------------ cards */

/* Plugin and game cards: as many columns as cards, at most 3 (the build adds cards-1, cards-2 or cards-3 from the number
   of cards). A row that is not full is centred under the one above: with 3 columns the 4th and 5th cards sit side by
   side in the middle of row 2. A single card is as wide as one of two, under the section title. */
.cards {
  --cols: 2;
  --gap: 20px;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--gap);
  margin: 0 0 16px;
}
.cards-1 { --cols: 2; justify-content: flex-start; }
.cards-2 { --cols: 2; }
.cards-3 { --cols: 3; }
.cards > .card { flex: 0 1 calc((100% - (var(--cols) - 1) * var(--gap)) / var(--cols)); min-width: 0; }
@media (max-width: 1000px) {
  .cards > .card { flex-basis: calc((100% - var(--gap)) / 2); }
}
@media (max-width: 720px) {
  .cards > .card { flex-basis: 100%; }
}
.card {
  display: flex;
  flex-direction: column;
  padding: 24px;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
}
/* Plugin cards and game cards share one layout. */
.plugin-card-head, .card-head {
  display: flex;
  align-items: center;
  gap: 14px;
}
.plugin-card-head img, .card-head img { width: 52px; height: 52px; flex: none; border-radius: 12px; }
.plugin-card-title, .card-title { margin: 0; font-size: 1.25rem; line-height: 1.3; }
.plugin-card-title a, .card-title a { color: var(--text); text-decoration: none; }
.plugin-card-title a:hover, .card-title a:hover { color: var(--accent); }
.card .tagline { margin: 2px 0 0; color: var(--muted); font-size: 0.9375rem; }
.card .summary { margin: 16px 0 0; }
.chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin: 16px 0 0;
  padding: 0;
  list-style: none;
}
.chip {
  margin: 0;
  padding: 2px 10px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--surface);
  color: var(--muted);
  font-size: 0.8125rem;
  font-weight: 500;
}
.price-line { margin: 16px 0 0; font-weight: 600; }
.card-actions { display: flex; flex-wrap: wrap; gap: 10px; margin-top: auto; padding-top: 20px; }
/* Game cards: a tap anywhere on the card opens the game. The Play link stretches over the whole card; the title and
   "About the game" sit above it and still open the game's page. */
.game-card { position: relative; transition: border-color 0.15s ease; }
.game-card:hover { border-color: var(--border-strong); }
.game-card .card-play::after { content: ""; position: absolute; inset: 0; border-radius: var(--radius); }
.game-card .card-title a, .game-card .card-actions .btn-secondary { position: relative; z-index: 1; }

.features {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 15rem), 1fr));
  gap: 14px;
  margin: 20px 0 24px;
  padding: 0;
  list-style: none;
}
.features li {
  margin: 0;
  padding: 16px 18px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
}
.features h3 { margin: 0 0 6px; font-size: 1.0625rem; line-height: 1.35; }
.features p { margin: 0; color: var(--muted); font-size: 0.9375rem; }

.steps {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 16rem), 1fr));
  gap: 16px;
  margin: 0 0 16px;
  padding: 0;
  list-style: none;
  counter-reset: step;
}
.steps li {
  position: relative;
  margin: 0;
  padding: 18px 20px 18px 64px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  counter-increment: step;
}
.steps li::before {
  content: counter(step);
  position: absolute;
  left: 20px;
  top: 18px;
  display: grid;
  place-items: center;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  background: var(--accent);
  color: var(--on-accent);
  font-weight: 700;
  font-size: 0.9375rem;
}
.steps h3 { margin: 0 0 4px; font-size: 1.0625rem; line-height: 1.35; }
.steps p { margin: 0; color: var(--muted); font-size: 0.9375rem; }

/* ------------------------------------------------------------------------------------------------ plugin header */

.plugin-top {
  border-bottom: 1px solid var(--border);
  background: linear-gradient(180deg, var(--surface), var(--bg));
  box-shadow: inset 0 4px 0 var(--plugin-accent);
}
.plugin-id {
  display: flex;
  align-items: center;
  gap: 16px;
  padding-top: 28px;
}
.plugin-id img { width: 56px; height: 56px; flex: none; border-radius: 14px; }
.plugin-name {
  margin: 0;
  font-size: 1.5rem;
  font-weight: 700;
  line-height: 1.2;
  letter-spacing: -0.01em;
}
.plugin-name a { color: var(--text); text-decoration: none; }
.plugin-name a:hover { color: var(--accent); }
.plugin-tagline { margin: 2px 0 0; color: var(--muted); }

.plugin-top.is-overview .plugin-id { padding-top: 40px; }
.plugin-top.is-overview .plugin-id img { width: 72px; height: 72px; border-radius: 18px; }
.plugin-top.is-overview .plugin-name { font-size: clamp(1.875rem, 5vw, 2.75rem); }
.plugin-intro { max-width: 46rem; margin: 20px 0 0; font-size: 1.0625rem; }

.plugin-nav { padding-block: 20px 16px; }
.plugin-nav ul {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin: 0;
  padding: 0;
  list-style: none;
}
.plugin-nav a {
  display: block;
  padding: 6px 14px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--bg);
  color: var(--muted);
  font-size: 0.9375rem;
  font-weight: 500;
  text-decoration: none;
}
.plugin-nav a:hover { color: var(--text); border-color: var(--border-strong); }
.plugin-nav a[aria-current="page"] {
  background: var(--text);
  border-color: var(--text);
  color: var(--bg);
}

/* ------------------------------------------------------------------------------------------------ game header */

.game-top {
  border-bottom: 1px solid var(--border);
  background: linear-gradient(180deg, var(--surface), var(--bg));
  box-shadow: inset 0 4px 0 var(--plugin-accent);
  padding-bottom: 28px;
}
.game-id {
  display: flex;
  align-items: center;
  gap: 16px;
  padding-top: 40px;
}
.game-id img { width: 72px; height: 72px; flex: none; border-radius: 18px; }
.game-name {
  margin: 0;
  font-size: clamp(1.875rem, 5vw, 2.75rem);
  font-weight: 700;
  line-height: 1.2;
  letter-spacing: -0.01em;
}
.game-tagline { margin: 2px 0 0; color: var(--muted); }
.game-intro { max-width: 46rem; margin: 20px 0 0; font-size: 1.0625rem; }
.game-account { max-width: 46rem; margin: 16px 0 0; color: var(--muted); font-size: 0.9375rem; }

/* Download for offline play (offline.js runs the box): hidden until the browser can keep files for offline play. */
.offline-box { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 16px; margin-top: 16px; }
.offline-box[hidden], .offline-box [hidden] { display: none; }
.offline-status { margin: 0; color: var(--muted); font-size: 0.9375rem; }
.offline-status:empty { display: none; }
.offline-hint { flex-basis: 100%; margin: 0; color: var(--muted); font-size: 0.875rem; }
.games-category .offline-box { margin: 0 0 20px; }
.link-button {
  padding: 0;
  border: 0;
  background: none;
  color: var(--accent);
  font: inherit;
  font-weight: 600;
  text-decoration: underline;
  text-underline-offset: 0.18em;
  cursor: pointer;
}
.link-button:hover { color: var(--accent-hover); }
.link-button:focus-visible { outline: 3px solid var(--accent); outline-offset: 2px; border-radius: 4px; }
.link-button:disabled { color: var(--muted); cursor: default; }

/* ------------------------------------------------------------------------------------------------ blog */

/* Sections after an article (the games it names, related articles) and after a game's page (its articles). */
.page-grid + .section { border-top: 1px solid var(--border); }

.blog-hero { padding-block: 40px 36px; }
.blog-hero h1 { max-width: 24ch; }
.feed-line { margin: 16px 0 0; font-size: 0.9375rem; }

/* The trail above an article's title and on tag pages; the current page (last) is cut short on narrow screens. */
.breadcrumbs { margin: 0 0 14px; font-size: 0.875rem; }
.breadcrumbs ol {
  display: flex;
  flex-wrap: wrap;
  margin: 0;
  padding: 0;
  list-style: none;
  color: var(--muted);
}
.breadcrumbs li { white-space: nowrap; }
.breadcrumbs li + li::before { content: "/"; margin: 0 8px; color: var(--border-strong); }
.breadcrumbs a { color: var(--muted); }
.breadcrumbs a:hover { color: var(--accent); }
.breadcrumbs li[aria-current="page"] {
  flex: 1 1 0;
  min-width: 8rem;
  overflow: hidden;
  text-overflow: ellipsis;
  color: var(--text);
}

.post-top {
  padding-block: 32px 28px;
  border-bottom: 1px solid var(--border);
  background: linear-gradient(180deg, var(--surface), var(--bg));
  box-shadow: inset 0 4px 0 var(--accent);
}
.post-title {
  max-width: 46rem;
  margin: 0;
  font-size: clamp(1.75rem, 5vw, 2.5rem);
  line-height: 1.2;
  letter-spacing: -0.015em;
}
.post-meta { margin: 12px 0 0; color: var(--muted); font-size: 0.9375rem; }
.post-tags { margin-top: 14px; }
.post-tags li { margin: 0; }
.chip-link { display: inline-block; text-decoration: none; }
.chip-link:hover { border-color: var(--border-strong); color: var(--text); }

.post-cover, .post-figure { margin: 0 0 24px; }
.post-cover img, .post-figure img {
  display: block;
  max-width: 100%;
  height: auto;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
}
.post-figure figcaption { margin-top: 8px; color: var(--muted); font-size: 0.875rem; }

.post-card-cover {
  display: block;
  width: calc(100% + 48px);
  max-width: none;
  height: auto;
  margin: -24px -24px 16px;
  border-bottom: 1px solid var(--border);
  border-radius: var(--radius) var(--radius) 0 0;
}
.post-card-meta { margin: 0 0 6px; color: var(--muted); font-size: 0.875rem; }
/* The publication date never wraps: "11 October / 2026" split over two lines reads wrong on a narrow card. */
.post-card-meta time { white-space: nowrap; }
.post-card .summary { margin-top: 10px; }

/* Blog articles already read. The mark is made by read.js on load, because the HTML is cached at the edge and the same
   for everyone. It must read as "you have been here", never as "this matters less", and colour is never the only
   signal (colour blindness, a phone in the sun): the border goes dashed, the title drops to --muted AND the word
   "Read" sits in a pill next to the date. --muted keeps small-text contrast on a card in both palettes: 7.5:1 on
   #ffffff in light and 8.5:1 on #0b1220 in dark, well over the 4.5:1 minimum. Only article cards (.post-card) and the
   article's own date line get the mark: the cards of games and plugins never do. */
.post-card.is-read { border-style: dashed; }
.post-card.is-read .card-title a { color: var(--muted); }
.card-read {
  display: inline-block;
  margin-left: 8px;
  padding: 1px 8px;
  border: 1px solid var(--border-strong);
  border-radius: 999px;
  color: var(--muted);
  font-size: 0.8125rem;
  font-weight: 600;
}
.post-meta .card-read { margin-left: 8px; }

.pagination {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 12px;
  margin-top: 24px;
}
.pagination-pages { display: flex; flex-wrap: wrap; gap: 4px; margin: 0; padding: 0; list-style: none; }
.pagination-pages a, .pagination-current {
  display: grid;
  place-items: center;
  min-width: 40px;
  min-height: 40px;
  padding: 0 8px;
  border-radius: 999px;
  font-weight: 600;
  text-decoration: none;
}
.pagination-pages a { border: 1px solid var(--border); color: var(--text); }
.pagination-pages a:hover { background: var(--surface); color: var(--text); }
.pagination-current { background: var(--text); color: var(--bg); }
.pagination-gap { display: grid; place-items: center; min-width: 24px; color: var(--muted); }

.post-nav-wrap { padding-block: 32px 56px; border-top: 1px solid var(--border); }
.post-nav { display: grid; grid-template-columns: minmax(0, 1fr); gap: 12px; }
.post-nav-link {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 16px 18px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--text);
  text-decoration: none;
}
.post-nav-link:hover { border-color: var(--border-strong); color: var(--text); }
.post-nav-label { color: var(--muted); font-size: 0.8125rem; font-weight: 600; letter-spacing: 0.04em; text-transform: uppercase; }
.post-nav-title { font-weight: 600; }
@media (min-width: 720px) {
  .post-nav { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .post-nav-newer { grid-column: 2; text-align: right; }
}

/* Display ads of blog articles (only while site.config.mjs sets ads.display): set apart from the text and labelled.
   AdSense marks a unit it could not fill with data-ad-status="unfilled"; the whole slot then disappears. */
.ad-slot { margin: 32px 0; padding-top: 10px; border-top: 1px solid var(--border); }
.ad-label {
  margin: 0 0 8px;
  color: var(--muted);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
.ad-slot ins { display: block; text-align: center; text-decoration: none; }
.ad-slot:has(ins[data-ad-status="unfilled"]) { display: none; }
.post-ad .ad-slot { margin-block: 8px 40px; }

/* ------------------------------------------------------------------------------------------------ plans + matrix */

.plans {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 15rem), 1fr));
  gap: 16px;
  margin: 8px 0 16px;
}
.plan {
  display: flex;
  flex-direction: column;
  padding: 22px;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
}
.plan.is-featured { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent), var(--shadow); }
.plan-name { margin: 0; font-size: 1.125rem; line-height: 1.3; }
.plan-price { margin: 10px 0 0; }
.plan-price .amount { font-size: 2.25rem; font-weight: 800; letter-spacing: -0.02em; line-height: 1.1; }
.plan-price .period { color: var(--muted); font-size: 0.9375rem; }
.plan-note { margin: 8px 0 0; color: var(--muted); font-size: 0.9375rem; }
.plan-features {
  margin: 16px 0 20px;
  padding: 0;
  list-style: none;
  font-size: 0.9375rem;
}
.plan-features li { position: relative; margin: 6px 0; padding-left: 24px; }
.plan-features li::before {
  content: "";
  position: absolute;
  left: 2px;
  top: 0.45em;
  width: 10px;
  height: 6px;
  border-left: 2px solid var(--ok);
  border-bottom: 2px solid var(--ok);
  transform: rotate(-45deg);
}
.plan .btn, .plan .soon { margin-top: auto; }
.plan .soon { width: 100%; }

.matrix td:nth-child(2), .matrix td:nth-child(3), .matrix th:nth-child(2), .matrix th:nth-child(3) { width: 26%; }
.yes { color: var(--ok); font-weight: 700; }
.no { color: var(--muted); }

.fineprint { color: var(--muted); font-size: 0.875rem; }

/* ------------------------------------------------------------------------------------------------ boxes */

.facts {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  margin: 0 0 16px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  overflow: hidden;
}
.facts > div {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 2px 16px;
  padding: 10px 14px;
  border-bottom: 1px solid var(--border);
}
.facts > div:last-child { border-bottom: 0; }
.facts dt { font-weight: 600; }
.facts dd { margin: 0; color: var(--muted); }
@media (min-width: 640px) {
  .facts > div { grid-template-columns: 11rem minmax(0, 1fr); }
}

.download-box {
  margin: 0 0 16px;
  padding: 20px 22px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--surface);
}
.download-box.is-pending { border-style: dashed; border-color: var(--border-strong); }
.download-title { margin: 0 0 6px; font-size: 1.125rem; font-weight: 700; }
.download-box p { margin: 0 0 8px; }
.download-box > :last-child { margin-bottom: 0; }
.download-meta { color: var(--muted); font-size: 0.9375rem; }

.link-list { display: flex; flex-wrap: wrap; gap: 8px 20px; margin: 0 0 16px; padding: 0; list-style: none; }
.link-list li { margin: 0; }

.shots {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 20rem), 1fr));
  gap: 16px;
  margin: 8px 0 16px;
}
.shot { margin: 0; }
.shot img {
  display: block;
  width: 100%;
  height: auto;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow);
}
.shot figcaption { margin-top: 6px; color: var(--muted); font-size: 0.875rem; }

/* ------------------------------------------------------------------------------------------------ pricing page */

.pricing-plugin { padding-block: 8px 24px; }
.pricing-plugin + .pricing-plugin { border-top: 1px solid var(--border); padding-top: 24px; }
.pricing-plugin-head { display: flex; align-items: center; gap: 12px; margin: 24px 0 8px; }
.pricing-plugin-head img { width: 40px; height: 40px; border-radius: 10px; }
.pricing-plugin-head h2 { margin: 0; font-size: 1.375rem; }
.pricing-plugin > p { margin: 0 0 12px; color: var(--muted); }

/* ------------------------------------------------------------------------------------------------ 404 */

.notfound { padding-block: 80px; text-align: center; }
.notfound .code-404 {
  margin: 0;
  color: var(--accent);
  font: 800 4rem/1 var(--mono);
}
.notfound h1 { margin: 12px 0 8px; font-size: 1.75rem; }
.notfound p { margin: 0 auto; max-width: 32rem; color: var(--muted); }
.notfound .actions { justify-content: center; }

/* ------------------------------------------------------------------------------------------------ footer */

.site-footer {
  border-top: 1px solid var(--border);
  background: var(--surface);
  color: var(--muted);
  font-size: 0.9375rem;
}
.footer-inner {
  display: grid;
  gap: 12px;
  padding-block: 28px;
}
.footer-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 8px 24px;
}
.footer-links {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 18px;
  margin: 0;
  padding: 0;
  list-style: none;
}
.footer-links a { color: var(--muted); }
.footer-links a:hover { color: var(--accent); }
.footer-copy { margin: 0; }
.footer-copy a { color: var(--muted); }
.legal-note { margin: 0; font-size: 0.8125rem; }

/* Plugin and game accents (generated). */
.plugin-chatshield { --plugin-accent: #2EC27E; }
.plugin-afkwarden { --plugin-accent: #8B5CF6; }
.plugin-blocktown { --plugin-accent: #E8743B; }
.game-skimline { --plugin-accent: #2A50D8; }
.game-hold-the-line { --plugin-accent: #2852D6; }
.game-mindlap { --plugin-accent: #2E6BE6; }
.game-pulsework { --plugin-accent: #2550D8; }
.game-hopwise { --plugin-accent: #2754D8; }
.game-snakey { --plugin-accent: #2A50D8; }
.game-genius-or-goof { --plugin-accent: #E54B4B; }
.game-boxlock { --plugin-accent: #2551CC; }

/* Hero pyramid: each plugin's link box and where its card opens (generated by lib/brand.mjs heroCubes). */
.cube-link[data-plugin="chatshield"] { left: 40.257%; top: 11%; width: 19.486%; height: 24%; }
.cube-link[data-plugin="chatshield"] .cube-card { left: 50%; top: 108.333%; max-width: 500.37%; --card-x: -50%; --card-y: 0%; }
.cube-link[data-plugin="afkwarden"] { left: 30.514%; top: 29%; width: 19.486%; height: 24%; }
.cube-link[data-plugin="afkwarden"] .cube-card { left: 109.623%; top: 50%; max-width: 240.563%; --card-x: 0%; --card-y: -50%; }
.cube-link[data-plugin="blocktown"] { left: 50%; top: 29%; width: 19.486%; height: 24%; }
.cube-link[data-plugin="blocktown"] .cube-card { right: 109.623%; top: 50%; max-width: 240.563%; --card-x: 0%; --card-y: -50%; }
