/* playsw.app. The public pages carry no JavaScript (the games page filters with a plain GET form),
   and the fonts are served from this host, so nothing here sends a visitor's IP to a third party.
   Two deliberate exceptions: on a user page and /games, game covers load from IGDB's image servers
   (Roman, 2026-09-22); and the sign-in pages (/login, /signup) run one first-party script that talks
   to Firebase Authentication (docs/web-client.md). The privacy policy says so. Keep everything else
   first-party. */

@font-face {
  font-family: Manrope;
  src: url("fonts/Manrope-Regular.woff2?v=2") format("woff2");
  font-weight: 400;
  font-display: swap;
}
@font-face {
  font-family: Manrope;
  src: url("fonts/Manrope-SemiBold.woff2?v=2") format("woff2");
  font-weight: 600;
  font-display: swap;
}
@font-face {
  font-family: Manrope;
  src: url("fonts/Manrope-ExtraBold.woff2?v=2") format("woff2");
  font-weight: 800;
  font-display: swap;
}

:root {
  /* The app icon's gradient: orange top-left to purple bottom-right. */
  --brand-from: #fd9305;
  --brand-to: #b153d8;

  --bg: #ffffff;
  --bg-sunk: #f6f5f8;
  --ink: #16141a;
  --ink-soft: #55505e;
  --rule: #e6e3ea;
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg: #121016;
    --bg-sunk: #1a171f;
    --ink: #f4f2f7;
    --ink-soft: #a9a2b5;
    --rule: #2b2733;
  }
}

* { box-sizing: border-box; }

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

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: Manrope, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  font-weight: 400;
  font-size: 17px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

/* A hairline of the brand gradient across the top, instead of painting the whole page with it. */
body::before {
  content: "";
  display: block;
  height: 4px;
  background: linear-gradient(90deg, var(--brand-from), var(--brand-to));
}

.bar {
  max-width: 720px;
  margin: 0 auto;
  padding: 0 24px;
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: 11px;
  margin: 26px 0 0;
  color: inherit;
  text-decoration: none;
  font-weight: 800;
  font-size: 17px;
  letter-spacing: -0.01em;
}

.brand img {
  border-radius: 8px;
  display: block;
}

main {
  max-width: 720px;
  margin: 0 auto;
  padding: 0 24px;
}

.hero {
  padding: 68px 0 64px;
}

h1 {
  margin: 0;
  font-weight: 800;
  font-size: clamp(34px, 7vw, 52px);
  line-height: 1.1;
  letter-spacing: -0.033em;
}

.lede {
  margin: 22px 0 0;
  max-width: 34em;
  font-size: 19px;
  color: var(--ink-soft);
}

.cta { margin: 34px 0 0; display: flex; flex-wrap: wrap; align-items: center; gap: 12px 22px; }

/* The ways into the web client (/signup) and playsw.app/games: secondary actions beside the App
   Store link, so an outline — in full ink, not faded, since each is just as much a link. */
.cta-link {
  display: inline-block;
  padding: 12px 22px;
  border: 1px solid var(--ink-soft);
  border-radius: 999px;
  color: var(--ink);
  font-weight: 600;
  font-size: 16px;
  letter-spacing: -0.005em;
  text-decoration: none;
  transition: border-color 0.15s ease;
}
.cta-link:hover { border-color: var(--ink); }
.cta-link:focus-visible { outline: 3px solid var(--brand-from); outline-offset: 3px; }

/* The App Store link (App Apple ID 6816521284) on the home pages and playsw.app/games, and
   "Open in PlayShare Swap" on a user page: the page's main action, in the filled gradient. */
.badge {
  display: inline-block;
  padding: 13px 24px;
  border-radius: 999px;
  background: linear-gradient(110deg, var(--brand-from), var(--brand-to));
  color: #fff;
  font-weight: 800;
  font-size: 16px;
  letter-spacing: -0.005em;
}

