/* ---------------------------------------------------------------------------
   Points, achievements and the toast that announces them.
   Loaded on every page, after style.css, so it inherits the palette rather
   than defining one. No radius anywhere: the global reset in style.css strips
   it, and this file does not fight that.
   --------------------------------------------------------------------------- */

/* ---- the chip in the top nav --------------------------------------------- */

.xpchip {
  margin-left: auto;
  display: flex;
  align-items: baseline;
  gap: 10px;
  text-decoration: none;
  white-space: nowrap;
  border-left: 1px solid var(--rule);
  padding-left: clamp(14px, 1.6vw, 26px);
}
.xpchip .lv { color: var(--ink); font-weight: 600; }
.xpchip .xp {
  font-family: var(--mono);
  font-size: 0.76rem;
  color: var(--accent);
  font-variant-numeric: tabular-nums;
}
.xpchip:hover .lv { color: var(--accent); }
@media (max-width: 700px) {
  .xpchip { margin-left: 0; border-left: none; padding-left: 0; }
  .xpchip .lv { font-weight: 500; }
}

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

.ach-toasts {
  position: fixed;
  right: clamp(12px, 2vw, 28px);
  bottom: clamp(12px, 2vw, 28px);
  z-index: 60;
  display: flex;
  flex-direction: column;
  gap: 10px;
  align-items: flex-end;
  pointer-events: none;
}
.ach-toast {
  width: min(320px, calc(100vw - 32px));
  background: var(--paper);
  /* A hairline, not an accent bar down one side: that is the card tell the
     rest of this site avoids, and a toast is not exempt. The kicker carries
     the accent instead. */
  border: 1px solid var(--rule);
  padding: 12px 16px;
  display: flex;
  flex-direction: column;
  gap: 2px;
  /* Starts visible-but-displaced rather than at opacity 0, so a dropped
     animation frame still leaves a readable toast on screen. */
  opacity: 0.001;
  transform: translateX(14px);
  transition: opacity 260ms cubic-bezier(0.16, 1, 0.3, 1),
              transform 260ms cubic-bezier(0.16, 1, 0.3, 1);
}
.ach-toast.shown { opacity: 1; transform: none; }
/* Tap or click a toast to send it away early. */
.ach-toast.dismissable { pointer-events: auto; cursor: pointer; }

/* On a phone the side panel sits under the board, so the bottom of the screen
   is where the leaderboard name box lands after a win. Toasts go to the top
   instead, just under the sticky nav (68px when it wraps to two lines). */
@media (max-width: 760px) {
  .ach-toasts {
    top: calc(env(safe-area-inset-top, 0px) + 76px);
    bottom: auto;
  }
}
.ach-kicker {
  font-family: var(--mono);
  /* 0.7rem is 11.2px, the floor for functional text; 0.62rem was 9.9px. */
  font-size: 0.7rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--accent);
}
.ach-name { font-family: var(--display); font-weight: 700; font-size: 1.05rem; }
.ach-desc { font-size: 0.82rem; color: var(--muted); }
.ach-xp {
  font-family: var(--mono);
  font-size: 0.72rem;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
  margin-top: 4px;
}
/* Several unlocked at once: a name per row with its XP on the right, then the
   total on its own line. Hairlines between rows, as everywhere else. */
.ach-list { display: flex; flex-direction: column; margin-top: 4px; }
.ach-row {
  display: flex; justify-content: space-between; align-items: baseline; gap: 12px;
  padding-block: 5px; border-top: 1px solid var(--rule);
}
.ach-row:first-child { border-top: 0; }
.ach-row .ach-name { font-size: 0.95rem; }
.ach-row .ach-xp { margin-top: 0; color: var(--muted); }
.ach-total { border-top: 1px solid var(--ink); padding-top: 6px; text-align: right; }
@media (prefers-reduced-motion: reduce) {
  .ach-toast { transition: none; opacity: 1; transform: none; }
}

/* ---- the rank meter ------------------------------------------------------ */

.rankbar { display: flex; flex-direction: column; gap: 10px; }
.rankbar .top {
  display: flex; flex-wrap: wrap; align-items: baseline;
  gap: 6px clamp(16px, 2vw, 32px);
}
.rankbar .lvl { font-family: var(--display); font-weight: 700; font-size: clamp(1.6rem, 3vw, 2.4rem); }
.rankbar .num {
  font-family: var(--mono); font-size: 0.8rem; color: var(--muted);
  font-variant-numeric: tabular-nums;
}
.rankbar .num b { color: var(--accent); font-weight: 500; }
/* The one-line version in the arcade header. */
.rankbar.compact { gap: 8px; max-width: 58ch; }
.rankbar.compact .lvl { font-size: 1.1rem; }
.rankbar.compact .meter { height: 4px; }
.rankbar .achlink {
  font-family: var(--mono); font-size: 0.8rem; color: var(--muted);
  text-decoration: none; border-bottom: 1px solid var(--rule); margin-left: auto;
}
.rankbar .achlink:hover { color: var(--accent); border-color: var(--accent); }
.meter { height: 6px; background: var(--code-bg); width: 100%; }
.meter i { display: block; height: 100%; background: var(--accent); }

/* ---- the achievement list ------------------------------------------------ */

.achs { display: flex; flex-direction: column; border-top: 1px solid var(--rule); }
.ach {
  display: grid;
  grid-template-columns: 1.6em minmax(0, 20ch) minmax(0, 1fr) auto;
  gap: 4px 18px;
  align-items: baseline;
  padding-block: 12px;
  border-bottom: 1px solid var(--rule);
}
.ach .tick { font-family: var(--mono); font-size: 0.82rem; color: var(--accent); }
.ach .n { font-weight: 600; }
.ach .d { color: var(--muted); font-size: 0.88rem; }
.ach .p {
  font-family: var(--mono); font-size: 0.74rem; color: var(--muted);
  font-variant-numeric: tabular-nums; text-align: right; white-space: nowrap;
}
/* Locked rows stay legible rather than being grayed into the background: you
   are meant to read them and want them. */
.ach.locked .n { font-weight: 400; color: var(--muted); }
.ach.locked .tick { color: var(--rule); }
@media (max-width: 720px) {
  .ach { grid-template-columns: 1.6em minmax(0, 1fr) auto; }
  .ach .d { grid-column: 2 / -1; }
}

/* ---- the per-game box in the side panel ---------------------------------- */

.ach-mini { display: flex; flex-direction: column; gap: 7px; }
.ach-mini .arow { display: flex; align-items: baseline; gap: 9px; font-size: 0.84rem; }
.ach-mini .arow .tick { font-family: var(--mono); font-size: 0.78rem; color: var(--accent); }
.ach-mini .arow.locked { color: var(--muted); }
/* Unlocked by the run that just ended. */
.ach-mini .arow.fresh { font-weight: 600; }
.ach-mini .arow.locked .tick { color: var(--rule); }
.ach-mini .arow .want {
  margin-left: auto; font-family: var(--mono); font-size: 0.7rem;
  color: var(--muted); font-variant-numeric: tabular-nums; white-space: nowrap;
}

/* ---- the summary strip on the arcade index ------------------------------- */

.ach-sum {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 14px clamp(20px, 3vw, 44px);
  border-top: 1px solid var(--rule);
  padding-top: 16px;
}
.ach-sum .cell { display: flex; flex-direction: column; gap: 2px; }
.ach-sum .k {
  font-family: var(--mono); font-size: 0.7rem; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--muted);
}
.ach-sum .v {
  font-family: var(--display); font-weight: 700; font-size: 1.5rem;
  font-variant-numeric: tabular-nums;
}
