/* ============================================================================
   The platform's account pages — /sign-in/, /sign-up/, /account/ — rebuilt
   natively from the 4 of a Kind Worker that served them (docs/4oak-merge-plan.md
   §3). These rules are that app's own (app/globals.css: the base, the stat and
   badge grids, the account block, and the .platform-page graphite + ember
   override), so the pages look as they did. The oak plate and gold dust are
   switched off by the override, as before.
   ========================================================================== */
:root {
  /* WARM — a lamplit workbench, in bronze and parchment.

     Everything here used to be cool: a graphite room, brushed-SILVER chrome,
     navy tiles. That was coherent on its own, but the board is the only
     surface on the site still built that way — the storefront cover, the OG
     card and the board's own oak backdrop are all Campfire now, and the
     difficulty ramp went warm when the NYT colours came out. A cool tray
     holding a warm ramp reads as two designs sharing a screen.

     So the metal is now aged BRONZE rather than brushed silver, and the tiles
     are warm charcoal rather than navy. The names moved with the values —
     --silver-* would have been a lie the moment it held #866d47, and this file
     already learned that lesson once with --ok. */
  --bg: #1a1512; /* warm graphite wall — panels/sheets sit on this */
  /* Body only. The oak plate is warm, so a cool flash before it decodes would
     be visible; this is the plate's own darkest tone. */
  --bg-board: #17120f;
  --bg-glow: rgba(246, 181, 63, 0.055); /* warm lamp, top of the room */
  --panel: #241f1d; /* Campfire --cf-surface — banners, cards, rows */
  --panel-top: #2e2724; /* Campfire --cf-raised — panel sheen top */
  /* BRONZE — the board tray and the chrome. Aged, not polished: kept well
     below the flame rank (#f6b53f) in both lightness and saturation so a
     solved Flame bar still reads as the brightest gold on screen. */
  --bronze: #866d47; /* bronze mid — board frame body */
  --bronze-hi: #c2a271; /* bronze highlight (sheen / lit edge) */
  --bronze-lo: #4a3a26; /* bronze shadow / recess */
  --chip: #58462e; /* darker bronze — control chips */
  --chip-top: #6d5839;
  --warm-line: #3d332b; /* warm hairline — borders, dividers */
  --text: #f7efe4; /* Campfire --cf-cream */
  --muted: #b8a696; /* Campfire --cf-muted (AA on bg + panel) */
  --ink-metal: #241a12; /* dark ink for text on bright bronze */
  --tile: #2a2320; /* warm neutral, for tracks/toggle backs */
  /* TILES — warm charcoal plaques. They were navy, which was the last cool
     field of any size on the board. Charcoal keeps the same job the navy did:
     a dark, quiet face that makes the tray read as metal holding something,
     and that a gold selection ring can sit on without competing. Cream text
     (#f7efe4) on the darkest of these measures ~13:1. */
  --tile-top: #342c26; /* plaque face, lit edge */
  --tile-bot: #262019; /* plaque face, shadowed edge (bevel gradient) */
  --tile-sel: #4a3c2f; /* lifted/lit */
  --tile-sel-top: #58483a;
    /* GOLD — Empire brand accent (thin accents only, never large fills) */
  --gold: #c9a84c; /* brand antique gold */
  --gold-light: #dfb573; /* brand gold sheen */
  --gold-deep: #8a6d2c; /* brand deep bronze */
  --accent: var(--gold); /* accent is now brand gold (was terracotta) */
  --bad: #f96a5f; /* warm coral-red — mistakes/errors */
  --edge: rgba(0, 0, 0, 0.42); /* carved edge shadow */
  --lift: rgba(255, 238, 214, 0.07); /* warm metal top highlight */
  /* Fine directional grain for brushed-metal surfaces (frame + chips). */
  --brush: repeating-linear-gradient(
    100deg,
    rgba(255, 255, 255, 0.05) 0 1px,
    rgba(0, 0, 0, 0.045) 1px 3px
  );
  /* The signature Empire gold shimmer (135°, lighter band at 50%). */
  --gold-shimmer: linear-gradient(
    135deg,
    var(--gold) 0%,
    var(--gold-light) 50%,
    var(--gold) 100%
  );
  /* Struck-bronze ramp with a hot specular band at 50% — for the wordmark,
     clipped to the glyphs. Was a polished-SILVER ramp, which made the game's
     own name the coolest thing on the board. Its lightest stops are cream
     rather than white so it stays inside the Campfire palette. */
  --bronze-shimmer: linear-gradient(
    176deg,
    #fff6e6 0%,
    #e0c391 20%,
    #ab8a55 43%,
    #fffaf0 50%,
    #8e7040 57%,
    #c0a069 78%,
    #e8d3ab 100%
  );
  /* ── Difficulty ramp: THE CAMPFIRE, burning down ──────────────────────
     Was yellow → green → blue → violet, which is the NYT Connections ramp
     note for note; it was replaced on legal advice and re-cut from the
     Expedition Games Campfire palette (--cf-coral #e6552e, --cf-gold #f6b53f,
     --cf-cream #f7efe4), which the rest of the hub is converging on.

     The ramp is a fire seen top to bottom: pale ASH on the surface, the
     FLAME above the fuel, the glowing EMBER under it, and the black-red COAL
     at the heart — easiest to hardest, going deeper and hotter.

     Why a one-family warm ramp beats four unrelated hues: these four separate
     by LIGHTNESS (≈91% → 72% → 52% → 33% relative luminance steps), and
     lightness is the one channel every form of colour-vision deficiency
     keeps. The old blue/violet pair had to be hand-nudged to stop collapsing
     under deuteranopia; this ramp cannot collapse, because greyscale alone
     still orders it correctly.

     Each rank carries its own ink, because rank-3 is dark enough that the
     shared dark ink would vanish on it. */
  --rank-0: #f0e3cd; /* ash    — pale spent ash            */
  --rank-1: #f6b53f; /* flame  — Campfire gold             */
  --rank-2: #e6552e; /* ember  — Campfire coral            */
  --rank-3: #8c2f1e; /* coal   — the black-red heart       */
  /* Ink per rank. 0/1 take the dark plum-brown the Campfire palette uses on
     its light chips; 2 takes the darker flame ink (coral needs it to clear
     AA); 3 inverts to cream. */
  --ink-rank-0: #3b2a1c;
  --ink-rank-1: #3b2a1c;
  --ink-rank-2: #2a1704;
  --ink-rank-3: #fbf1e6;
  /* Legacy tier aliases kept for other UI (achievements, archive badges). */
  --tier-0: var(--rank-0);
  --tier-1: var(--rank-1);
  --tier-2: var(--rank-2);
  --tier-3: var(--rank-3);
  /* The "go" accent: the Share CTA, the haptics toggle, achievement
     progress — UI that has nothing to do with difficulty. It was a plain
     success GREEN, which was fine on a cool board and is now the one cool
     thing left on a warm one. Campfire gold instead: still unmistakably
     "this is the button", and it no longer fights the room.

     Deliberately the same value as the Flame rank. They never appear in the
     same place — Flame is a solved bar in the results list, this is a control
     — and inventing a second, near-identical gold to keep them nominally
     separate would be worse than sharing one. */
  --go: #f6b53f;
  --ink-go: #2a1704; /* Campfire --cf-ink-flame, for text on --go */
  /* Clerk's widgets (app/layout.tsx appearance) read these. Same values as
     --panel / --gold / --text / --muted / --bg / --warm-line above; the
     platform pages redefine them at the bottom of this file. */
  --auth-bg: #241f1d;
  --auth-primary: #c9a84c;
  --auth-fg: #f7efe4;
  --auth-muted: #b8a696;
  --auth-input: #1a1512;
  --auth-danger: #f96a5f;
  --auth-border: #3d332b;
}