a.badge {
  text-decoration: none;
  box-shadow: 0 6px 18px -8px var(--brand-to);
  transition: transform 0.15s ease, box-shadow 0.15s ease;
}
a.badge:hover { transform: translateY(-1px); box-shadow: 0 10px 22px -8px var(--brand-to); }
a.badge:focus-visible { outline: 3px solid var(--brand-from); outline-offset: 3px; }

.steps {
  display: grid;
  gap: 1px;
  background: var(--rule);
  border: 1px solid var(--rule);
  border-radius: 16px;
  overflow: hidden;
  margin-bottom: 80px;
}

.steps article {
  background: var(--bg-sunk);
  padding: 28px 26px;
}

.steps h2 {
  margin: 0 0 8px;
  font-weight: 800;
  font-size: 19px;
  letter-spacing: -0.015em;
}

.steps p {
  margin: 0;
  color: var(--ink-soft);
}

.steps b {
  font-weight: 600;
  color: var(--ink);
}

.steps i {
  font-style: normal;
  font-weight: 600;
}

/* The legal pages, written by scripts/export-legal.py into the same shell as the landing. */

/* Top and bottom only: the sides come from `main`'s 24px, which a `padding` shorthand here
   would zero out and leave the text touching the screen edges on a phone. */
.prose {
  padding-top: 46px;
  padding-bottom: 80px;
}

.prose h1 {
  font-size: clamp(28px, 5vw, 38px);
  line-height: 1.15;
  margin-bottom: 26px;
}

.prose h2 {
  margin: 48px 0 12px;
  font-weight: 800;
  font-size: 23px;
  letter-spacing: -0.02em;
  scroll-margin-top: 20px;
}

.prose h3 {
  margin: 32px 0 10px;
  font-weight: 600;
  font-size: 18px;
  letter-spacing: -0.01em;
  scroll-margin-top: 20px;
}

.prose p,
.prose li {
  color: var(--ink-soft);
}

.prose p {
  margin: 0 0 14px;
}

.prose strong {
  font-weight: 600;
  color: var(--ink);
}

.prose ul,
.prose ol {
  margin: 0 0 14px;
  padding-left: 22px;
}

.prose li {
  margin-bottom: 8px;
}

/* A nested list sits inside its parent item; it needs the gap above, not below. */
.prose li > ul,
.prose li > ol {
  margin: 8px 0 0;
}

.prose hr {
  margin: 40px 0;
  border: 0;
  border-top: 1px solid var(--rule);
}

.prose a {
  color: inherit;
  text-decoration-color: var(--brand-to);
  text-underline-offset: 2px;
}

.prose code {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 0.9em;
  background: var(--bg-sunk);
  border: 1px solid var(--rule);
  border-radius: 5px;
  padding: 1px 5px;
}

.prose .updated {
  font-size: 15px;
}

.foot {
  border-top: 1px solid var(--rule);
  padding-top: 26px;
  padding-bottom: 46px;
}

.foot nav {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 22px;
  font-weight: 600;
  font-size: 15px;
}

.foot a {
  color: var(--ink);
  text-decoration: none;
  border-bottom: 1px solid var(--rule);
}

.foot a:hover {
  border-bottom-color: var(--brand-to);
}

.fine {
  margin: 14px 0 0;
  font-size: 14px;
  color: var(--ink-soft);
}

@media (min-width: 620px) {
  .steps { grid-template-columns: 1fr 1fr; }
  /* An odd step count would leave an empty cell showing the rule colour. */
  .steps article:last-child:nth-child(odd) { grid-column: 1 / -1; }
}

/* The user pages (playsw.app/<username>), rendered by the API — see server/src/publicPageHtml.ts.
   The markup lives there; the look lives here, so a page stays part of the site. */

.pf-head { padding: 44px 0 6px; }

