/* Easy Tracking Games — web app.
   Loads the site's tokens from ../styles.css first, then dresses them as an
   app shell: a fixed chrome at the top, one scrolling grid underneath. */

body {
  min-height: 100%;
  padding-bottom: 40px;
}

/* .empty, .grid and friends set display, which beats the UA rule for [hidden]. */
[hidden] { display: none !important; }

.app-header {
  position: sticky;
  top: env(safe-area-inset-top, 0px);
  z-index: 30;
  background: color-mix(in srgb, var(--ground) 92%, transparent);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--rim);
}

.app-header .bar {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 16px;
  max-width: 1200px;
  margin-inline: auto;
}

.app-brand {
  display: flex;
  align-items: center;
  gap: 9px;
  font-family: var(--display);
  font-weight: 700;
  font-size: 0.98rem;
  color: var(--ink);
  text-decoration: none;
  margin-right: auto;
  white-space: nowrap;
}

.app-brand img { width: 28px; height: 28px; }
.app-brand span { display: none; }
@media (min-width: 560px) { .app-brand span { display: inline; } }

.btn {
  font: inherit;
  font-size: 0.9rem;
  padding: 7px 14px;
  border-radius: 999px;
  border: 1px solid var(--rim);
  background: var(--surface-2);
  color: var(--ink);
  cursor: pointer;
  white-space: nowrap;
}

.btn:hover { border-color: var(--accent); color: var(--accent); }

.btn.primary {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--accent-ink);
  font-weight: 600;
}

.btn.primary:hover { filter: brightness(1.08); color: var(--accent-ink); }
.btn.quiet { background: transparent; }
/* Danger has no hue of its own now: the brand is red, so a second red
   would read as decoration rather than warning. The two-tap confirm is
   what makes deleting deliberate. */
.btn.danger:hover { border-color: var(--accent); color: var(--accent); }
.btn[aria-pressed="true"] { border-color: var(--accent); color: var(--accent); background: var(--accent-wash); }

.tabs {
  display: flex;
  gap: 8px;
  overflow-x: auto;
  padding: 0 16px 10px;
  max-width: 1200px;
  margin-inline: auto;
  scrollbar-width: none;
}

.tabs::-webkit-scrollbar { display: none; }

.tab {
  font: inherit;
  font-size: 0.88rem;
  padding: 6px 14px;
  border-radius: 999px;
  border: 1px solid var(--rim);
  background: transparent;
  color: var(--ink-soft);
  cursor: pointer;
  white-space: nowrap;
}

.tab[aria-selected="true"] {
  background: var(--accent-wash);
  border-color: var(--accent);
  color: var(--accent);
  font-weight: 600;
}

.tab .count {
  font-family: var(--mono);
  font-size: 0.76rem;
  opacity: 0.75;
  margin-left: 6px;
}

.page {
  max-width: 1200px;
  margin-inline: auto;
  padding: 18px 16px 0;
}

.toolbar {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  align-items: center;
  margin-bottom: 16px;
}

input[type="text"],
input[type="search"],
input[type="password"],
input[type="number"],
textarea,
select {
  font: inherit;
  font-size: 0.95rem;
  padding: 9px 13px;
  border-radius: 10px;
  border: 1px solid var(--rim);
  background: var(--surface);
  color: var(--ink);
  width: 100%;
}

textarea { resize: vertical; min-height: 84px; }
.grow { flex: 1 1 220px; min-width: 0; }

.muted { color: var(--ink-soft); font-size: 0.9rem; }
.mono { font-family: var(--mono); }

/* ---------- cover grid ---------- */

.grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(var(--tile, 140px), 1fr));
  gap: 16px;
  /* Every tile is the same 3:4 shape now, as on the phone, so the grid is an
     ordinary one again -- no row spans, no measuring. That only worked while
     covers arrived in every shape; see .cover. */
  align-items: start;
  padding-bottom: 40px;
}

.card {
  position: relative;   /* the status menu hangs off it */
  display: flex;
  flex-direction: column;
  gap: 7px;
  text-align: left;
}