* {
  box-sizing: border-box;
}

body {
  margin: 0;
  color: var(--text);
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui,
    sans-serif;
  /* THE TABLE. The board now sits on the same dark oak the storefront cover
     is shot on — public/bg-*.jpg are derived from that very cover master by
     scripts/make-bg-plates.py, so the card and the board cannot drift apart.

     What was here before was six stacked gradients, including a fine gold +
     silver graticule meant to READ as a drafting table. With an actual table
     underneath, a drawn grid on top is two ideas fighting — and a straight
     ruled grid beats against the tile grid besides — so the graticule is gone.
     The two radial gradients stay: they are lighting, not texture, and they
     still do the work of putting a shop-light overhead and darkness at the
     edges.

     The plate is the BOTTOM layer, under both gradients. It is exposed to a
     99th-percentile luminance of 0.0075 — just under the 0.0088 of the flat
     colour it replaces — so nothing on top of it lost contrast in the swap.

     Two plates, not one: `fixed` + `cover` on a 900x1600 portrait plate would
     crop to a sliver on a desktop window. The tall one serves phone portrait,
     the wide one everything else. */
  background-color: var(--bg-board);
  background-image:
    radial-gradient(120% 70% at 50% -8%, var(--bg-glow), transparent 55%),
    radial-gradient(150% 120% at 50% 108%, rgba(0, 0, 0, 0.6), transparent 62%),
    none;
  background-size: auto, auto, cover;
  background-position: center, center, center;
  background-attachment: fixed;
  background-repeat: no-repeat;
  min-height: 100vh;
}

/* Phone portrait gets the portrait plate. */
@media (max-aspect-ratio: 1/1) {
  body {
    background-image:
      radial-gradient(120% 70% at 50% -8%, var(--bg-glow), transparent 55%),
      radial-gradient(150% 120% at 50% 108%, rgba(0, 0, 0, 0.6), transparent 62%),
      none;
  }
}

/* ─── Drifting gold dust ─────────────────────────────────────────────────
   Empire's signature "subtle background animation" (they sell it as an
   add-on; their homepage uses this exact heroDrift technique). Adapted far
   sparser/slower/fainter for a puzzle game — motes are spawned + capped by
   components/GoldDust.tsx into a fixed z-index:-1 layer, behind all content.
   Transform + opacity only (GPU-composited, no layout/paint thrash). */