.pf-name {
  display: inline;
  margin: 0;
  font-weight: 800;
  font-size: clamp(32px, 6vw, 44px);
  letter-spacing: -0.03em;
  line-height: 1.1;
  overflow-wrap: anywhere;
}

.pf-badge {
  display: inline-block;
  vertical-align: 6px;
  margin-left: 12px;
  padding: 5px 12px;
  border-radius: 999px;
  background: linear-gradient(110deg, var(--brand-from), var(--brand-to));
  color: #fff;
  font-size: 13px;
  font-weight: 600;
}

.pf-handle {
  margin: 8px 0 0;
  color: var(--ink-soft);
  font-size: 17px;
  font-weight: 600;
  overflow-wrap: anywhere;
}

.pf-handle + .pf-meta { margin-top: 4px; }

.pf-meta {
  margin: 14px 0 0;
  color: var(--ink-soft);
  font-size: 17px;
}

.pf-section {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  margin: 44px 0 0;
}

.pf-section h2 {
  margin: 0;
  font-weight: 800;
  font-size: 21px;
  letter-spacing: -0.02em;
}

.pf-count {
  color: var(--ink-soft);
  font-size: 15px;
}

.pf-list {
  margin: 18px 0 0;
  padding: 0;
  list-style: none;
  border: 1px solid var(--rule);
  border-radius: 16px;
  overflow: hidden;
}

.pf-list li {
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 14px 18px;
  background: var(--bg-sunk);
}

.pf-list li + li { border-top: 1px solid var(--rule); }

