/* games.css — the arcade's front door.
 *
 * GENERATED by scripts/build_games_sheet.py from the owner's design mock
 * (specimens/games-mock/index.html). Edit the script, not this file.
 *
 * Every rule is scoped under .gsheet. The mock styled bare `body`, `main`,
 * `button` and `a`, and shipping that unscoped would restyle the chrome and
 * every story page that shares styles.css. The mock's colours are kept as
 * drawn — the owner approved those hues; only the FACES are swapped, Anton
 * for the house Inter 900.
 */

.gsheet {
  --gs-navy: #00142f;
  --gs-blue: #071eaa;
  --gs-rule: #d9d9d9;
  --gs-ink: #080b12;
  --gs-ink-2: #53565d;
  font-family: var(--ui);
  color: var(--gs-ink);
}
.gsheet a { text-decoration: none; color: inherit; }
/* Scoped past `.gsheet a`, which would otherwise win on specificity and turn
   every card's white copy to body ink on a dark ground. */
.gsheet a.gh-card { color: #fff; }
.gs-edge { width: calc(100% - 72px); max-width: var(--page); margin: 0 auto; }

/* ---- The Latest. Ships hidden; its script unhides it once the feed has
   given it a real headline and a real link. Never a baked one. ---- */
.gs-latest { border-bottom: 1px solid var(--gs-rule); }
.gs-latest[hidden] { display: none; }
.gs-latest-inner {
  height: 43px; display: flex; align-items: center; gap: 18px;
  overflow: hidden; white-space: nowrap;
}
.gs-latest-label {
  flex: 0 0 auto; color: var(--gs-blue);
  font-size: 13px; font-weight: 800; letter-spacing: .04em; text-transform: uppercase;
}
.gs-latest-time { flex: 0 0 auto; font-size: 14px; font-weight: 800; font-variant-numeric: tabular-nums; }
.gs-latest-sep { flex: 0 0 1px; width: 1px; height: 19px; background: #9b9b9b; }
.gs-latest-head {
  min-width: 0; overflow: hidden; text-overflow: ellipsis;
  font-size: 15px; color: var(--gs-ink);
}
.gs-latest-head:hover { color: var(--gs-blue); }
.gs-latest-arrow {
  flex: 0 0 auto; color: var(--gs-blue); font-size: 21px; line-height: 1;
  transition: transform .15s ease;
}
.gs-latest:hover .gs-latest-arrow { transform: translateX(4px); }

/* ---- the hero. Two illustrations bleeding to the sheet's edges, the word
   between them. The centre carries a soft white ground of its own so navy
   type never lands on a palm frond. ---- */
/* min-height is the taller illustration's own height at its widest (the pier
   is 413x198). Below that, `overflow: hidden` crops the art from the top and
   the skyline loses its towers. */
.gs-hero {
  position: relative; overflow: hidden; background: var(--paper);
  min-height: 202px; padding: 12px 0 16px;
  display: flex; flex-direction: column; justify-content: center;
}
.gs-hero-art { position: absolute; bottom: 0; z-index: 0; display: block; height: auto; }
.gs-hero-art.at-left { left: 0; width: min(414px, 30%); }
.gs-hero-art.at-right { right: 0; width: min(420px, 30%); }
.gs-hero-center {
  position: relative; z-index: 2; max-width: 760px; margin: 0 auto;
  padding: 4px 12px 0; text-align: center;
  background: radial-gradient(58% 78% at 50% 44%,
              rgba(255, 255, 255, .96) 50%, rgba(255, 255, 255, 0) 100%);
}
.gs-hero h1 {
  margin: 0; color: var(--gs-navy);
  font-family: var(--ui); font-weight: 900;
  font-size: clamp(56px, 8.2vw, 112px);
  line-height: .94; letter-spacing: -.045em; text-transform: uppercase;
}
.gs-hero-sub {
  max-width: 650px; margin: 10px auto 0; color: #101628;
  font-family: var(--ui); font-size: 18px; line-height: 25px;
}
.gs-spark { position: absolute; top: 40%; width: 78px; height: 28px; z-index: 3; }
.gs-spark.at-left { left: calc(50% - 281px); }
.gs-spark.at-right { right: calc(50% - 281px); transform: scaleX(-1); }
.gs-spark::before, .gs-spark::after {
  content: ""; position: absolute; left: 14px; height: 1px; background: #cbd2e1;
}
.gs-spark::before { top: 3px; width: 66px; }
.gs-spark::after { top: 20px; width: 48px; }
.gs-spark > span {
  position: absolute; left: 0; top: 7px; width: 15px; height: 15px;
  background: #aab5d3;
  clip-path: polygon(50% 0, 63% 37%, 100% 50%, 63% 63%,
                     50% 100%, 37% 63%, 0 50%, 37% 37%);
}

/* ---- the four doors ---- */
.gs-main { padding: 18px 0 0; }
.gh-grid {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  column-gap: 26px; row-gap: 18px;
}
.gh-card {
  position: relative; display: block; overflow: hidden; isolation: isolate;
  border-radius: 16px; color: #fff;
  background: linear-gradient(118deg, var(--gh-a) 0%, var(--gh-b) 100%);
  box-shadow: 0 2px 5px rgba(0, 0, 0, .23);
  transition: transform .18s ease, box-shadow .18s ease;
}
/* The mock's two row heights, by POSITION rather than by a class on the card.
   tests/test_games_hub.py pins the card's class attribute to exactly
   `gh-card gh-<game>` followed immediately by its href — one extra class in
   there and the contract regex stops matching, which is the contract doing
   its job. nth-child says the same thing and cannot collide with it. */
.gh-grid > .gh-card:nth-child(-n+2) { height: 248px; }
.gh-grid > .gh-card:nth-child(n+3) { height: 239px; }
.gh-card:hover { transform: translateY(-2px); box-shadow: 0 6px 14px rgba(0, 0, 0, .22); }
.gh-card:active { transform: translateY(0); }
.gh-card:focus-visible { outline: 3px solid rgba(16, 37, 185, .45); outline-offset: 3px; }

.gh-damage { --gh-a: #0871db; --gh-b: #003887; --gh-badge: rgba(0, 28, 69, .82); --gh-go-ink: #07369a; }
.gh-zoomed { --gh-a: #409d70; --gh-b: #147145; --gh-badge: rgba(13, 73, 55, .84); --gh-go-ink: #27744b; }
.gh-crosstown { --gh-a: #f1a600; --gh-b: #eba000; --gh-badge: rgba(157, 95, 0, .78); --gh-go-ink: #b97800; }
.gh-demoday { --gh-a: #ee5815; --gh-b: #df3519; --gh-badge: rgba(153, 42, 10, .82); --gh-go-ink: #bd3715; }

.gh-art {
  position: absolute; z-index: 1; top: 0; right: 0;
  height: 100%; width: auto; max-width: none;
  pointer-events: none; user-select: none;
}
/* The art carries its own ground and on a narrow card it reaches the type.
   A navy wash from the left keeps white copy on a dark ground at every
   width — including the amber card, the one place the mock's own drawing
   put white below 3:1. */
.gh-card::after {
  content: ""; position: absolute; z-index: 2; inset: 0; pointer-events: none;
  background: linear-gradient(90deg,
    rgba(0, 20, 47, .54) 0%, rgba(0, 20, 47, .42) 30%,
    rgba(0, 20, 47, .15) 56%, rgba(0, 20, 47, 0) 76%);
}
.gh-copy {
  position: relative; z-index: 3; display: block;
  padding: 26px 0 0 30px; max-width: 62%;
  text-shadow: 0 1px 2px rgba(0, 0, 0, .30);
}
.gh-name {
  display: block; font-family: var(--ui); font-weight: 900;
  font-size: clamp(32px, 4vw, 56px); line-height: 1;
  letter-spacing: -.04em; text-transform: uppercase;
}
.gh-pitch {
  display: block; margin: 12px 0 0;
  font-size: 19px; line-height: 23px; font-weight: 700; letter-spacing: -.012em;
}
.gh-no {
  position: absolute; z-index: 4; top: 14px; right: 14px;
  width: 57px; height: 57px; border-radius: 50%;
  display: grid; place-items: center;
  background: var(--gh-badge); color: #fff;
  font-size: 21px; font-weight: 900; letter-spacing: -.02em;
  font-variant-numeric: tabular-nums;
}
/* No number, no disc. The round arrives from the game's own data file, and a
   badge that cannot say which round it is says nothing instead. */
.gh-no:empty { display: none; }
.gh-go {
  position: absolute; z-index: 5; left: 30px; bottom: 24px;
  min-width: 127px; height: 47px; padding: 0 18px;
  border-radius: 15px; background: linear-gradient(#fff, #f8f8f8);
  color: var(--gh-go-ink); display: grid; place-items: center;
  font-size: 18px; font-weight: 900; letter-spacing: .03em; text-transform: uppercase;
  box-shadow: 0 2px 3px rgba(0, 0, 0, .14);
  transition: transform .15s ease, background .15s ease;
}
.gh-card:hover .gh-go { transform: scale(1.04); background: #fff; }

/* ---- the scoreboard. The mock drew this with absolute offsets around three
   sample names; real names run to 20 characters, so it is flex here. Ships
   hidden and its script unhides it — every number in it comes from
   localStorage or /api/scores, and neither exists without JavaScript. ---- */
.gs-board {
  margin-top: 17px; border: 1px solid #dedede; border-radius: 16px;
  background: #fff; box-shadow: 0 1px 4px rgba(0, 0, 0, .08);
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.2fr) minmax(0, .62fr);
  overflow: hidden;
}
.gs-board[hidden] { display: none; }
.gs-cell { padding: 15px 22px; min-width: 0; }
.gs-cell + .gs-cell { border-left: 1px solid #e5e5e5; }
.gs-cap {
  margin: 0 0 11px; display: flex; align-items: center; gap: 8px;
  font-size: 13px; font-weight: 900; letter-spacing: .03em; text-transform: uppercase;
}
.gs-note { margin: 10px 0 0; color: var(--gs-ink-2); font-size: 11.5px; line-height: 1.45; }

.gs-streak { display: flex; align-items: center; gap: 15px; }
.gs-flame { flex: 0 0 auto; font-size: 38px; line-height: 1; }
.gs-streak-n { margin: 0; display: flex; align-items: baseline; gap: 7px; }
.gs-streak-n b { font-size: 34px; font-weight: 900; line-height: 1; font-variant-numeric: tabular-nums; }
.gs-streak-n span {
  font-size: 12px; font-weight: 700; letter-spacing: .06em;
  text-transform: uppercase; color: var(--gs-ink-2);
}
.gs-dots { display: flex; align-items: center; gap: 7px; margin-top: 10px; }
.gs-dot {
  width: 20px; height: 20px; border-radius: 50%;
  display: grid; place-items: center;
  background: #e7e7e4; color: #fff;
  box-shadow: inset 0 -1px 1px rgba(0, 0, 0, .10);
}
.gs-dot.is-done { background: #3f8735; }
.gs-dot svg { width: 12px; height: 12px; display: block; }
.gs-dot:not(.is-done) svg { visibility: hidden; }

.gs-rows { display: flex; flex-direction: column; gap: 6px; }
.gs-row { display: flex; align-items: center; gap: 10px; min-width: 0; height: 32px; }
.gs-mono {
  flex: 0 0 28px; width: 28px; height: 28px; border-radius: 50%;
  display: grid; place-items: center; color: #fff;
  font-size: 11px; font-weight: 900; background: var(--gs-mono, #2447e0);
}
/* Each disc in its own game's accent, darkened where the card's hue could not
   hold white type at 11px. This is what stands in for the mock's three
   generated avatar faces: a board row is a handle a reader typed, and putting
   an invented face on it invents a person. */
.gs-row[data-board="damage"] { --gs-mono: #0b57c4; }
.gs-row[data-board="zoomed"] { --gs-mono: #227a4e; }
.gs-row[data-board="crosstown"] { --gs-mono: #97690a; }
.gs-row[data-board="demoday"] { --gs-mono: #c9421a; }
.gs-row-game {
  flex: 0 0 84px; font-size: 11px; font-weight: 800;
  letter-spacing: .05em; text-transform: uppercase; color: var(--gs-ink-2);
}
.gs-row-name {
  flex: 1 1 auto; min-width: 0; font-size: 13px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.gs-row-name.is-empty { color: var(--gs-ink-3, #63676f); font-style: italic; }
.gs-row-score { flex: 0 0 auto; font-size: 13px; font-weight: 800; font-variant-numeric: tabular-nums; }

.gs-tally b { display: block; font-size: 27px; font-weight: 900; line-height: 1.1; font-variant-numeric: tabular-nums; }

.gs-colophon {
  margin: 0; padding: 15px 0 6px; text-align: center;
  color: #62646b; font-family: var(--ui); font-size: 12px;
}

/* ---- the account strip. Ships hidden; its script unhides whichever of its
   three views is true (signed out / link sent / signed in), so the first
   paint never shows a control that cannot work and nothing rearranges
   itself. Everything a reader can click talks to /api/reader-auth. ---- */
.gs-signin {
  margin-top: 17px; border: 1px solid #dedede; border-radius: 16px;
  background: #fff; box-shadow: 0 1px 4px rgba(0, 0, 0, .08);
  padding: 15px 22px;
}
.gs-signin[hidden] { display: none; }
.gs-si-view[data-si-view="in"] {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 6px 18px;
}
.gs-si-view[hidden] { display: none; }
.gs-si-pitch { margin: 0; font-size: 14px; line-height: 1.5; }
.gs-si-form {
  display: flex; flex-wrap: wrap; align-items: center; gap: 10px; margin-top: 11px;
}
.gs-si-mail {
  flex: 1 1 220px; min-width: 0; height: 42px; padding: 0 13px;
  border: 1px solid #cfcfcf; border-radius: 11px;
  font: inherit; font-size: 14px; background: #fff; color: var(--gs-ink);
}
.gs-si-mail:focus-visible { outline: 2px solid var(--gs-blue); outline-offset: 1px; }
.gs-si-send {
  height: 42px; padding: 0 18px; border: 0; border-radius: 11px;
  background: var(--gs-blue); color: #fff; cursor: pointer;
  font-family: var(--ui); font-size: 13px; font-weight: 800; letter-spacing: .02em;
}
.gs-si-send:hover { background: var(--gs-navy); }
.gs-si-google {
  height: 42px; padding: 0 16px; border: 1px solid #cfcfcf; border-radius: 11px;
  display: inline-flex; align-items: center;
  font-family: var(--ui); font-size: 13px; font-weight: 800; color: var(--gs-ink);
}
.gs-si-google:hover { border-color: var(--gs-blue); color: var(--gs-blue); }
.gs-si-note { margin: 9px 0 0; font-size: 12.5px; color: #a33c2e; }
.gs-si-links { display: inline-flex; flex-wrap: wrap; gap: 14px; }
.gs-si-links button {
  border: 0; background: none; padding: 0; cursor: pointer;
  font-family: var(--ui); font-size: 12.5px; font-weight: 700;
  color: var(--gs-blue); text-decoration: underline;
}
.gs-si-links button:hover { color: var(--gs-navy); }

@media (max-width: 1040px) {
  .gs-hero-art.at-left, .gs-hero-art.at-right { width: 33%; }
  .gs-spark { display: none; }
  .gh-copy { max-width: 66%; }
  .gs-board { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
  .gs-board .gs-cell:nth-child(3) {
    grid-column: 1 / -1; border-left: 0; border-top: 1px solid #e5e5e5;
  }
}
@media (max-width: 760px) {
  .gs-edge { width: calc(100% - 28px); }
  .gs-hero { padding: 8px 0 14px; }
  .gs-hero-art.at-left { left: -9%; width: 44%; }
  .gs-hero-art.at-right { right: -9%; width: 44%; }
  .gs-hero-center { background: radial-gradient(70% 82% at 50% 46%,
                    rgba(255, 255, 255, .94) 54%, rgba(255, 255, 255, 0) 100%); }
  .gs-hero h1 { font-size: clamp(44px, 13.5vw, 76px); }
  .gs-hero-sub { font-size: 15.5px; line-height: 22px; }
  .gh-grid { grid-template-columns: 1fr; row-gap: 14px; }
  .gh-card.is-top, .gh-card.is-bottom { height: 212px; }
  .gh-copy { padding: 20px 0 0 20px; max-width: 70%; }
  .gh-pitch { margin-top: 9px; font-size: 16.5px; line-height: 21px; }
  .gh-no { top: 12px; right: 12px; width: 46px; height: 46px; font-size: 17px; }
  .gh-go { left: 20px; bottom: 18px; min-width: 106px; height: 42px; font-size: 16px; }
  .gs-board, .gs-board .gs-cell:nth-child(3) { grid-template-columns: 1fr; }
  .gs-signin { padding: 13px 14px; }
  .gs-si-send, .gs-si-google { flex: 1 1 auto; justify-content: center; text-align: center; }
  .gs-cell + .gs-cell { border-left: 0; border-top: 1px solid #e5e5e5; }
  .gs-latest-inner { gap: 12px; }
  .gs-latest-label, .gs-latest-time { font-size: 12.5px; }
  .gs-latest-head { font-size: 13.5px; }
}
@media (prefers-reduced-motion: reduce) {
  .gh-card, .gh-go, .gs-latest-arrow { transition: none; }
  .gh-card:hover, .gh-card:hover .gh-go { transform: none; }
}