@keyframes goldDrift {
  0% {
    transform: translate3d(0, 0, 0);
    opacity: 0;
  }
  12% {
    opacity: 1;
  }
  88% {
    opacity: 0.55;
  }
  100% {
    transform: translate3d(var(--dx), -102vh, 0);
    opacity: 0;
  }
}

/* Reduced motion: no drift at all. GoldDust.tsx also bails before spawning,
   this is the belt-and-braces static fallback. */
@media (prefers-reduced-motion: reduce) {
  .golddust {
    display: none !important;
  }
}

/* Faint canvas/paper tooth over the whole wall — a tiled, desaturated SVG
   noise, fixed and sitting just behind the in-flow content (z-index:-1), so
   text stays crisp on top while the background gains a tactile grain that
   matches the physical, pressable feel of the tiles and the haptics. */
body::after {
  content: '';
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  opacity: 0.06;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  background-size: 120px 120px;
}

.wrap {
  max-width: 560px;
  margin: 0 auto;
  padding: 24px 16px 64px;
}

/* ─── Hub back link ─────────────────────────────────────────────────────
   /account is served at the platform apex, so its only exit used to be the
   bottom nav — which pointed at 4 of a Kind. A brushed-steel chip at the top
   left, styled like the control chips so it reads as a real button and not
   as body copy. */
.hubnav {
  margin: 0 0 14px;
}

.hublink {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 7px 13px;
  border: 1px solid var(--warm-line);
  border-radius: 8px;
  background: linear-gradient(180deg, var(--chip-top), var(--chip));
  color: var(--text);
  font-size: 13px;
  font-weight: 700;
  text-decoration: none;
  box-shadow: inset 0 1px 0 var(--lift), 0 1px 2px var(--edge);
}

.hublink:hover {
  border-color: var(--gold-deep);
  color: var(--gold-light);
}

.hublink:focus-visible {
  outline: 2px solid var(--gold);
  outline-offset: 2px;
}

/* The game board's hub row. Matches .wrap's width and gutter so the link lines
   up with the board's left edge rather than floating at the viewport margin. */
.gamebar {
  max-width: 560px;
  margin: 0 auto;
  padding: 12px 16px 0;
}

/* ─── Brandmark: struck-metal seal + embossed nameplate ──────────────────
   The old wordmark was flat gold-gradient text. This gives the header real
   presence, matching Empire's silver-medallion-beside-serif composition: a
   struck-metal roundel (gold-ringed coin with an engraved "4") above an
   embossed brushed-silver nameplate, finished with a gold hairline rule. */
.brandmark {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  margin: 6px 0 6px;
}

/* Struck-metal seal — a domed BRONZE coin: radial metal body + concentric
   brushed grain, a brass ring, top specular + underside shadow for the dome,
   and a drop shadow so it sits proud of the page. It was silver, which put a
   cool disc directly above the wordmark. */