/* Both the real cover and the letter placeholder for a game we have no artwork for. */
.pf-cover {
  flex: 0 0 auto;
  width: 52px;
  height: 69px;
  border-radius: 6px;
  object-fit: cover;
  background: linear-gradient(150deg, #cdc7d6, #a79fb5);
  display: grid;
  place-items: center;
  color: #fff;
  font-weight: 800;
  font-size: 19px;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .pf-cover {
    background: linear-gradient(150deg, #4b4457, #332e3d);
  }
}

.pf-title { flex: 1; min-width: 0; }
.pf-title b { display: block; font-weight: 600; font-size: 17px; letter-spacing: -0.01em; }
.pf-title span { display: block; margin-top: 3px; color: var(--ink-soft); font-size: 14px; }

.pf-offer { flex: 0 0 auto; text-align: right; }
.pf-offer b { display: block; font-weight: 800; font-size: 16px; letter-spacing: -0.01em; }
.pf-offer span { display: block; margin-top: 3px; color: var(--ink-soft); font-size: 13px; font-weight: 600; }

.pf-cta { margin: 34px 0 0; }

.pf-empty {
  margin: 18px 0 0;
  padding: 26px 22px;
  border: 1px solid var(--rule);
  border-radius: 16px;
  background: var(--bg-sunk);
  color: var(--ink-soft);
}

.pf-note {
  margin: 30px 0 60px;
  padding-top: 22px;
  border-top: 1px solid var(--rule);
  color: var(--ink-soft);
  font-size: 14px;
}

/* playsw.app/games, rendered by the API — see server/src/gamesCatalogueHtml.ts. The list and the
   cards reuse the user page's .pf-* look; only the filter form and the pager are its own. */

.gc-filters {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 12px;
  align-items: end;
  margin: 32px 0 0;
}

.gc-field { display: block; min-width: 0; }
.gc-field span { display: block; margin-bottom: 6px; color: var(--ink-soft); font-size: 14px; font-weight: 600; }

.gc-filters select,
.gc-filters input,
.gc-filters button {
  width: 100%;
  height: 44px;
  padding: 0 12px;
  border: 1px solid var(--rule);
  border-radius: 10px;
  background: var(--bg-sunk);
  color: var(--ink);
  font: inherit;
  font-size: 16px; /* below 16px iOS Safari zooms the page on focus */
}

.gc-filters select:disabled { color: var(--ink-soft); }

.gc-filters button {
  border: 0;
  background: linear-gradient(110deg, var(--brand-from), var(--brand-to));
  color: #fff;
  font-weight: 800;
  cursor: pointer;
}

.gc-terms { display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 10px; margin-top: 6px; }
.pf-title .gc-price { display: inline; font-weight: 800; font-size: 15px; }
.pf-title .gc-copies { display: inline; margin: 0; color: var(--ink-soft); font-size: 13px; font-weight: 600; }

.gc-pager {
  display: flex;
  justify-content: space-between;
  gap: 16px;
  margin: 18px 0 0;
  font-weight: 600;
}
.gc-pager a { color: var(--ink); }
.gc-pager .gc-next { margin-left: auto; }

/* Under the landing page's three steps: the way to the guide and the screenshots. Buttons one
   step down from the filled .cta-link: a gradient outline (a padding-box fill over a border-box
   gradient) and gradient text, full width on a phone, side by side from a tablet up. */
.more { margin: 0 0 72px; display: grid; gap: 14px; }
.more a {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 18px 24px;
  border: 2px solid transparent;
  border-radius: 999px;
  background:
    linear-gradient(var(--bg), var(--bg)) padding-box,
    linear-gradient(110deg, var(--brand-from), var(--brand-to)) border-box;
  color: var(--ink);
  font-weight: 800;
  font-size: 18px;
  letter-spacing: -0.01em;
  text-decoration: none;
  box-shadow: 0 6px 18px -12px var(--brand-to);
  transition: transform 0.15s ease, box-shadow 0.15s ease;
}
.more a::after {
  content: "→";
  font-size: 20px;
  background: linear-gradient(110deg, var(--brand-from), var(--brand-to));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}
.more a:hover { transform: translateY(-1px); box-shadow: 0 10px 22px -10px var(--brand-to); }
.more a:focus-visible { outline: 3px solid var(--brand-from); outline-offset: 3px; }
@media (min-width: 620px) { .more { grid-template-columns: 1fr 1fr; } }

/* playsw.app/guide, generated from the app's How to use screen (scripts/export-guide.py). Each
   section keeps the app's accent colour for it as a rule down the left edge and its heading. */
.guide .lede { margin-top: 12px; }
.guide-points { margin: 22px 0 34px; padding-left: 1.2em; color: var(--ink-soft); }
.guide-points li { margin: 4px 0; }
.guide-box {
  margin: 0 0 18px;
  padding: 4px 22px 6px;
  background: var(--bg-sunk);
  border: 1px solid var(--rule);
  border-left: 4px solid var(--accent);
  border-radius: 16px;
}
.guide-box h2 { color: var(--accent); margin-top: 18px; }

/* playsw.app/screenshots: two phones a row on a phone, three from a tablet up. */
.shots-page { padding-top: 46px; padding-bottom: 72px; }
.shots-page .lede { margin: 14px 0 34px; }
.shots-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 28px 16px; }
.shots-grid figure { margin: 0; }
.shots-grid img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: 22px;
  border: 1px solid var(--rule);
  background: var(--bg-sunk);
}
.shots-grid figcaption { margin-top: 10px; font-size: 14px; line-height: 1.45; color: var(--ink-soft); }
@media (min-width: 620px) { .shots-grid { grid-template-columns: repeat(3, 1fr); gap: 34px 22px; } }
/* The web client's pages under the phones: a laptop window's middle column, one a row on a phone,
   two from a tablet up, top-aligned since each is cut to its own content. */
.shots-h2 { margin: 56px 0 22px; }
.shots-web { grid-template-columns: 1fr; align-items: start; }
.shots-web img { border-radius: 12px; }
@media (min-width: 620px) { .shots-web { grid-template-columns: repeat(2, 1fr); } }