/* The cover and the title are separate buttons inside the card, so which
   action you get is decided by what you tapped — the same split as the phone,
   where the cover opens the game and the title changes its status. */
.cover-button,
.card .name {
  font: inherit;
  color: inherit;
  background: none;
  border: 0;
  padding: 0;
  text-align: left;
  cursor: pointer;
  width: 100%;
}

.cover {
  position: relative;
  /* 3:4 for every tile, cropped to fill, which is exactly what the iOS app
     does (CoverImage in Badges.swift). Store box art is 2:3 and loses a
     sliver; the shelf reads as a shelf. */
  aspect-ratio: 3 / 4;
  border-radius: 10px;
  overflow: hidden;
  background: linear-gradient(150deg, var(--surface-2), var(--surface));
  border: 1px solid var(--rim);
}

/* One shape for every tile, filled by cropping.

   This was a per-picture shape for a while, because covers arrived in every
   shape and forcing one cropped most of them to a slice. That was a workaround
   for the art, not a design: RAWG has no box art at all, so the library was a
   wall of 16:9 wallpaper and the grid had to accommodate it. With the store's
   own pack shots the shape is the right one, and matching the phone matters
   more than accommodating a picture that should not be there. */
.cover img { width: 100%; height: 100%; object-fit: cover; display: block; }

.cover .placeholder-art {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  padding: 10px;
  text-align: center;
  font-family: var(--display);
  font-size: 0.85rem;
  color: var(--ink-faint);
}

/* Two discs in the cover's top-right corner, the same pair and the same
   corner as the phone. In the grid they sit over the cover button rather than
   inside it, so .card is their positioning context there; in the detail panel
   .cover is. Both are position: relative, so one rule covers both. */
.badges {
  position: absolute;
  top: 6px;
  right: 6px;
  display: flex;
  flex-direction: column;
  gap: 5px;
  align-items: flex-end;
  z-index: 2;
}

.badge {
  width: 22px;
  height: 22px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  color: #fff;
  background: rgba(0, 0, 0, 0.55);
  border: 1px solid rgba(0, 0, 0, 0.35);
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.4);
  /* The brand colour is set from marks.js, so the four stores are defined in
     one place shared with the phone rather than in a stylesheet of their own. */
}

.badge svg { display: block; }

/* No store yet: a question mark, so the menu that assigns one is still
   reachable from the grid. The phone shows the same stand-in. */
.badge.unknown {
  font-family: var(--mono);
  font-size: 0.7rem;
  font-weight: 600;
}

/* Status is deliberately not brand-coloured: the disc above it already
   carries one, and two coloured discs stacked in a corner fight each other. */
.badge.status { background: rgba(11, 11, 12, 0.74); }

.badge.tappable { cursor: pointer; }
.badge.tappable:hover { border-color: rgba(255, 255, 255, 0.5); }
.badge.tappable:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* Kept for the add-game results, which show a status without a game to hang a
   menu on. The grid and the detail panel use the disc above instead. */
.status-pill {
  position: absolute;
  left: 6px;
  bottom: 6px;
  padding: 2px 9px;
  border-radius: 999px;
  background: rgba(11, 11, 12, 0.85);
  border: 1px solid rgba(255, 255, 255, 0.16);
  color: #f5f2ec;
  font-family: var(--mono);
  font-size: 0.62rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.card .name {
  font-size: 0.92rem;
  font-weight: 600;
  line-height: 1.25;
  color: var(--ink);
}

.card .name:hover { color: var(--accent); }

.status-menu {
  position: absolute;
  z-index: 25;
  left: 0;
  right: 0;
  top: 100%;
  margin-top: 4px;
  display: grid;
  gap: 1px;
  background: var(--rim);
  border: 1px solid var(--rim);
  border-radius: 10px;
  overflow: hidden;
  box-shadow: 0 14px 34px rgba(0, 0, 0, 0.45);
}

.status-item {
  font: inherit;
  font-size: 0.86rem;
  text-align: left;
  padding: 9px 12px;
  border: 0;
  background: var(--surface);
  color: var(--ink);
  cursor: pointer;
}

/* Section headings, so Status and Outcome are told apart in one menu -- the
   same grouping the phone's context menu uses. */
.menu-heading {
  font-family: var(--mono);
  font-size: 0.62rem;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--ink-faint);
  background: var(--surface);
  padding: 8px 12px 4px;
}