.seal {
  width: 46px;
  height: 46px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  background-image: repeating-radial-gradient(
      circle at 50% 42%,
      rgba(255, 255, 255, 0.06) 0 1px,
      rgba(0, 0, 0, 0.05) 1px 2px
    ),
    radial-gradient(circle at 50% 34%, #e8d3ab, #b18f57 46%, #6b5230 82%, #927549 100%);
  box-shadow: 0 0 0 2px var(--gold-deep), 0 0 0 3px rgba(0, 0, 0, 0.45),
    inset 0 1px 1px rgba(255, 255, 255, 0.55),
    inset 0 -3px 5px rgba(0, 0, 0, 0.4), 0 3px 7px rgba(0, 0, 0, 0.5);
}

/* The "4" engraved into the coin: gold shimmer fill, debossed by a light
   underside highlight + dark top line so it reads struck into the metal. */
.seal-num {
  font: 800 25px/1 Georgia, 'Times New Roman', serif;
  background: var(--gold-shimmer);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  -webkit-text-fill-color: transparent;
  filter: drop-shadow(0 -1px 0 rgba(0, 0, 0, 0.45))
    drop-shadow(0 1px 0 rgba(255, 255, 255, 0.14));
}

.title {
  position: relative;
  text-align: center;
  font-size: 34px;
  font-weight: 800;
  letter-spacing: -0.5px;
  margin: 0 0 12px;
  /* Embossed nameplate: a struck-bronze ramp clipped to the glyphs, lifted
     off the page with a stacked drop-shadow bevel (dark below, light above,
     then a soft cast shadow) so it reads as struck metal, not flat text. */
  background: var(--bronze-shimmer);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  -webkit-text-fill-color: transparent;
  filter: drop-shadow(0 1px 0 rgba(0, 0, 0, 0.55))
    drop-shadow(0 -1px 0 rgba(255, 255, 255, 0.16))
    drop-shadow(0 3px 4px rgba(0, 0, 0, 0.5));
}

/* Gold hairline rule beneath the wordmark — the Empire gold rule motif. */
.title::after {
  content: '';
  position: absolute;
  left: 50%;
  bottom: -8px;
  width: 116px;
  height: 2px;
  transform: translateX(-50%);
  border-radius: 2px;
  background: linear-gradient(
    90deg,
    transparent,
    var(--gold) 22%,
    var(--gold-light) 50%,
    var(--gold) 78%,
    transparent
  );
  opacity: 0.85;
}

.sub {
  text-align: center;
  color: var(--muted);
  font-size: 14px;
  margin: 0 0 20px;
}

.solved {
  border-radius: 11px;
  padding: 12px 14px;
  margin-bottom: 8px;
  /* Ink comes from .rank-N (see below) — it varies across the ash→coal ramp. */
  /* Painted-enamel plate: a soft top sheen and a carved bottom edge so the
     revealed bar feels like a real placard the tiles collapsed into, not a
     flat swatch. The rank color underneath (set via .rank-N) shows through. */
  background-image: linear-gradient(
    180deg,
    rgba(255, 255, 255, 0.18),
    rgba(0, 0, 0, 0.06) 55%,
    rgba(0, 0, 0, 0.14)
  );
  box-shadow: 0 1px 0 var(--lift) inset, 0 2px 5px rgba(0, 0, 0, 0.3);
}

.solved .name {
  font-weight: 800;
  text-transform: uppercase;
  font-size: 14px;
  letter-spacing: 0.5px;
}

.solved .items {
  font-size: 14px;
  margin-top: 2px;
}

.solved .why {
  font-size: 12px;
  margin-top: 4px;
  opacity: 0.75;
}

.solved.revealed {
  opacity: 0.78;
}

.solved .tag {
  display: inline-block;
  margin-left: 8px;
  padding: 1px 7px;
  border-radius: 999px;
  /* Tinted from the bar's OWN ink, so the chip stays legible whether the bar
     is pale ash (dark ink) or dark coal (cream ink). The flat rgba fallback is
     for engines without color-mix. */
  background: rgba(20, 15, 12, 0.28);
  background: color-mix(in srgb, currentColor 20%, transparent);
  font-size: 10px;
  letter-spacing: 0.4px;
  vertical-align: middle;
}

/* background-COLOR (not the shorthand) so the .solved enamel sheen gradient
   and the .tile wood gradient can both layer over the rank hue.

   Ink rides along on the same class. The ramp spans ash to coal, so no single
   ONE shared ink works across all four: dark ink dies on rank-3 and cream dies
   on rank-0. Setting `color` here means .solved bars AND the .tile.solving
   flash both get the right ink from the one class they already carry. */
.rank-0 {
  background-color: var(--rank-0);
  color: var(--ink-rank-0);
}
.rank-1 {
  background-color: var(--rank-1);
  color: var(--ink-rank-1);
}
.rank-2 {
  background-color: var(--rank-2);
  color: var(--ink-rank-2);

.nudge {
  margin-top: 12px;
}

button.nudgebtn {
  background-image: var(--brush),
    linear-gradient(180deg, var(--chip-top), var(--chip));
  color: var(--text);
  border: 1px solid var(--warm-line);
  border-radius: 999px;
  padding: 10px 20px;
  font-size: 14px;
  font-weight: 700;
  cursor: pointer;
}

button.nudgebtn:hover {
  filter: brightness(1.12);
}

.banner {
  text-align: center;
  padding: 16px;
  background-image: linear-gradient(180deg, var(--panel-top), var(--panel));
  /* A thin gold rule across the top edge marks the win/end panel as brand. */
  border: 1px solid var(--warm-line);
  border-top: 2px solid var(--gold);
  border-radius: 12px;
  margin-bottom: 16px;
  box-shadow: 0 1px 0 var(--lift) inset, 0 4px 12px rgba(0, 0, 0, 0.28);
}

.banner h2 {
  margin: 0 0 4px;
}

.banner .meta {
  color: var(--muted);
  font-size: 14px;
}

.ach {
  margin-top: 8px;
  color: var(--gold); /* brand gold for the unlock line */
  font-size: 14px;
  font-weight: 600;
}

/* ─── Share (end-of-game growth loop) ────────────────────────────────── */
.sharewrap {
  margin-top: 14px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
}

button.sharebtn {
  background-image: linear-gradient(180deg, #ffcf6a, var(--go));
  color: var(--ink-go);
  border: none;
  border-radius: 999px;
  padding: 14px 40px;
  font-size: 16px;
  font-weight: 800;
  letter-spacing: 0.3px;
  cursor: pointer;
  min-height: 48px;
  width: 100%;
  max-width: 320px;
  box-shadow: 0 1px 0 rgba(255, 255, 255, 0.28) inset, 0 3px 8px rgba(0, 0, 0, 0.3);
}

button.sharebtn:hover {
  filter: brightness(1.08);
}

button.sharebtn:active {
  transform: scale(0.98);
}

.sharemsg {
  min-height: 16px;
  color: var(--go);
  font-size: 13px;
  font-weight: 600;
}

/* ─── After the daily board ───────────────────────────────────────────────
   One puzzle a day, one attempt. There is no replay button any more, so this
   is what sits where it used to. */
.tomorrow {
  margin-top: 14px;
  padding-top: 12px;
  border-top: 1px solid var(--warm-line);
}

.tomorrow-line {
  margin: 0;
  color: var(--text);
  font-size: 14px;
  font-weight: 600;
}

button.replay {
  margin-top: 12px;
  background: transparent;
  color: var(--muted);
  border: 1px dashed var(--warm-line);
  border-radius: 999px;
  padding: 8px 18px;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
}

.toast {
  text-align: center;
  color: var(--muted);
  min-height: 20px;
  margin-top: 12px;
  font-size: 14px;
}

.authbar {
  display: flex;
  justify-content: flex-end;
  align-items: center;
  gap: 10px;
  padding: 12px 16px;
  min-height: 44px;
  /* Masthead: a brushed-silver rail finished with a thin gold hairline, so the
     header reads as structural brand chrome framing the room. */
  background-image: var(--brush),
    linear-gradient(180deg, var(--panel-top), transparent);
  border-bottom: 1px solid var(--gold);
}

.authbar button {
  background: transparent;
  color: var(--muted);
  border: 1px solid var(--warm-line);
  border-radius: 999px;
  padding: 6px 16px;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
}

.authbar button:hover {
  color: var(--text);
}

.boardnav {
  max-width: 560px;
  margin: 20px auto 40px;
  padding: 0 16px;
  text-align: center;
}

.boardnav a {
  color: var(--muted);
  text-decoration: none;
  font-size: 14px;
  font-weight: 600;
  /* A nav wide enough to wrap (the account page carries three links) must break
     BETWEEN links, not inside one — otherwise "Friends →" drops its arrow onto
     a line of its own. */
  white-space: nowrap;
}

.boardnav a:hover {
  color: var(--text);
}

/* Navs with more than one link (e.g. /account, /friends) need breathing room
   between them; single-link navs are unaffected. */
.boardnav a + a {
  margin-left: 18px;
}

.archive {
  list-style: none;
  margin: 16px 0 0;
  padding: 0;
}

.archive li {
  margin: 0 0 8px;
}

.arow {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 12px 16px;
  background: var(--panel);
  border: 1px solid var(--tile);
  border-radius: 10px;
  text-decoration: none;
  color: var(--text);
}

.arow:hover {
  border-color: var(--warm-line);
}

.adate {
  font-variant-numeric: tabular-nums;
  font-weight: 600;
}

.abadge {
  font-size: 13px;
  font-weight: 600;
}

.abadge.new {
  color: var(--text);
}

.abadge.won {
  color: var(--go);
}

.abadge.lost {
  color: var(--muted);
}
.statgrid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 8px;
  margin-top: 16px;
}

.statcard {
  background: var(--panel);
  border: 1px solid var(--tile);
  border-radius: 10px;
  padding: 14px 8px;
  text-align: center;
}

.statval {
  font-size: 26px;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
}

.statlabel {
  color: var(--muted);
  font-size: 12px;
  font-weight: 600;
  margin-top: 2px;
}

.achtitle {
  text-align: center;
  font-size: 18px;
  margin: 28px 0 12px;
}
/* Sub-heading for a game section's own achievements (left-aligned under the
   game's stat grid, smaller than the page-level Achievements heading). */
.achtitle-sm {
  text-align: left;
  font-size: 15px;
  margin: 20px 0 10px;
  color: var(--muted);
}

/* Per-game section header on the platform account page. A left-aligned title
   with a short brand-gold rule, so each game's stats read as its own block. */
.gametitle {
  font-size: 20px;
  font-weight: 800;
  letter-spacing: 0.01em;
  margin: 32px 0 6px;
  padding-bottom: 8px;
  border-bottom: 1px solid var(--tile);
}
.gametitle::after {
  content: '';
  display: block;
  width: 46px;
  height: 2px;
  margin-top: 8px;
  background: linear-gradient(90deg, #c9a84c, #dfb573);
  border-radius: 2px;
}
.gamesection {
  margin-top: 4px;
}

.achcount {
  color: var(--muted);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

.achtabs {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 6px;
  margin-bottom: 12px;
}

.achtab {
  background: transparent;
  color: var(--muted);
  border: 1px solid var(--tile);
  border-radius: 999px;
  padding: 6px 14px;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
}

.achtab.on {
  color: var(--text);
  border-color: var(--warm-line);
  background: var(--tile);
}

.achgrid {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 8px;
}

.achcard {
  background: var(--panel);
  border: 1px solid var(--tile);
  border-radius: 10px;
  padding: 12px 14px;
}

.achcard.locked {
  opacity: 0.62;
}

.achcard.unlocked {
  border-color: var(--go);
  box-shadow: inset 0 0 0 1px var(--go);
}

.achname {
  display: flex;
  align-items: center;
  gap: 7px;
  font-weight: 700;
  font-size: 14px;
}

.achtick {
  flex: none;
  font-size: 12px;
  line-height: 1;
}

.achcard.unlocked .achtick {
  color: var(--go);
}

/* A "hard" (status) badge on the account page. */
.achrare {
  margin-left: auto;
  flex: none;
  padding: 1px 7px;
  border-radius: 999px;
  font-size: 10.5px;
  font-weight: 800;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: #3a2408;
  background: linear-gradient(135deg, #f6d98a, #d9a84a 55%, #a8761f);
}

.achdesc {
  color: var(--muted);
  font-size: 13px;
  margin-top: 2px;
}

.achdate {
  color: var(--go);
  font-size: 11px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  margin-top: 4px;
}

/* Progress bar for locked, countable achievements. */
.achprog {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 8px;
}

.achbar {
  flex: 1;
  height: 6px;
  border-radius: 999px;
  background: var(--tile);
  overflow: hidden;
}

.achbarfill {
  display: block;
  height: 100%;
  min-width: 2px;
  border-radius: 999px;
  background: var(--rank-2);
  transition: width 0.4s ease;
}

.achprogtxt {
  flex: none;
  color: var(--muted);
  font-size: 11px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

/* ─── Suggest a category (end-of-game feedback) ──────────────────────── */
.footer {
  display: flex;
  justify-content: center;
  margin-top: 28px;
}

.hapticsrow {
  display: inline-flex;
  align-items: center;
  gap: 10px;
}

.hapticslabel {
  color: var(--muted);
  font-size: 13px;
  font-weight: 600;
}

button.hapticsswitch {
  position: relative;
  width: 42px;
  height: 24px;
  border-radius: 999px;
  border: none;
  background: var(--tile);
  cursor: pointer;
  padding: 0;
  flex: none;
  transition: background 0.18s ease;
}

button.hapticsswitch.on {
  background: var(--go);
}

.hapticsknob {
  position: absolute;
  top: 3px;
  left: 3px;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: #fff;
  transition: transform 0.18s ease;
}

button.hapticsswitch.on .hapticsknob {
  transform: translateX(18px);
}

button.hapticsswitch:focus-visible {
  outline: 2px solid var(--gold);
  outline-offset: 2px;
}

/* Respect a reduced-motion preference: no collapse, shake, or wiggle. The solve
   still commits (the JS path skips the animation timer entirely), and the toggle
   snaps instead of sliding. */
@media (prefers-reduced-motion: reduce) {
  .tile.solving,
  .tile.shake,
  .tile.hint,
  button.hapticsswitch,
  .hapticsknob {
    animation: none;
    transition: none;
  }
}

/* ─── Friends (friend codes + weekly-league foundation) ──────────────── */
}

/* ─── /account, reworked (AccountView, owner-gated 2026-09-25) ──────────────
   Identity on top, one compact row per game below that expands into the
   game's full stats. Built from the same tokens as everything above: panel
   and tile surfaces, the gold rule, the campfire --go for progress. Every
   class is acct2- so the legacy page's classes are untouched. */
.acct2 .title { margin-bottom: 22px; }

.acct2-id {
  background: linear-gradient(180deg, var(--panel-top), var(--panel));
  border: 1px solid var(--tile);
  border-top: 2px solid var(--gold);
  border-radius: 14px;
  padding: 16px;
  box-shadow: 0 10px 28px rgba(0, 0, 0, 0.35);
}
.acct2-who { display: flex; align-items: center; gap: 12px; }
.acct2-avatar {
  flex: none;
  width: 46px; height: 46px; border-radius: 50%;
  display: grid; place-items: center;
  font-size: 20px; font-weight: 800; color: var(--ink-go);
  background: radial-gradient(circle at 35% 30%, var(--rank-1), var(--rank-2) 75%);
  box-shadow: 0 0 0 2px rgba(246, 181, 63, 0.25), 0 4px 12px rgba(230, 85, 46, 0.3);
}
.acct2-namebox, .acct2-nameform { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.acct2-kicker {
  font-size: 11px; font-weight: 700; letter-spacing: 1.1px; text-transform: uppercase; color: var(--gold-light);
}
.acct2-name {
  font-size: 21px; font-weight: 800; color: var(--text);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.acct2-link {
  flex: none; background: none; border: none; padding: 6px 2px; cursor: pointer;
  color: var(--gold-light); font: inherit; font-size: 14px; font-weight: 600;
  text-decoration: underline; text-underline-offset: 3px;
}
.acct2-inline { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.acct2-input {
  flex: 1 1 150px; min-width: 0;
  font: inherit; font-size: 16px; color: var(--text);
  background: var(--bg-board); border: 1.5px solid var(--warm-line); border-radius: 10px;
  padding: 10px 12px; outline: none;
}
.acct2-input:focus { border-color: var(--gold); box-shadow: 0 0 0 3px rgba(201, 168, 76, 0.18); }
.acct2-input.code { text-transform: uppercase; letter-spacing: 1px; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; }
.acct2-input.code::placeholder { letter-spacing: 1px; }
.acct2-btn {
  flex: none; font: inherit; font-size: 14px; font-weight: 700; cursor: pointer;
  padding: 10px 16px; border-radius: 10px; border: 1px solid transparent;
  background: var(--gold-shimmer); color: #241703;
}
.acct2-btn[disabled] { opacity: 0.5; cursor: default; }
.acct2-btn.ghost { background: var(--tile); color: var(--text); border-color: var(--warm-line); }
.acct2-hint { font-size: 12.5px; color: var(--muted); min-height: 17px; margin-top: 5px; }
.acct2-hint.bad { color: var(--bad); }
.acct2-hint.good { color: var(--go); }
/* A suggestion, not an error: the real-name nudge on the screen-name field. */
.acct2-hint.soft { color: var(--gold-light); }

.acct2-friends {
  margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--tile);
  display: flex; flex-direction: column; gap: 14px;
}
.acct2-code { display: flex; flex-direction: column; gap: 6px; }
.acct2-codeval {
  flex: 1 1 auto;
  font: 800 22px/1 ui-monospace, SFMono-Regular, Menlo, monospace; letter-spacing: 2px;
  color: var(--text); background: var(--bg-board);
  border: 1px dashed var(--bronze); border-radius: 10px; padding: 11px 14px;
  user-select: all; -webkit-user-select: all;
}
.acct2-add { display: flex; flex-direction: column; gap: 6px; }
.acct2-friendlink {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  background: var(--tile); border: 1px solid var(--warm-line); border-radius: 12px;
  padding: 12px 14px; text-decoration: none; color: var(--text);
}
.acct2-friendlink strong { display: block; font-size: 15px; }
.acct2-sub { display: block; color: var(--muted); font-size: 12.5px; margin-top: 2px; }
.acct2-signout {
  display: block; width: 100%; margin-top: 16px;
  font: inherit; font-size: 14px; font-weight: 600; cursor: pointer;
  padding: 10px; border-radius: 10px;
  background: transparent; color: var(--muted); border: 1px solid var(--tile);
}
.acct2-signout:hover { color: var(--bad); border-color: var(--bad); }

.acct2-section { margin-top: 28px; }
.acct2-sechead { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; flex-wrap: wrap; margin-bottom: 10px; }
.acct2-sechead h2 { margin: 0; font-size: 19px; font-weight: 800; }
.acct2-totals { color: var(--muted); font-size: 12.5px; font-weight: 600; font-variant-numeric: tabular-nums; }
.acct2-empty { color: var(--muted); font-size: 14px; text-align: center; padding: 18px 8px; }

.acct2-games { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }
.acct2-game { background: var(--panel); border: 1px solid var(--tile); border-radius: 12px; overflow: hidden; }
.acct2-game.open { border-color: var(--warm-line); box-shadow: inset 3px 0 0 var(--gold); }
.acct2-row {
  width: 100%; display: flex; align-items: center; gap: 12px;
  background: none; border: none; color: inherit; font: inherit; text-align: left;
  padding: 13px 14px; cursor: pointer; min-height: 56px;
}
.acct2-rowmain { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.acct2-gname { font-size: 15.5px; font-weight: 800; color: var(--text); }
.acct2-head { font-size: 13px; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.acct2-head b { color: var(--text); font-variant-numeric: tabular-nums; }
.acct2-rank {
  margin-left: 7px; font-size: 11px; font-weight: 700; color: var(--ink-go);
  background: var(--go); border-radius: 6px; padding: 1px 6px; vertical-align: 1px;
}
.acct2-achsum { flex: none; display: flex; flex-direction: column; align-items: flex-end; gap: 4px; width: 58px; }
.acct2-achnum { font-size: 12.5px; font-weight: 700; color: var(--gold-light); font-variant-numeric: tabular-nums; }
.acct2-minibar { width: 100%; height: 4px; border-radius: 999px; background: var(--tile); overflow: hidden; }
.acct2-minibar span { display: block; height: 100%; background: linear-gradient(90deg, var(--rank-2), var(--rank-1)); }
.acct2-chev { flex: none; color: var(--muted); font-size: 22px; line-height: 1; transition: transform 0.18s; }
.acct2-game.open .acct2-chev { transform: rotate(90deg); color: var(--gold-light); }
.acct2-detail { padding: 0 14px 16px; border-top: 1px solid var(--tile); }
.acct2-detail .statgrid { margin-top: 14px; }
.acct2-detail .statval { font-size: 22px; }
.acct2-statnote { font-size: 11px; color: var(--go); font-weight: 700; margin-top: 3px; }
.acct2-note { color: var(--muted); font-size: 12.5px; margin: 12px 0 0; }
.acct2-gamelink { display: inline-block; margin-top: 14px; color: var(--gold-light); font-size: 13.5px; font-weight: 600; }
@media (max-width: 380px) {
  .acct2-detail .statgrid { grid-template-columns: repeat(2, 1fr); }
}
@media (prefers-reduced-motion: reduce) { .acct2-chev { transition: none; } }

/* ─── Site links ────────────────────────────────────────────────────────────
   The platform's footer row (components/SiteLinks.tsx), styled as it is on
   every other Expedition Games page: small, centred, muted, hairline
   underlines — present, and never louder than the game above it. */
.sitelinks {
  margin: 28px 0 22px;
  padding: 0 12px;
  text-align: center;
  font-size: 12px;
  line-height: 1.75;
  color: rgba(184, 166, 150, 0.85);
}
.sitelinks a {
  color: inherit;
  text-decoration: none;
  border-bottom: 1px solid rgba(247, 239, 228, 0.18);
}
@media (hover: hover) {
  .sitelinks a:hover {
    color: var(--text);
    border-bottom-color: rgba(201, 168, 76, 0.55);
  }
}

/* ─── Platform pages: graphite + ember ──────────────────────────────────────
   /account, /sign-in and /sign-up are served at the platform apex, and they
   are on a new member's path through the main site — which is graphite with
   an ember accent, not this game's Campfire gold on oak. Wearing the board's
   look there was a seam. Each of those routes wraps its page in
   .platform-page (see their layout.tsx), and this block re-points the shared
   tokens at the main site's values (expeditiongames.app: --bg #0b0d12,
   --panel #161a23, --line #232a37, --text #eef1f6, --muted #9aa4b5,
   --accent #e0a760). Set on <html> via :has() so the body, the masthead,
   the footer row and Clerk's modals — all outside the wrapper — follow.
   Look only: nothing here changes what the pages do. */
html:has(.platform-page) {
  --bg: #0b0d12;
  --bg-board: #0b0d12;
  --bg-glow: rgba(224, 167, 96, 0.045);
  --panel: #10141b;
  --panel-top: #161a23;
  --chip: #1a1f2b;
  --chip-top: #212736;
  --warm-line: #232c3b;
  --text: #eef1f6;
  --muted: #9aa4b5;
  --tile: #1a1f2b;
  --lift: rgba(255, 255, 255, 0.04);
  --gold: #e0a760; /* ember */
  --gold-light: #f0c08a;
  --gold-deep: #a85a2c;
  --accent: #e0a760;
  --gold-shimmer: linear-gradient(180deg, #f6dfae, #d69b4e);
  --rank-1: #e0a760;
  --rank-2: #a85a2c;
  --go: #e0a760;
  --ink-go: #1a1206;
  --auth-bg: #161a23;
  --auth-primary: #e0a760;
  --auth-fg: #eef1f6;
  --auth-muted: #9aa4b5;
  --auth-input: #0b0d12;
  --auth-danger: #f96a5f;
  --auth-border: #232c3b;
}

/* A flat graphite room: no oak plate, no paper grain, no gold dust. */
html:has(.platform-page) body {
  background: radial-gradient(120% 60% at 50% -10%, var(--bg-glow), transparent 60%) var(--bg) fixed;
}
html:has(.platform-page) body::after,
html:has(.platform-page) .golddust {
  display: none;
}

/* Masthead: a plain graphite rule instead of the brushed rail + gold line. */
html:has(.platform-page) .authbar {
  background: none;
  border-bottom-color: var(--warm-line);
}

/* Page title in the main site's voice — plain bright type, no struck metal. */
.platform-page .title {
  background: none;
  color: var(--text);
  -webkit-text-fill-color: currentColor;
  filter: none;
  font-size: 30px;
}
.platform-page .title::after {
  display: none;
}

.platform-page .banner,
.platform-page .acct2-id {
  background: var(--panel);
  border-top-width: 1px;
  border-top-color: var(--warm-line);
}

.platform-page .acct2-avatar {
  box-shadow: 0 0 0 2px rgba(224, 167, 96, 0.25), 0 4px 12px rgba(168, 90, 44, 0.3);
}
.platform-page .acct2-input:focus {
  box-shadow: 0 0 0 3px rgba(224, 167, 96, 0.18);
}
.platform-page .acct2-btn:not(.ghost) {
  color: var(--ink-go);
}

html:has(.platform-page) .sitelinks {
  color: var(--muted);
}
html:has(.platform-page) .sitelinks a {
  border-bottom-color: rgba(238, 241, 246, 0.16);
}
@media (hover: hover) {
  html:has(.platform-page) .sitelinks a:hover {
    border-bottom-color: rgba(224, 167, 96, 0.55);
  }
}

/* The account page's way to the boards: one full-width ember button, the
   main site's primary-pill style, so a profile is one tap from the
   leaderboards. */
.acct2-boards {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  margin: 16px 0 0;
  padding: 13px 18px;
  border-radius: 12px;
  background: var(--gold-shimmer);
  color: var(--ink-go);
  font-size: 15.5px;
  font-weight: 800;
  text-decoration: none;
  box-shadow: 0 6px 18px rgba(224, 167, 96, 0.18);
}
.acct2-boards:hover {
  filter: brightness(1.06);
}
.acct2-boards:focus-visible {
  outline: 2px solid var(--gold-light);
  outline-offset: 3px;
}