/* The signed-in pages (/login, /signup, /library, /account), rendered by the API — see
   server/src/web/webHtml.ts. The site's own 720px column, so the content lines up with the header
   on a wide screen; a form, a message or the account rows stay narrower within it, left-aligned,
   since a form reads best narrow even on a laptop. */

.w-top { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.w-who {
  margin-top: 26px;
  padding: 7px 14px;
  border: 1px solid var(--rule);
  border-radius: 999px;
  color: var(--ink);
  font-weight: 600;
  font-size: 14px;
  text-decoration: none;
  max-width: 50%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.w-who.on { border-color: var(--brand-to); }

.w-tabs { display: flex; gap: 6px; margin: 16px 0 0; overflow-x: auto; }
.w-tabs a {
  flex: none;
  padding: 8px 14px;
  border-radius: 999px;
  background: var(--bg-sunk);
  color: var(--ink-soft);
  font-weight: 600;
  font-size: 14px;
  text-decoration: none;
}
.w-tabs a.on { color: #fff; background: linear-gradient(110deg, var(--brand-from), var(--brand-to)); }

.w-main { padding-bottom: 56px; }
.w-form, .w-error, .w-notice, .w-rows, .w-links-small { max-width: 480px; }
.w-h1 { margin: 36px 0 0; font-size: clamp(28px, 6vw, 36px); overflow-wrap: anywhere; }
/* "‹ Back" above a page's content, where the eye looks for it — quiet, like iOS's back button,
   so it never competes with the page's own action at the bottom. */
/* At least 44px tall: Apple's minimum touch target, so it's easy to hit on a phone. */
.w-back { display: inline-flex; align-items: center; gap: 4px; min-height: 44px; margin: 18px 0 0; padding: 0 12px 0 0; color: var(--ink-soft); font-size: 18px; font-weight: 600; text-decoration: none; }
.w-back-chevron { font-size: 28px; line-height: 1; margin-top: -3px; }
.w-back:hover { color: var(--ink); }
.w-back:focus-visible { outline: 3px solid var(--brand-from); outline-offset: 3px; border-radius: 4px; }
.w-back + .w-h1, .w-back + .w-game { margin-top: 4px; }
.w-back + .w-error { margin-top: 16px; }
.w-lede { margin: 12px 0 0; color: var(--ink-soft); font-size: 16px; }
.w-sec {
  margin: 34px 0 0;
  font-size: 13px;
  font-weight: 800;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--ink-soft);
}

.w-form { display: grid; gap: 16px; margin: 26px 0 0; }
.w-form[hidden] { display: none; }
.w-field { display: block; min-width: 0; }
.w-field > span, .w-sub > span { display: block; margin-bottom: 6px; color: var(--ink-soft); font-size: 14px; font-weight: 600; }
.w-field small { display: block; margin-top: 6px; color: var(--ink-soft); font-size: 13px; }
.w-sub { display: block; margin-top: 10px; }
.w-field input[type="text"], .w-field input[type="email"], .w-field input[type="password"], .w-field select, .w-sub input, .w-sub select {
  width: 100%;
  height: 46px;
  padding: 0 12px;
  border: 1px solid var(--rule);
  border-radius: 10px;
  background: var(--bg-sunk);
  color: var(--ink);
  font: inherit;
  font-size: 16px; /* below 16px iOS Safari zooms the page on focus */
}
.w-field input:focus-visible, .w-field select:focus-visible, .w-sub input:focus-visible, .w-sub select:focus-visible {
  outline: 2px solid var(--brand-to);
  outline-offset: 1px;
}

.w-btn {
  display: block;
  width: 100%;
  height: 48px;
  border: 0;
  border-radius: 999px;
  background: linear-gradient(110deg, var(--brand-from), var(--brand-to));
  color: #fff;
  font: inherit;
  font-weight: 800;
  font-size: 16px;
  line-height: 48px;
  text-align: center;
  text-decoration: none;
  cursor: pointer;
}
.w-btn:disabled { opacity: 0.6; cursor: progress; }
.w-btn:focus-visible { outline: 3px solid var(--brand-from); outline-offset: 3px; }
.w-btn-outline { background: none; border: 1px solid var(--ink-soft); color: var(--ink); font-weight: 600; line-height: 46px; }
.w-btn-danger { background: none; border: 1px solid #e5484d; color: #e5484d; font-weight: 700; line-height: 46px; }
.w-btn-danger-filled { background: #e5484d; }

/* "Continue with Apple" / "Continue with Google" above a sign-in form: plain links to the API's
   /login/<provider>, drawn to Apple's (black, white mark) and Google's (outline, four-colour G)
   button rules. Over the "or" divider sits the email form. */
.w-socials { display: grid; gap: 10px; max-width: 480px; margin: 26px 0 0; }
.w-social {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  height: 48px;
  border-radius: 999px;
  font-weight: 700;
  font-size: 16px;
  text-decoration: none;
}
.w-social:focus-visible { outline: 3px solid var(--brand-from); outline-offset: 3px; }
.w-social-apple { background: #000; color: #fff; }
.w-social-google { border: 1px solid var(--ink-soft); color: var(--ink); background: var(--bg); }
@media (prefers-color-scheme: dark) { .w-social-apple { background: #fff; color: #000; } }
.w-or { display: flex; align-items: center; gap: 10px; max-width: 480px; margin: 18px 0 0; color: var(--ink-soft); font-size: 13px; }
.w-or::before, .w-or::after { content: ""; flex: 1; height: 1px; background: var(--rule); }
.w-or + .w-form { margin-top: 18px; }

.w-links { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 8px 18px; margin: 4px 0 0; font-size: 15px; font-weight: 600; }
.w-links a { color: var(--ink); }
.w-links-small { justify-content: flex-start; margin-top: 30px; font-size: 14px; font-weight: 400; }
.w-fine { margin: 0; color: var(--ink-soft); font-size: 14px; }
.w-fine a { color: inherit; }

.w-check { display: flex; gap: 10px; align-items: flex-start; font-size: 15px; }
.w-check input { flex: none; width: 20px; height: 20px; margin: 2px 0 0; accent-color: var(--brand-to); }
.w-check a { color: var(--ink); }

.w-tiles { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.w-tile { position: relative; display: block; }
.w-tile input { position: absolute; opacity: 0; }
.w-tile span {
  display: block;
  padding: 10px 12px;
  border: 1px solid var(--rule);
  border-radius: 10px;
  background: var(--bg-sunk);
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
}
.w-tile input:checked + span { border-color: var(--brand-to); box-shadow: inset 0 0 0 1px var(--brand-to); }
.w-tile input:focus-visible + span { outline: 2px solid var(--brand-from); outline-offset: 2px; }

.w-more { margin-top: 10px; }
.w-more summary { cursor: pointer; font-size: 14px; font-weight: 600; }
.w-more[open] summary { margin-bottom: 8px; }

.w-rows { margin: 24px 0 0; border-top: 1px solid var(--rule); }
.w-row { display: flex; justify-content: space-between; gap: 12px; padding: 14px 0; border-bottom: 1px solid var(--rule); font-size: 16px; }
.w-row > span { color: var(--ink-soft); }
.w-row b, .w-row a { min-width: 0; font-weight: 600; text-align: right; overflow-wrap: anywhere; }
.w-row a { color: var(--ink); text-decoration: none; }

.w-switch { display: flex; align-items: center; justify-content: space-between; gap: 12px; font-size: 16px; }
.w-switch input { flex: none; width: 22px; height: 22px; accent-color: var(--brand-to); }

.w-error {
  margin: 18px 0 0;
  padding: 10px 12px;
  border-radius: 10px;
  background: rgba(229, 72, 77, 0.1);
  color: #c4363b;
  font-size: 15px;
  font-weight: 600;
}
.w-error[hidden], .w-notice[hidden] { display: none; }
.w-notice {
  margin: 18px 0 0;
  padding: 10px 12px;
  border-radius: 10px;
  background: var(--bg-sunk);
  color: var(--ink);
  font-size: 15px;
}
@media (prefers-color-scheme: dark) {
  .w-error { color: #ff7a7e; }
}

/* Phase 2: the library's actions, a game's page, adding games (server/src/routes/webGames.ts). */

.w-actions { display: flex; flex-wrap: wrap; gap: 10px; margin: 22px 0 0; max-width: 480px; }
.w-actions .w-btn { flex: 1 1 180px; width: auto; }

/* A library row is a link to the game's page: the whole row, with a chevron. */
.pf-list li.w-li { padding: 0; }
.w-li > a { display: flex; align-items: center; gap: 16px; width: 100%; padding: 14px 18px; color: inherit; text-decoration: none; }
.w-li > a::after { content: "›"; margin-left: auto; color: var(--ink-soft); font-size: 22px; line-height: 1; }
.w-li > a:hover .pf-title b { color: var(--brand-to); }
.w-li > a:focus-visible { outline: 3px solid var(--brand-from); outline-offset: -3px; }

.w-game { display: flex; align-items: center; gap: 16px; margin: 36px 0 0; }
.w-game .pf-title b { font-size: clamp(22px, 5vw, 28px); font-weight: 800; letter-spacing: -0.02em; }

.w-pills { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.w-pill, .w-pill-radio span {
  display: inline-block;
  padding: 8px 13px;
  border: 1px solid var(--rule);
  border-radius: 999px;
  background: var(--bg);
  color: var(--ink);
  font: inherit;
  font-size: 14px;
  font-weight: 700;
  cursor: pointer;
}
.w-pill:hover, .w-pill-radio span:hover { border-color: var(--brand-to); }
.w-pill.on, .w-pill-radio input:checked + span { color: #fff; border-color: transparent; background: linear-gradient(110deg, var(--brand-from), var(--brand-to)); }
.w-pill:focus-visible, .w-pill-radio input:focus-visible + span { outline: 3px solid var(--brand-from); outline-offset: 2px; }
.w-pill-radio input { position: absolute; opacity: 0; }
.w-pills select { height: 36px; padding: 0 8px; border: 1px solid var(--rule); border-radius: 10px; background: var(--bg); color: var(--ink); font: inherit; font-size: 14px; }

.w-radios { margin: 0; padding: 0; border: 0; }
.w-radios > span { display: block; margin-bottom: 6px; color: var(--ink-soft); font-size: 14px; font-weight: 600; }
.w-radio { display: flex; align-items: center; gap: 10px; padding: 6px 0; font-size: 16px; cursor: pointer; }
.w-radio input { width: 18px; height: 18px; margin: 0; accent-color: var(--brand-to); }
.w-radio small { color: var(--ink-soft); }

.w-search { grid-template-columns: 1fr auto; align-items: center; gap: 10px; }
.w-search input {
  width: 100%;
  height: 48px;
  padding: 0 14px;
  border: 1px solid var(--rule);
  border-radius: 999px;
  background: var(--bg-sunk);
  color: var(--ink);
  font: inherit;
  font-size: 16px;
}
.w-search .w-btn { width: auto; padding: 0 22px; }
.pf-list li.w-result { align-items: flex-start; }

.w-textarea {
  width: 100%;
  padding: 12px 14px;
  border: 1px solid var(--rule);
  border-radius: 12px;
  background: var(--bg-sunk);
  color: var(--ink);
  font: inherit;
  font-size: 16px;
  line-height: 1.5;
  resize: vertical;
}

.w-checklist { margin: 0; padding: 0; list-style: none; border-top: 1px solid var(--rule); }
.w-check-row { padding: 12px 0; border-bottom: 1px solid var(--rule); }
.w-check-row .w-more { margin: 6px 0 0 30px; }
.w-missing { color: var(--ink-soft); font-size: 15px; }
.w-for { color: var(--ink-soft); font-weight: 400; }

/* Phase 3: games nearby and exchanges (server/src/routes/webExchanges.ts). */

.w-tag, .pf-title b .w-tag { display: inline-block; margin-left: 6px; padding: 1px 8px; border-radius: 999px; background: linear-gradient(110deg, var(--brand-from), var(--brand-to)); color: #fff; font-size: 11px; font-weight: 800; vertical-align: 2px; }
.w-pills a.w-pill { text-decoration: none; }
.w-btn-small { display: inline-block; width: auto; height: 36px; padding: 0 14px; font-size: 14px; line-height: 36px; flex: none; }
.pf-list li.w-owner { justify-content: space-between; }

.w-deal { margin: 14px 0 0; padding: 16px; border: 1px solid var(--rule); border-radius: 16px; background: var(--bg-sunk); }
.w-deal-title { margin: 0; font-weight: 800; font-size: 16px; }
.w-deal-sides { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin: 12px 0 0; }
.w-deal-label { display: block; margin-bottom: 6px; color: var(--ink-soft); font-size: 12px; font-weight: 800; letter-spacing: 0.04em; text-transform: uppercase; }
.w-deal-game { display: flex; align-items: center; gap: 10px; margin-top: 6px; }
.w-deal-game .pf-cover { width: 36px; height: 48px; font-size: 16px; }
.w-deal-game .pf-title b { font-size: 15px; }
.w-deal-line { margin: 10px 0 0; color: var(--ink-soft); font-size: 14px; }
.w-deal-line b { color: var(--ink); }
.w-deal-actions { margin: 12px 0 0; }
.w-deal-actions .w-radios { margin-bottom: 8px; }

/* Phase 4: messages and a chat (server/src/routes/webChats.ts). */

.w-count { display: inline-block; min-width: 18px; margin-left: 6px; padding: 0 5px; border-radius: 999px; background: #e5484d; color: #fff; font-size: 11px; font-weight: 800; line-height: 18px; text-align: center; }
.w-dot { flex: none; width: 10px; height: 10px; margin-left: auto; border-radius: 50%; background: #e5484d; }
.w-unread .pf-title b { font-weight: 800; }
.pf-title .w-chat-last { margin-top: 4px; color: var(--ink-soft); }
.w-chat-link { font-weight: 700; color: var(--ink); }

.w-chat {
  display: flex;
  flex-direction: column;
  gap: 6px;
  max-height: min(60vh, 560px);
  margin: 22px 0 0;
  padding: 14px;
  overflow-y: auto;
  border: 1px solid var(--rule);
  border-radius: 16px;
  background: var(--bg-sunk);
}
.w-chat-empty { margin: 0; color: var(--ink-soft); text-align: center; }
.w-bubble {
  align-self: flex-start;
  max-width: 78%;
  padding: 8px 12px;
  border: 1px solid var(--rule);
  border-radius: 16px 16px 16px 4px;
  background: var(--bg);
  font-size: 15px;
  line-height: 1.45;
  overflow-wrap: anywhere;
}
.w-bubble.w-me { align-self: flex-end; border-color: transparent; border-radius: 16px 16px 4px 16px; background: linear-gradient(110deg, var(--brand-from), var(--brand-to)); color: #fff; }
.w-bubble time { display: block; margin-top: 2px; font-size: 11px; opacity: 0.7; }
.w-composer { display: flex; gap: 8px; align-items: flex-end; margin: 12px 0 0; }
.w-composer textarea { flex: 1; min-height: 48px; padding: 12px 14px; border: 1px solid var(--rule); border-radius: 16px; background: var(--bg-sunk); color: var(--ink); font: inherit; font-size: 16px; resize: vertical; }
.w-composer .w-btn { width: auto; padding: 0 22px; }