.status-item:hover { background: var(--surface-2); color: var(--accent); }
.status-item.current { color: var(--accent); font-weight: 600; }
.status-item.current::after { content: " ·"; }

.card .meta {
  font-family: var(--mono);
  font-size: 0.75rem;
  color: var(--ink-faint);
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
}

.card .meta .rating { color: var(--accent); }
.rank {
  font-family: var(--display);
  font-size: 0.95rem;
  color: var(--ink-faint);
  font-variant-numeric: tabular-nums;
}

/* ---------- empty state ---------- */

.empty {
  border: 1px dashed var(--rim);
  border-radius: var(--radius);
  padding: 34px 24px;
  text-align: center;
  display: grid;
  gap: 12px;
  justify-items: center;
  color: var(--ink-soft);
}

.empty h2 { font-size: 1.2rem; color: var(--ink); }

/* ---------- panels: detail, add, settings ---------- */

.overlay {
  position: fixed;
  inset: 0;
  z-index: 40;
  background: rgba(5, 5, 6, 0.62);
  display: grid;
  justify-items: end;
}

.overlay[hidden] { display: none !important; }

.panel {
  width: min(520px, 100%);
  height: 100%;
  overflow-y: auto;
  background: var(--ground);
  border-left: 1px solid var(--rim);
  padding: 20px 20px calc(40px + env(safe-area-inset-bottom, 0px));
  display: grid;
  gap: 16px;
  align-content: start;
}

.panel-head {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  justify-content: space-between;
}

.panel h2 { font-size: 1.35rem; }

.field { display: grid; gap: 7px; }

.field label,
.legend {
  font-family: var(--mono);
  font-size: 0.7rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-faint);
}

.detail-head {
  display: flex;
  align-items: flex-start;
  gap: 16px;
}

.detail-head .stack { gap: 6px; }

.detail-cover {
  width: 132px;
  border-radius: 10px;
  border: 1px solid var(--rim);
  overflow: hidden;
  flex: none;
}

.slider-row { display: flex; align-items: center; gap: 12px; }
input[type="range"] { flex: 1; accent-color: var(--accent); }
.rating-value {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  min-width: 3.4em;
  text-align: right;
  color: var(--accent);
}

.chip-btn {
  font: inherit;
  font-size: 0.85rem;
  padding: 6px 13px;
  border-radius: 999px;
  border: 1px solid var(--rim);
  background: var(--surface-2);
  color: var(--ink-soft);
  cursor: pointer;
}

.chip-btn[aria-pressed="true"] {
  border-color: var(--accent);
  background: var(--accent-wash);
  color: var(--accent);
  font-weight: 600;
}

.row-actions { display: flex; gap: 10px; flex-wrap: wrap; }

/* ---------- toast ---------- */

.toast {
  position: fixed;
  left: 50%;
  transform: translateX(-50%);
  bottom: calc(22px + env(safe-area-inset-bottom, 0px));
  z-index: 60;
  background: var(--surface-2);
  border: 1px solid var(--accent);
  color: var(--ink);
  padding: 11px 18px;
  border-radius: 999px;
  font-size: 0.9rem;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.4);
  max-width: min(92vw, 520px);
}

.toast[hidden] { display: none !important; }

/* ---------- misc ---------- */

.stack { display: grid; gap: 14px; }
.inline-note {
  border-left: 3px solid var(--accent);
  background: var(--accent-wash);
  padding: 12px 15px;
  border-radius: 0 8px 8px 0;
  font-size: 0.9rem;
  color: var(--ink);
}

.spread { display: flex; justify-content: space-between; align-items: center; gap: 12px; flex-wrap: wrap; }
hr.sep { border: 0; border-top: 1px solid var(--rim); margin: 4px 0; }
