/** Shopify CDN: Minification failed

Line 2285:0 Unexpected "}"

**/
/* =============================================================================
   Puzzles Galore — Free online jigsaw puzzles
   Stylesheet for sections/pg-puzzle-game.liquid + assets/pg-jigsaw-game.js

   AUDIENCE: 50–65. Large type (17px base), 44px+ touch targets, high contrast,
   words on buttons, no thin weights. Warm "front parlour", not a dark arcade.

   SELF-CONTAINED: no @import, no external fonts, no image URLs. The felt and
   the wooden shelf are painted by the canvas engine (_tiles()), not by CSS.

   SCOPING: everything hangs off #pgj-root / .pgj so it cannot leak into the
   Horizon theme, and Horizon cannot bleed in (button/ol/li/img are reset).
   ========================================================================== */

/* -----------------------------------------------------------------------------
   1. Tokens
   --------------------------------------------------------------------------
   --pgj-tray-h and --pgj-topbar-h are a CONTRACT with pg-jigsaw-engine.js:
   _measure() runs parseFloat(getComputedStyle(document.documentElement)
   .getPropertyValue('--pgj-tray-h')) to reserve the shelf strip and to
   hit-test drops onto it. They MUST live on :root and MUST stay plain px —
   a calc() or a nested selector makes parseFloat return NaN, the engine
   silently falls back to its own defaults, and the shelf stops lining up with
   the chrome. Change them here and in the mobile block at §24 only.
   -------------------------------------------------------------------------- */
:root {
  --pgj-tray-h: 118px;   /* wooden shelf height — canvas-drawn, CSS declares it */
  --pgj-topbar-h: 58px;  /* game chrome bar height */

  /* Brand palette */
  --pgj-teal: var(--pg-teal-text, #1d7a34);
  --pgj-teal-deep: #0e4a41;
  --pgj-teal-soft: #e3efec;
  --pgj-teal-lt: #2fa08c;      /* mid teal — progress, accents (matches confetti) */
  --pgj-orange: #e5762d;       /* PRIMARY ACTION ONLY */
  --pgj-orange-deep: #c95f1d;
  --pgj-cream: #faf6ee;
  --pgj-paper: #fffdf8;
  --pgj-ink: #22312d;
  --pgj-ink-soft: #5b6b66;
  --pgj-line: #e4ddcf;
  --pgj-danger: #b3432b;
  --pgj-gold: #f6c357;
  --pgj-silver: #cfd4d2;
  --pgj-bronze: #c98a5e;
  --pgj-felt: #457a5d;         /* mirrors engine _tiles() — stops a white flash */

  /* Type — inherit the theme's face (the shop runs Instrument Sans) so the
     game matches the rest of the site rather than announcing itself in a
     different typeface. The stack is only a fallback for when this renders
     outside the theme (the dev harness). NO SERIF: headings use the same
     face as body copy. */

  /* Shape. Hairlines + layered shadows do the separating — a chunky 2px
     border on every container is what made the old build feel dated. */
  --pgj-r: 16px;
  --pgj-r-lg: 20px;
  --pgj-r-xl: 24px;
  --pgj-hairline: rgba(34, 49, 45, 0.14);
  --pgj-shadow: 0 1px 2px rgba(34, 49, 45, 0.05), 0 4px 12px rgba(34, 49, 45, 0.07),
    0 16px 32px rgba(34, 49, 45, 0.08);
  --pgj-shadow-lift: 0 2px 4px rgba(34, 49, 45, 0.06), 0 10px 24px rgba(34, 49, 45, 0.1),
    0 28px 56px rgba(34, 49, 45, 0.16);

  /* Layering. The game is a full-viewport overlay and must clear Horizon's
     sticky header; the sheets must in turn clear the game. */
  --pgj-z-game: 9000;
  --pgj-z-chrome: 9100;
  --pgj-z-veil: 9300;
  --pgj-z-finish: 9400;
  --pgj-z-fx: 9500;
  --pgj-z-dim: 9600;
  --pgj-z-sheet: 9700;
}

/* -----------------------------------------------------------------------------
   2. Reset + scoping
   -------------------------------------------------------------------------- */
#pgj-root,
#pgj-root *,
#pgj-root *::before,
#pgj-root *::after {
  box-sizing: border-box;
}

#pgj-root {
  /* inherit = the theme's body face (Instrument Sans on the live shop). */
  font-family: inherit;
  font-size: 17px;
  line-height: 1.5;
  color: var(--pgj-ink);
  background: var(--pgj-cream);
  -webkit-tap-highlight-color: rgba(22, 97, 86, 0.15);
  /* The hero breaks out to 100vw, and 100vw INCLUDES the scrollbar — so it
     overhangs by ~15px and gives the whole page a horizontal scrollbar.
     `clip` trims it without creating a scroll container (which `hidden` would,
     breaking position: sticky in the theme around us). */
  overflow-x: clip;
}

/* The JS toggles the `hidden` attribute on ~15 elements (panels, sheets, lid,
   finish, cutting, resume…). Horizon's reset can out-specify the UA rule, so
   pin it. §18 documents the one deliberate exception. */
#pgj-root [hidden] {
  display: none !important;
}

/* Element resets are wrapped in :where() so they carry the specificity of a
   BARE ELEMENT (0-0-1), not of an id (1-0-1).
   Without this, `#pgj-root button { background: none }` out-specifies
   `.pgj-btn--primary { background: var(--pgj-orange) }` — an id beats any
   class — and every button in the game (tiles, chips, tabs, tiers, menu rows)
   renders as unstyled text. 0-0-1 still beats the theme's bare `button {}`
   on source order, since this sheet loads after base.css. */
:where(#pgj-root) button {
  margin: 0;
  padding: 0;
  border: 0;
  font: inherit;
  color: inherit;
  background: none;
  text-align: inherit;
  cursor: pointer;
  -webkit-appearance: none;
  appearance: none;
}

:where(#pgj-root) button:disabled {
  cursor: default;
}

:where(#pgj-root) ol,
:where(#pgj-root) li {
  margin: 0;
  padding: 0;
  list-style: none;
}

:where(#pgj-root) img {
  display: block;
  max-width: 100%;
  border: 0;
}

:where(#pgj-root) h1,
:where(#pgj-root) h2,
:where(#pgj-root) h3,
:where(#pgj-root) h4 {
  margin: 0;
  font-weight: 700;
  line-height: 1.2;
  letter-spacing: 0;
  color: var(--pgj-ink);
}

:where(#pgj-root) p {
  margin: 0;
}

/* :where() here too, and for the same reason: at id specificity this `font:
   inherit` would beat .pgj-field input / .pgj-feedback__text and drag them to
   the inherited 16px — which is precisely the size that makes iOS zoom the
   page on focus. */
:where(#pgj-root) input,
:where(#pgj-root) textarea {
  font: inherit;
  color: inherit;
}

/* Keyboard users get an unmissable ring. */
#pgj-root :focus-visible {
  outline: 3px solid var(--pgj-orange);
  outline-offset: 2px;
  border-radius: 6px;
}

/* Playing = the fixed overlay covers the page; stop the theme scrolling under. */
body.pgj-playing {
  overflow: hidden;
}

/* THE STACKING ESCAPE HATCH — the live-theme bug this fixes:
   pg-megamenu.css ships `main .shopify-section { z-index: 1 !important }`.
   Every section is therefore pinned into a stacking context at z-index 1, so
   our fixed overlays (z 9000–9700) are trapped BELOW the sticky header
   (#header-group, z-index 999) — the header paints over the whole game.
   `!important` is the operative bit: our selector already out-specifies the
   megamenu rule (0,2,1 vs 0,1,1), but an !important declaration beats a
   non-important one regardless of specificity, so we must match it.
   Scoped to play/sheet-open only — on the plain select screen the section
   must stay at z1 and scroll UNDER the sticky header, not over it. */
body.pgj-playing .section-puzzle-game,
body.pgj-sheet-open .section-puzzle-game {
  position: relative !important;
  z-index: 10000 !important;
}

/* -----------------------------------------------------------------------------
   3. Buttons
   -------------------------------------------------------------------------- */
.pgj-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: 52px;
  padding: 9px 24px;
  border: 2px solid transparent;
  border-radius: 999px;
  font-size: 18px;
  font-weight: 600;
  letter-spacing: 0.01em;
  text-align: center;
  text-decoration: none;
  white-space: nowrap;
  transition: transform 0.15s ease, box-shadow 0.15s ease, background 0.15s ease;
}

.pgj-btn:active {
  transform: scale(0.97);
}

/* Primary — orange, and orange is reserved for this.
   White on #e5762d measures 3.02:1. That is AA for LARGE text only, and WCAG
   counts bold as large from 18.66px (14pt) — so 18px/700 would have missed by
   two thirds of a pixel. 19px/700 clears it, and a bigger primary CTA suits
   this audience anyway. Don't drop this below 19px, and don't dim the white:
   the palette fixes the orange, so the type size is the only lever left. */
.pgj-btn--primary {
  min-height: 52px;
  padding: 13px 26px;
  /* Fable's: a three-stop gradient, a solid orange-deep edge beneath, and a
     coloured glow. A flat fill is not the same button. 19px/700 keeps the
     white above the WCAG large-text threshold on this orange. */
  background: linear-gradient(180deg, #f08137, var(--pgj-orange) 55%, var(--pgj-orange-deep));
  border-color: transparent;
  font-size: 19px;
  font-weight: 700;
  color: #fff;
  box-shadow: 0 3px 0 var(--pgj-orange-deep), 0 10px 22px rgba(201, 95, 29, 0.35);
}

.pgj-btn--primary:hover {
  filter: brightness(1.05);
}

.pgj-btn--light {
  background: var(--pgj-paper);
  border-color: var(--pgj-teal);
  color: var(--pgj-teal);
  box-shadow: 0 2px 0 rgba(14, 74, 65, 0.25);
}

.pgj-btn--light:hover {
  background: var(--pgj-teal-soft);
}

.pgj-btn--danger {
  background: var(--pgj-danger);
  border-color: var(--pgj-danger);
  color: #fff;
}

.pgj-btn--danger:hover {
  filter: brightness(0.92);
}

.pgj-btn--ghost {
  background: none;
  border-color: transparent;
  color: var(--pgj-ink-soft);
  text-decoration: underline;
  text-underline-offset: 3px;
}

.pgj-btn--ghost:hover {
  background: var(--pgj-teal-soft);
  color: var(--pgj-teal);
}

.pgj-btn--wide {
  display: flex;
  width: 100%;
}

/* -----------------------------------------------------------------------------
   4. Select screen — shell + hero
   -------------------------------------------------------------------------- */
.pgj-select {
  width: min(1440px, 100% - 32px);
  margin-inline: auto;
  padding-block: 0 56px;
}

/* Fable's hero, restored: a teal band with a radial glow and a genuine
   JIGSAW-CUT bottom edge (a radial mask, not a border), with white brand
   pieces drifting behind. This band is the page's signature — flattening it to
   text-on-cream is what made the screen feel ordinary. It is a bright teal on
   a cream page, not a dark one: everything below stays near-white. */
.pgj-hero {
  position: relative;
  overflow: hidden;
  /* Break out of .pgj-select's 1440px column — the band spans the page. */
  width: 100vw;
  margin-inline: calc(50% - 50vw);
  margin-bottom: 34px;
  padding: 34px 20px 40px;
  text-align: center;
  color: #fff;
  background: radial-gradient(
    1200px 500px at 50% -180px,
    #1d7a6c 0%,
    var(--pgj-teal) 55%,
    var(--pgj-teal-deep) 100%
  );
}

/* (The scalloped "jigsaw-cut" bottom edge used to live here — at full page
   width it read as a fussy awning fringe rather than a puzzle edge, and the
   merchant asked for it gone. The band now ends clean.) */

.pgj-hero__inner {
  position: relative;
  z-index: 2;
  max-width: 760px;
  margin: 0 auto;
}

.pgj-hero__h1 {
  font-size: clamp(2.1rem, 5.5vw, 3.2rem);
  color: #fff;
  text-shadow: 0 2px 0 rgba(0, 0, 0, 0.18);
}

.pgj-hero__sub {
  max-width: 34em;
  margin: 12px auto 0;
  font-size: 1.13rem;
  color: #eaf4f1;
}

/* The points line under the hero sub — the game's honest deal. The <b> values
   come from the loyalty metafield; the link must read on the green band. */
.pgj-hero__points {
  margin-top: 10px;
  font-size: 15px;
  line-height: 1.5;
  color: #eaffec;
}
.pgj-hero__points b { color: #fff; }
.pgj-hero__points a { color: #fff; font-weight: 700; text-underline-offset: 2px; }


.pgj-hero__actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 14px;
  margin-top: 22px;
}

/* On teal, the light button inverts to a white outline. */
.pgj-hero__actions .pgj-btn--light {
  background: rgba(255, 255, 255, 0.12);
  border-color: #fff;
  color: #fff;
  box-shadow: none;
}

.pgj-hero__actions .pgj-btn--light:hover {
  background: rgba(255, 255, 255, 0.22);
}

.pgj-hero__actions .pgj-btn__piece {
  background-image: var(--pp-ttbf-white);
}

.pgj-btn__piece {
  width: 1.25em;
  height: 1.25em;
  background: var(--pp-ttbf-teal) center / contain no-repeat;
}

.pgj-hero__float {
  position: absolute;
  z-index: 0;
  background: var(--pp-ttbf-white) center / contain no-repeat;
  opacity: 0.12;
  pointer-events: none;
}

.pgj-hero__float--a {
  top: 16%;
  left: 4%;
  width: 150px;
  height: 150px;
  rotate: -14deg;
}

.pgj-hero__float--b {
  top: 10%;
  right: 7%;
  width: 90px;
  height: 90px;
  rotate: 18deg;
  background-image: var(--pp-tttb-white);
}

.pgj-hero__float--c {
  right: -40px;
  bottom: -60px;
  width: 210px;
  height: 210px;
  rotate: -8deg;
  opacity: 0.09;
}

@media (prefers-reduced-motion: no-preference) {
  .pgj-hero__float {
    animation: pgj-floaty 9s ease-in-out infinite;
  }

  .pgj-hero__float--b {
    animation-duration: 11s;
    animation-delay: -3s;
  }

  .pgj-hero__float--c {
    animation-duration: 13s;
    animation-delay: -6s;
  }

  @keyframes pgj-floaty {
    50% {
      translate: 0 -12px;
    }
  }
}

/* On the teal band the resume card keeps its own paper background. */
.pgj-resume {
  position: relative;
  z-index: 1;
  cursor: pointer;
}

/* ---- "Carry on" — the most recent unfinished game, up front ---- */
.pgj-resume {
  display: flex;
  align-items: center;
  gap: 16px;
  width: min(560px, 100%);
  margin: 24px auto 0;
  padding: 12px 16px;
  text-align: left;
  background: var(--pgj-paper);
  /* The hero band sets color:#fff. Without this the card's own text inherits
     white and vanishes into the paper. */
  color: var(--pgj-ink);
  border-radius: var(--pgj-r);
  box-shadow: var(--pgj-shadow);
}

.pgj-resume__art {
  flex: none;
  width: 86px;
  height: 64px;
  object-fit: cover;
  border-radius: 8px;
}

.pgj-resume__copy {
  flex: 1;
  min-width: 0;
}

.pgj-resume__copy strong {
  display: block;
  overflow: hidden;
  font-size: 17px;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.pgj-resume__copy small {
  font-size: 14px;
  color: var(--pgj-ink-soft);
}

.pgj-resume .pgj-btn {
  flex: none;
}

/* -----------------------------------------------------------------------------
   5. Daily hero card — the star of the select screen
   -------------------------------------------------------------------------- */
.pgj-daily {
  cursor: pointer;
  display: grid;
  grid-template-columns: minmax(0, 420px) minmax(0, 1fr);
  overflow: hidden;
  margin-bottom: 36px;
  background: var(--pgj-teal);
  border-radius: var(--pgj-r-xl);
  box-shadow: var(--pgj-shadow-lift);
}

/* JS fills this once the daily resolves — never flash an empty teal slab. */
.pgj-daily:empty {
  display: none;
}

/* Carried by both an <img> (normal) and a <div> (Mystery Wednesday). */
.pgj-daily__art {
  width: 100%;
  height: 100%;
  min-height: 300px;
  object-fit: cover;
  background: var(--pgj-teal-deep);
}

.pgj-daily__art--mystery {
  display: grid;
  place-items: center;
  background: linear-gradient(150deg, var(--pgj-teal-lt), var(--pgj-teal-deep) 78%);
}

.pgj-daily__art--mystery span {
  font-size: 132px;
  font-weight: 700;
  line-height: 1;
  color: var(--pgj-cream);
  opacity: 0.92;
  text-shadow: 0 4px 16px rgba(0, 0, 0, 0.25);
}

.pgj-daily__body {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: center;
  gap: 12px;
  padding: 36px 40px;
}

.pgj-daily__kicker {
  font-size: 15px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.09em;
  color: var(--pgj-gold);
}

.pgj-daily__title {
  font-size: 32px;
  color: var(--pgj-paper);
}

.pgj-daily__artist {
  margin-top: 2px;
  font-size: 17px;
  color: rgba(250, 246, 238, 0.78);
}

.pgj-daily__sub {
  max-width: 46ch;
  font-size: 17px;
  line-height: 1.5;
  color: rgba(250, 246, 238, 0.86);
}

.pgj-daily .pgj-btn {
  margin-top: 8px;
}

/* -----------------------------------------------------------------------------
   6. Panel tabs + panels
   --------------------------------------------------------------------------
   A segmented control rather than underlined tabs — the selected state has to
   read at a glance. Wraps to 2x2 on a phone: a swipe rail would hide half the
   navigation from people who don't think to swipe it.
   -------------------------------------------------------------------------- */
.pgj-panel-tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  padding: 6px;
  margin-bottom: 24px;
  background: var(--pgj-paper);
  border: 1.5px solid var(--pgj-hairline);
  border-radius: 999px;
  box-shadow: inset 0 1px 3px rgba(34, 49, 45, 0.05);
}

.pgj-panel-tab {
  flex: 1 1 auto;
  min-height: 48px;
  padding: 10px 20px;
  border-radius: 999px;
  font-size: 17px;
  font-weight: 700;
  text-align: center;
  color: var(--pgj-ink-soft);
  transition: background-color 0.15s ease, color 0.15s ease;
}

.pgj-panel-tab:hover {
  background: var(--pgj-teal-soft);
  color: var(--pgj-teal);
}

.pgj-panel-tab[aria-selected="true"] {
  background: var(--pgj-teal);
  color: var(--pgj-paper);
  box-shadow: 0 3px 10px rgba(22, 97, 86, 0.3);
}

.pgj-panel__title {
  font-size: 26px;
  color: var(--pgj-teal);
}

.pgj-panel__h {
  margin: 32px 0 14px;
  font-size: 20px;
  color: var(--pgj-ink);
}

.pgj-empty {
  padding: 30px 16px;
  font-size: 17px;
  text-align: center;
  color: var(--pgj-ink-soft);
  background: var(--pgj-paper);
  border: 1.5px dashed rgba(34, 49, 45, 0.25);
  border-radius: var(--pgj-r);
}

.pgj-empty::before {
  content: "";
  display: block;
  width: 30px;
  height: 30px;
  margin: 0 auto 10px;
  background: var(--pp-ttff-teal) center / contain no-repeat;
  opacity: 0.55;
}

/* -----------------------------------------------------------------------------
   7. Picture shelves + puzzle cards
   --------------------------------------------------------------------------
   NB "shelf" here is a section of the select screen — not the wooden piece
   shelf in the game, which the canvas paints.

   A GRID of rich cards, not a rail of thumbnails. Two reasons:
   1. Horizontal rails hide their contents behind a gesture. This audience does
      better with everything on the page and a button that says what it does
      than with a tile they're expected to intuit is tappable.
   2. The card has something to say — the picture, the artist, the brand, the
      real box piece count, and progress if a game is on the go. That doesn't
      fit a 200px thumbnail.
   -------------------------------------------------------------------------- */
.pgj-shelf {
  margin-bottom: 40px;
}

.pgj-shelf__title {
  margin-bottom: 14px;
  font-size: 22px;
  color: var(--pgj-ink);
}

.pgj-cards {
  display: grid;
  /* Fable's exact numbers. At the 1440px column these give FOUR across —
     (1440 + 26) / (300 + 26) = 4.49. Shrinking the minimum to 266px silently
     made it five, and the cards got mean. */
  gap: 26px;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
}

.pgj-card {
  position: relative;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  cursor: pointer;
  text-align: left;
  background: var(--pgj-paper);
  border-radius: var(--pgj-r);
  box-shadow: var(--pgj-shadow);
  transition: transform 0.18s ease, box-shadow 0.18s ease;
}

.pgj-card:hover {
  transform: translateY(-4px);
  box-shadow: var(--pgj-shadow-lift);
}

.pgj-card:hover .pgj-card__art {
  scale: 1.045;
}

.pgj-card__art {
  display: block;
  width: 100%;
  aspect-ratio: 3 / 2.1;
  /* cover, not contain: these are the flat artworks (the engine plays the same
     trimmed image), so cropping a sliver beats letterboxing every card. */
  object-fit: cover;
  background: var(--pgj-line);
  transition: scale 0.35s ease;
}

.pgj-card__body {
  display: flex;
  flex: 1;
  flex-direction: column;
  gap: 8px;
  padding: 14px 16px 16px;
}

.pgj-card__title {
  font-size: 19px;
  line-height: 1.3;
}

.pgj-card__artist {
  margin-top: -4px;
  font-size: 15px;
  color: var(--pgj-ink-soft);
}

.pgj-card__chips {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin-top: auto;
}

.pgj-card__chip {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 4px 12px;
  font-size: 13px;
  font-weight: 700;
  color: var(--pgj-teal-deep);
  background: var(--pgj-teal-soft);
  border-radius: 999px;
}

/* The piece count carries the canonical brand piece, never a generic icon. */
.pgj-card__chip-piece {
  width: 13px;
  height: 13px;
  background: var(--pp-ttff-teal) center / contain no-repeat;
}

.pgj-card__cta {
  display: flex;
  gap: 10px;
  align-items: center;
  justify-content: space-between;
  margin-top: 4px;
}

.pgj-card__play {
  display: inline-flex;
  flex: 1;
  align-items: center;
  justify-content: center;
  min-height: 50px;
  padding: 0 14px;
  font-size: 16px;
  font-weight: 700;
  color: #fff;
  background: var(--pgj-teal);
  border-radius: 12px;
  transition: background-color 0.15s ease;
}

.pgj-card__play:hover {
  background: var(--pgj-teal-deep);
}

.pgj-card__play.is-continue {
  background: linear-gradient(180deg, #f08137, var(--pgj-orange-deep));
}

.pgj-card__play.is-continue:hover {
  filter: brightness(1.05);
}

.pgj-ring {
  position: relative;
  flex: none;
  width: 46px;
  height: 46px;
}

.pgj-ring svg {
  transform: rotate(-90deg);
}

.pgj-ring__label {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  font-size: 12px;
  font-weight: 700;
  color: var(--pgj-teal-deep);
}

.pgj-card__ribbon {
  position: absolute;
  top: 12px;
  left: -8px;
  z-index: 1;
  padding: 4px 14px 4px 16px;
  font-size: 13px;
  font-weight: 700;
  color: #fff;
  background: var(--pgj-teal);
  border-radius: 0 999px 999px 0;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.25);
}

/* -----------------------------------------------------------------------------
   8. Leaderboard
   -------------------------------------------------------------------------- */
.pgj-lb__head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
}

.pgj-lb__tabs {
  display: flex;
  gap: 6px;
  padding: 5px;
  background: var(--pgj-paper);
  border: 2px solid var(--pgj-line);
  border-radius: 999px;
}

.pgj-lb-tab {
  min-height: 44px;
  padding: 8px 20px;
  border-radius: 999px;
  font-size: 16px;
  font-weight: 700;
  color: var(--pgj-ink-soft);
  transition: background-color 0.15s ease, color 0.15s ease;
}

.pgj-lb-tab:hover {
  background: var(--pgj-teal-soft);
  color: var(--pgj-teal);
}

.pgj-lb-tab[aria-selected="true"] {
  background: var(--pgj-teal);
  color: var(--pgj-paper);
}

.pgj-lb__note {
  margin: 10px 0 18px;
  font-size: 15px;
  color: var(--pgj-ink-soft);
}

.pgj-lb {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.pgj-lb__row {
  display: grid;
  grid-template-columns: 46px minmax(0, 1fr) auto;
  align-items: center;
  gap: 14px;
  min-height: 60px;
  padding: 8px 16px;
  background: var(--pgj-paper);
  border: 1.5px solid var(--pgj-hairline);
  border-radius: var(--pgj-r);
  box-shadow: 0 1px 2px rgba(34, 49, 45, 0.04);
}

.pgj-lb__row.is-me {
  background: var(--pgj-teal-soft);
  border-color: var(--pgj-teal);
  box-shadow: inset 0 0 0 1px var(--pgj-teal);
}

.pgj-lb__rank {
  display: grid;
  place-items: center;
  width: 42px;
  height: 42px;
  border-radius: 50%;
  font-size: 17px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  background: var(--pgj-teal-soft);
  color: var(--pgj-teal);
}

/* Proper medals: metal gradients, a white inner ring, a soft cast. */
.pgj-lb__rank--1 {
  background: linear-gradient(160deg, #fbe08e, #edb73f);
  color: #5c430c;
  box-shadow: inset 0 0 0 2px rgba(255, 255, 255, 0.55), 0 3px 8px rgba(214, 160, 40, 0.35);
}

.pgj-lb__rank--2 {
  background: linear-gradient(160deg, #eef1f0, #c3ccc8);
  color: #3c4844;
  box-shadow: inset 0 0 0 2px rgba(255, 255, 255, 0.6), 0 3px 8px rgba(52, 64, 60, 0.18);
}

.pgj-lb__rank--3 {
  background: linear-gradient(160deg, #dda67a, #b97844);
  color: #472a12;
  box-shadow: inset 0 0 0 2px rgba(255, 255, 255, 0.4), 0 3px 8px rgba(168, 111, 69, 0.35);
}

.pgj-lb__name {
  overflow: hidden;
  font-size: 17px;
  font-weight: 600;
  white-space: nowrap;
  text-overflow: ellipsis;
}

.pgj-lb__time {
  font-size: 18px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--pgj-teal);
}

.pgj-lb__empty {
  padding: 30px 16px;
  font-size: 17px;
  text-align: center;
  color: var(--pgj-ink-soft);
  background: var(--pgj-paper);
  border: 1.5px dashed rgba(34, 49, 45, 0.25);
  border-radius: var(--pgj-r);
}

.pgj-lb__empty::before {
  content: "";
  display: block;
  width: 30px;
  height: 30px;
  margin: 0 auto 10px;
  background: var(--pp-ttff-teal) center / contain no-repeat;
  opacity: 0.55;
}

/* -----------------------------------------------------------------------------
   9. Progress — stat tiles, best times
   -------------------------------------------------------------------------- */
.pgj-stat-row {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 14px;
  margin-top: 18px;
}

.pgj-stat {
  position: relative;
  overflow: hidden;
  padding: 22px 14px 18px;
  text-align: center;
  background: var(--pgj-paper);
  border-radius: 18px;
  box-shadow: var(--pgj-shadow);
}

/* A faint brand piece peeks from the corner — a watermark, not a border. */
.pgj-stat::after {
  content: "";
  position: absolute;
  right: -14px;
  bottom: -14px;
  width: 54px;
  height: 54px;
  background: var(--pp-ttff-teal) center / contain no-repeat;
  opacity: 0.1;
  rotate: -12deg;
}

.pgj-stat strong {
  display: block;
  font-size: 34px;
  font-weight: 700;
  line-height: 1.1;
  color: var(--pgj-teal);
}

.pgj-stat small {
  display: block;
  margin-top: 7px;
  font-size: 13px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--pgj-ink-soft);
}

.pgj-best-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(110px, 1fr));
  gap: 12px;
}

.pgj-best {
  padding: 14px 10px;
  text-align: center;
  background: var(--pgj-paper);
  border: 1.5px solid var(--pgj-hairline);
  border-radius: 14px;
}

.pgj-best strong {
  display: block;
  font-size: 20px;
  font-weight: 700;
  color: var(--pgj-teal);
}

.pgj-best span {
  display: block;
  margin-top: 4px;
  font-size: 16px;
  font-variant-numeric: tabular-nums;
  color: var(--pgj-ink-soft);
}

/* -----------------------------------------------------------------------------
   10. Badges
   --------------------------------------------------------------------------
   Un-earned badges fade the ICON, not the words: dropping the whole tile to
   low opacity would make the 14px description unreadable — and that
   description is exactly what tells you how to earn it.
   -------------------------------------------------------------------------- */
.pgj-badge-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
  gap: 12px;
}

.pgj-badge {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  padding: 18px 12px;
  text-align: center;
  background: var(--pgj-cream);
  border: 1.5px dashed rgba(34, 49, 45, 0.22);
  border-radius: var(--pgj-r);
}

.pgj-badge.is-earned {
  background: var(--pgj-paper);
  border: 2px solid var(--pgj-teal);
  box-shadow: 0 4px 14px rgba(22, 97, 86, 0.14);
}

/* Earned wears a tick, so the state reads without comparing tiles. */
.pgj-badge.is-earned::after {
  content: "\2713";
  position: absolute;
  top: 8px;
  right: 8px;
  display: grid;
  place-items: center;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: var(--pgj-teal);
  font-size: 13px;
  font-weight: 700;
  color: #fff;
}

.pgj-badge__icon {
  font-size: 34px;
  line-height: 1.2;
  filter: grayscale(1);
  opacity: 0.35;
}

.pgj-badge.is-earned .pgj-badge__icon {
  filter: none;
  opacity: 1;
}

.pgj-badge__name {
  font-size: 16px;
  font-weight: 700;
  color: var(--pgj-ink-soft);
}

.pgj-badge.is-earned .pgj-badge__name {
  color: var(--pgj-teal);
}

.pgj-badge__desc {
  font-size: 14px;
  line-height: 1.35;
  color: var(--pgj-ink-soft);
}

/* Newly-earned pills on the finish card */
.pgj-badge-pill {
  display: inline-block;
  margin: 4px 3px 0;
  padding: 8px 16px;
  border-radius: 999px;
  font-size: 16px;
  font-weight: 700;
  background: #fbf1d7;
  border: 1.5px solid #e5c469;
  color: #6b4c0d;
}

/* -----------------------------------------------------------------------------
   11. Calendar — 7 columns, Monday-first
   --------------------------------------------------------------------------
   .pgj-cal__dows and .pgj-cal__grid are separate elements and MUST share the
   same column template, or the day letters drift off their columns.
   -------------------------------------------------------------------------- */
.pgj-cal {
  max-width: 420px;
  padding: 18px;
  background: var(--pgj-paper);
  border: 1.5px solid var(--pgj-hairline);
  border-radius: var(--pgj-r);
  box-shadow: 0 1px 2px rgba(34, 49, 45, 0.04);
}

.pgj-cal__dows,
.pgj-cal__grid {
  display: grid;
  grid-template-columns: repeat(7, minmax(0, 1fr));
  gap: 6px;
}

.pgj-cal__dows {
  margin-bottom: 8px;
}

.pgj-cal__dows span {
  font-size: 14px;
  font-weight: 700;
  text-align: center;
  text-transform: uppercase;
  color: var(--pgj-ink-soft);
}

.pgj-cal__day {
  display: grid;
  place-items: center;
  aspect-ratio: 1 / 1;
  border-radius: 50%;
  font-size: 15px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  color: var(--pgj-ink-soft);
  background: var(--pgj-cream);
}

.pgj-cal__day.is-done {
  background: var(--pgj-teal);
  font-weight: 700;
  color: var(--pgj-paper);
}

.pgj-cal__day.is-today {
  box-shadow: inset 0 0 0 3px var(--pgj-orange);
  color: var(--pgj-ink);
}

.pgj-cal__day.is-done.is-today {
  color: var(--pgj-paper);
}

/* .pgj-cal__pad — deliberately empty; holds the Monday-first offset. */

.pgj-cal__sum {
  margin-top: 14px;
  font-size: 15px;
  font-weight: 600;
  text-align: center;
  color: var(--pgj-ink-soft);
}

/* -----------------------------------------------------------------------------
   12. Collection gallery
   -------------------------------------------------------------------------- */
.pgj-gal-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
  gap: 16px;
  margin-top: 18px;
}

/* A framed print: white mat around the artwork, caption on the mount. */
.pgj-gal {
  display: block;
  overflow: hidden;
  padding: 10px 10px 0;
  text-decoration: none;
  background: var(--pgj-paper);
  border: 1.5px solid var(--pgj-hairline);
  border-radius: var(--pgj-r);
  box-shadow: 0 1px 2px rgba(34, 49, 45, 0.04);
  transition: border-color 0.15s ease, transform 0.12s ease, box-shadow 0.15s ease;
}

.pgj-gal:hover {
  border-color: var(--pgj-teal);
  transform: translateY(-3px);
  box-shadow: var(--pgj-shadow);
}

.pgj-gal img {
  width: 100%;
  aspect-ratio: 1 / 1;
  object-fit: contain;
  background: #fff;
  border: 1px solid var(--pgj-line);
  border-radius: 6px;
}

.pgj-gal__t {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  padding: 10px 6px 0;
  font-size: 16px;
  font-weight: 600;
  line-height: 1.35;
  color: var(--pgj-ink);
}

.pgj-gal__m {
  display: block;
  padding: 3px 6px 12px;
  font-size: 14px;
  font-weight: 600;
  color: var(--pgj-teal);
}

/* -----------------------------------------------------------------------------
   13. Game overlay + canvas
   -------------------------------------------------------------------------- */
.pgj-game {
  position: fixed;
  inset: 0;
  z-index: var(--pgj-z-game);
  background: var(--pgj-felt);
  overscroll-behavior: contain;
}

.pgj-table {
  position: absolute;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
  /* Essential: the engine drives pieces with pointer events. Without this a
     drag scrolls the page / fires pull-to-refresh instead of moving a piece. */
  touch-action: none;
}

/* -----------------------------------------------------------------------------
   14. Top bar
   --------------------------------------------------------------------------
   Height is --pgj-topbar-h, which the engine also reserves when it centres the
   board. Deep teal to echo the site header; cream on that is ~7:1.
   -------------------------------------------------------------------------- */
.pgj-topbar {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  z-index: var(--pgj-z-chrome);
  display: flex;
  align-items: center;
  gap: 8px;
  height: var(--pgj-topbar-h);
  padding: 0 10px;
  overflow: hidden;
  /* Light, warm chrome — NOT a dark bar. The table is a deep felt so the
     artwork pops; if the chrome goes dark too, the whole screen reads as a
     muted arcade rather than a bright front parlour. */
  background: rgba(250, 246, 238, 0.88);
  -webkit-backdrop-filter: blur(12px) saturate(1.3);
  backdrop-filter: blur(12px) saturate(1.3);
  border-bottom: 1px solid rgba(34, 49, 45, 0.12);
  box-shadow: 0 2px 14px rgba(0, 0, 0, 0.16);
}

.pgj-tb {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  flex: 0 0 auto;
  min-width: 44px;
  height: 44px;
  padding: 0 12px;
  /* On the light bar the affordance is the teal ink and the hover fill, so the
     outline can be subtle. Teal-deep on cream is ~9:1 — far past AA. */
  border: 1.5px solid rgba(22, 97, 86, 0.28);
  border-radius: 999px;
  font-size: 16px;
  font-weight: 700;
  white-space: nowrap;
  color: var(--pgj-teal-deep);
  transition: background-color 0.15s ease, border-color 0.15s ease;
}

.pgj-tb:hover {
  background: var(--pgj-teal-soft);
  border-color: var(--pgj-teal);
}

.pgj-topbar__info {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 5px;
  flex: 1 1 auto;
  min-width: 0;
}

.pgj-topbar__title {
  overflow: hidden;
  font-size: 16px;
  font-weight: 700;
  white-space: nowrap;
  text-overflow: ellipsis;
  color: var(--pgj-ink);
}

.pgj-progress {
  overflow: hidden;
  height: 8px;
  background: #e2dbcb;
  border-radius: 999px;
}

.pgj-progress__fill {
  width: 0;
  height: 100%;
  background: linear-gradient(90deg, var(--pgj-teal), var(--pgj-teal-lt));
  border-radius: 999px;
  transition: width 0.35s ease;
}

.pgj-topbar__pct {
  flex: 0 0 auto;
  font-size: 16px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--pgj-teal-deep);
}

.pgj-timer {
  display: inline-flex;
  align-items: center;
  flex: 0 0 auto;
  height: 40px;
  padding: 0 14px;
  background: #efe9db;
  border-radius: 999px;
  font-size: 18px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--pgj-ink-soft);
}

.pgj-topbar__actions {
  display: flex;
  align-items: center;
  gap: 6px;
  flex: 0 1 auto;
  min-width: 0;
}

.pgj-zoom-pct {
  min-width: 46px;
  font-size: 15px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  text-align: center;
  color: var(--pgj-ink-soft);
}

/* -----------------------------------------------------------------------------
   15. Tray bar + toasts
   --------------------------------------------------------------------------
   Both float over the felt just above the canvas-drawn shelf. The bar spans
   the full width, so it must NOT swallow pointer events — a player dragging a
   piece across that strip would find it dead. Children opt back in.
   -------------------------------------------------------------------------- */
.pgj-traybar {
  position: absolute;
  left: 0;
  right: 0;
  bottom: var(--pgj-tray-h);
  z-index: var(--pgj-z-chrome);
  display: flex;
  align-items: center;
  /* Tools hug the SIDES — centred, they sat right on the board's bottom
     edge. Edges/Sort cluster left; the count and Hint go right (the count
     carries margin-left:auto below). The middle stays clear for the picture. */
  justify-content: flex-start;
  flex-wrap: wrap;
  gap: 8px;
  padding: 8px 12px;
  pointer-events: none;
}

.pgj-traybar > * {
  pointer-events: auto;
}

/* Shelf paging. Dragging the shelf sideways is fine with a finger; with a
   mouse it is a chore, so give it visible arrows too. */
.pgj-tray-arrow {
  position: absolute;
  bottom: calc(var(--pgj-tray-h) / 2 - 27px);
  z-index: var(--pgj-z-chrome);
  display: grid;
  place-items: center;
  width: 46px;
  height: 54px;
  font-size: 26px;
  font-weight: 800;
  color: #fff;
  background: rgba(20, 34, 28, 0.45);
  border-radius: 12px;
  backdrop-filter: blur(2px);
  transition: background-color 0.15s ease;
}

.pgj-tray-arrow:hover {
  background: rgba(20, 34, 28, 0.65);
}

.pgj-tray-arrow--l {
  left: 6px;
}

.pgj-tray-arrow--r {
  right: 6px;
}

/* Touch has drag-scroll; the arrows would only steal room from the shelf. */
@media (max-width: 749px) {
  .pgj-tray-arrow {
    display: none;
  }
}

/* ---- How to play ---- */
.pgj-help {
  display: flex;
  flex-direction: column;
  gap: 14px;
  margin: 6px 0 22px;
}

.pgj-help li {
  position: relative;
  padding-left: 38px;
  font-size: 17px;
  line-height: 1.45;
}

.pgj-help li::before {
  content: "";
  position: absolute;
  top: 2px;
  left: 0;
  width: 24px;
  height: 24px;
  background: var(--pp-ttff-teal) center / contain no-repeat;
}

.pgj-confirm__row {
  display: flex;
  gap: 12px;
  margin-top: 20px;
}

.pgj-confirm__row .pgj-btn {
  flex: 1;
}

/* The tray bar's chips (Edges first / Sort / Hint) — buttons that float over
   the felt. Distinct from .pgj-card__chip, which is a static label on a
   puzzle card; they collided under one name and the card labels inherited
   this button treatment. */
.pgj-chip {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  padding: 0 16px;
  background: rgba(250, 246, 238, 0.95);
  border: 2px solid transparent;
  border-radius: 999px;
  font-size: 16px;
  font-weight: 700;
  white-space: nowrap;
  color: var(--pgj-teal-deep);
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.18), 0 6px 16px rgba(0, 0, 0, 0.14);
  transition: background-color 0.15s ease, color 0.15s ease;
}

.pgj-chip:hover {
  background: var(--pgj-teal-soft);
}

/* Pressed = filled teal. The filter is on, and you can see that it is. */
.pgj-chip[aria-pressed="true"] {
  background: var(--pgj-teal);
  color: #fff;
}

.pgj-chip--hint {
  border-color: var(--pgj-orange);
  color: var(--pgj-orange-deep);
}

.pgj-chip--hint:hover {
  background: #fdece0;
}

/* Hint runs a 20s cooldown, relabelling itself "Hint (12s)" while disabled. */
.pgj-chip:disabled {
  background: var(--pgj-line);
  border-color: var(--pgj-ink-soft);
  color: var(--pgj-ink-soft);
  box-shadow: none;
}

.pgj-traybar__count {
  margin-left: auto;
  padding: 8px 16px;
  background: rgba(14, 74, 65, 0.82);
  border-radius: 999px;
  font-size: 15px;
  font-weight: 700;
  white-space: nowrap;
  color: var(--pgj-cream);
  pointer-events: none;
}

.pgj-toasts {
  position: absolute;
  left: 50%;
  bottom: calc(var(--pgj-tray-h) + 64px);
  z-index: var(--pgj-z-chrome);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  width: min(520px, calc(100% - 24px));
  transform: translateX(-50%);
  pointer-events: none;
}

.pgj-toast {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 20px 12px 16px;
  background: var(--pgj-paper);
  border-radius: 999px;
  font-size: 16px;
  font-weight: 600;
  text-align: left;
  color: var(--pgj-ink);
  box-shadow: var(--pgj-shadow-lift);
  animation: pgj-toast-in 0.28s ease both;
}

.pgj-toast::before {
  content: "";
  flex: none;
  width: 20px;
  height: 20px;
  background: var(--pp-ttff-teal) center / contain no-repeat;
}

.pgj-toast.is-out {
  opacity: 0;
  transform: translateY(6px);
  transition: opacity 0.4s ease, transform 0.4s ease;
}

@keyframes pgj-toast-in {
  from { opacity: 0; transform: translateY(10px); }
  to { opacity: 1; transform: translateY(0); }
}

/* -----------------------------------------------------------------------------
   16. Lid — the reference picture
   -------------------------------------------------------------------------- */
.pgj-lid {
  position: absolute;
  top: calc(var(--pgj-topbar-h) + 12px);
  right: 12px;
  z-index: var(--pgj-z-chrome);
  width: min(420px, calc(100% - 24px));
  overflow: hidden;
  background: var(--pgj-paper);
  border: 2px solid var(--pgj-teal-deep);
  border-radius: var(--pgj-r);
  box-shadow: var(--pgj-shadow-lift);
}

.pgj-lid__bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 8px 8px 8px 16px;
  background: var(--pgj-teal-deep);
  font-size: 16px;
  font-weight: 700;
  color: var(--pgj-cream);
}

.pgj-lid.is-large {
  width: min(66vw, 560px);
}

/* The bar is the handle — the lid is a real object you can shove aside. */
.pgj-lid__bar {
  cursor: grab;
  touch-action: none;
  user-select: none;
}

.pgj-lid__bar:active {
  cursor: grabbing;
}

.pgj-lid__title {
  flex: 1;
}

.pgj-lid__btn,
.pgj-lid__close {
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  font-size: 18px;
  color: var(--pgj-cream);
  transition: background-color 0.15s ease;
}

.pgj-lid__btn:hover,
.pgj-lid__close:hover {
  background: rgba(250, 246, 238, 0.2);
}

.pgj-lid img {
  width: 100%;
  max-height: 46vh;
  object-fit: contain;
  background: #fff;
}

/* -----------------------------------------------------------------------------
   17. Cutting veil
   --------------------------------------------------------------------------
   The spinner IS the brand piece — from the canonical kit via
   pg-jigsaw-pieces.css, never a hand-drawn CSS silhouette. The fill bar is
   driven by the engine's cut-progress callback.
   -------------------------------------------------------------------------- */
.pgj-cutting {
  position: absolute;
  inset: 0;
  z-index: var(--pgj-z-veil);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 22px;
  padding: 24px;
  text-align: center;
  background: rgba(14, 74, 65, 0.94);
}

.pgj-cutting__spin {
  width: 64px;
  height: 64px;
  background: var(--pp-ttbf-white) center / contain no-repeat;
  animation: pgj-spin 1.6s ease-in-out infinite;
}

#pgj-cutting-text {
  font-size: 19px;
  font-weight: 700;
  color: var(--pgj-cream);
}

.pgj-cutting__bar {
  width: min(300px, 68%);
  height: 6px;
  overflow: hidden;
  background: rgba(250, 246, 238, 0.22);
  border-radius: 999px;
}

.pgj-cutting__bar i {
  display: block;
  width: 0;
  height: 100%;
  background: var(--pgj-cream);
  border-radius: 999px;
  transition: width 0.2s ease;
}

@keyframes pgj-spin {
  50% { transform: rotate(180deg) scale(0.88); }
  100% { transform: rotate(360deg); }
}

/* -----------------------------------------------------------------------------
   18. Finish screen
   -------------------------------------------------------------------------- */
.pgj-finish {
  position: absolute;
  inset: 0;
  z-index: var(--pgj-z-finish);
  display: grid;
  place-items: center;
  padding: 16px;
  background: rgba(14, 74, 65, 0.6);
  -webkit-backdrop-filter: blur(4px);
  backdrop-filter: blur(4px);
  animation: pgj-fade-in 0.3s ease both;
}

@keyframes pgj-fade-in {
  from { opacity: 0; }
}

/* DELIBERATE EXCEPTION to the blanket [hidden] rule at §2.
   "Sit back and admire" sets #pgj-finish hidden and un-hides #pgj-admire-back —
   but that Back button is a CHILD of #pgj-finish, so display:none on the parent
   would take the only way out with it. Keep the container laid out, transparent
   and inert; hide the card instead. In every other state the card AND the
   button are both hidden, so this paints nothing and blocks nothing. */
#pgj-root .pgj-finish[hidden] {
  display: block !important;
  background: none;
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
  animation: none;
  pointer-events: none;
}

#pgj-root .pgj-finish[hidden] .pgj-finish__card {
  display: none;
}

.pgj-finish__card {
  width: min(560px, 100%);
  max-height: 100%;
  overflow-y: auto;
  overflow-x: hidden;
  padding: 30px 28px;
  text-align: center;
  background: var(--pgj-paper);
  border-radius: var(--pgj-r-xl);
  box-shadow: 0 40px 90px rgba(10, 30, 24, 0.45), 0 12px 28px rgba(10, 30, 24, 0.28);
  -webkit-overflow-scrolling: touch;
  animation: pgj-rise-in 0.55s cubic-bezier(0.18, 0.9, 0.28, 1.06) both;
}

@keyframes pgj-rise-in {
  from {
    opacity: 0;
    transform: translateY(34px) scale(0.97);
  }
}

.pgj-finish__kicker {
  font-size: 15px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.09em;
  color: var(--pgj-teal-lt);
}

.pgj-finish__title {
  margin-top: 8px;
  font-size: 30px;
  color: var(--pgj-teal);
}

.pgj-finish__stars {
  margin-top: 14px;
  font-size: 42px;
  line-height: 1;
  letter-spacing: 6px;
  color: var(--pgj-line);
}

.pgj-finish__stars span {
  display: inline-block;
}

.pgj-finish__stars .is-on {
  color: var(--pgj-gold);
  text-shadow: 0 2px 6px rgba(214, 160, 40, 0.45);
  animation: pgj-star-pop 0.55s cubic-bezier(0.2, 1.4, 0.4, 1) both;
}

/* Stars land one after another — the little ceremony of the thing. */
.pgj-finish__stars .is-on:nth-child(2) {
  animation-delay: 0.14s;
}

.pgj-finish__stars .is-on:nth-child(3) {
  animation-delay: 0.28s;
}

@keyframes pgj-star-pop {
  0% {
    opacity: 0;
    transform: scale(0) rotate(-30deg);
  }

  60% {
    transform: scale(1.28) rotate(6deg);
  }

  100% {
    opacity: 1;
    transform: scale(1) rotate(0deg);
  }
}

.pgj-finish__stats {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 12px;
  margin-top: 22px;
}

.pgj-finish__stats > div {
  flex: 1 1 120px;
  padding: 14px 10px;
  background: var(--pgj-teal-soft);
  border-radius: var(--pgj-r);
}

.pgj-finish__stats strong {
  display: block;
  font-size: 22px;
  font-weight: 700;
  color: var(--pgj-teal);
}

.pgj-finish__stats small {
  display: block;
  margin-top: 3px;
  font-size: 14px;
  font-weight: 600;
  color: var(--pgj-ink-soft);
}

.pgj-finish__rank {
  display: inline-block;
  margin-top: 16px;
  padding: 10px 20px;
  background: #fbf1d7;
  border: 1.5px solid #e5c469;
  border-radius: 999px;
  font-size: 16px;
  font-weight: 700;
  color: #6b4c0d;
}

.pgj-finish__loyalty {
  display: inline-block;
  margin-top: 10px;
  padding: 10px 20px;
  background: var(--pgj-teal-soft);
  border: 1.5px solid var(--pgj-teal);
  border-radius: 999px;
  font-size: 16px;
  font-weight: 700;
  color: var(--pgj-teal-deep);
}

.pgj-finish__badges:not(:empty) {
  margin-top: 18px;
}

.pgj-finish__badges-h {
  margin-bottom: 4px;
  font-size: 15px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--pgj-ink-soft);
}

/* The finished picture crowns the card, full-bleed to its edges. */
.pgj-finish__art {
  width: calc(100% + 56px);
  height: 172px;
  margin: -30px -28px 22px;
  object-fit: cover;
  background: var(--pgj-teal-soft);
}

.pgj-finish__actions {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-top: 22px;
}

.pgj-admire-back {
  position: absolute;
  top: calc(var(--pgj-topbar-h) + 12px);
  left: 50%;
  transform: translateX(-50%);
  pointer-events: auto;
  box-shadow: var(--pgj-shadow-lift);
}

.pgj-fx {
  position: fixed;
  inset: 0;
  z-index: var(--pgj-z-fx);
  display: none; /* JS flips to block for the confetti burst, then back */
  width: 100%;
  height: 100%;
  pointer-events: none;
}

/* -----------------------------------------------------------------------------
   19. Feedback block (inside the finish card)
   -------------------------------------------------------------------------- */
.pgj-feedback {
  margin-top: 26px;
  padding-top: 22px;
  border-top: 2px solid var(--pgj-line);
}

.pgj-feedback__h {
  font-size: 18px;
  font-weight: 700;
  color: var(--pgj-ink);
}

.pgj-feedback__text {
  display: block;
  width: 100%;
  margin-bottom: 12px;
  padding: 12px 14px;
  background: var(--pgj-cream);
  border: 1.5px solid var(--pgj-hairline);
  border-radius: var(--pgj-r);
  font-size: 17px;
  resize: vertical;
}

.pgj-feedback__text:focus {
  border-color: var(--pgj-teal);
  box-shadow: 0 0 0 3px rgba(22, 97, 86, 0.15);
  outline: none;
}

.pgj-feedback__thanks {
  padding: 16px;
  font-size: 17px;
  font-weight: 600;
  color: var(--pgj-teal);
}

.pgj-feedback__more {
  margin-top: 4px;
}

.pgj-feedback__sub {
  margin-bottom: 12px;
  font-size: 16px;
  color: var(--pgj-ink-soft);
}

/* -----------------------------------------------------------------------------
   19b. "Tell us something" — the always-available report

   Deliberately quiet. It is on every visit, so anything loud here would be
   nagging; the job is to be findable the moment somebody wants it, not to
   be noticed the rest of the time.
   -------------------------------------------------------------------------- */
/* The "you gave up on one" prompt. A card, not a banner: it is a real
   question about a specific thing, shown at most once a fortnight — but it
   must never read as an error or a telling-off. */
.pgj-fb-abandon {
  max-width: 640px;
  margin: 30px auto 0;
  padding: 18px 20px;
  background: var(--pgj-teal-soft);
  border: 1.5px solid var(--pgj-teal-lt);
  border-radius: var(--pgj-r);
  text-align: center;
}

.pgj-fb-abandon__text {
  margin-bottom: 14px;
  font-size: 17px;
  line-height: 1.45;
  color: var(--pgj-teal-deep);
}

.pgj-fb-abandon__row {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  justify-content: center;
  align-items: center;
}

/* ⚠ "No" is a plain link, not a second button. Two equal buttons make a
   dismissal look like a decision worth pausing over; this one should cost
   nothing. It is still a 44px target. */
.pgj-fb-abandon__no {
  padding: 10px 12px;
  min-height: 44px;
  background: none;
  border: 0;
  font-size: 15px;
  color: var(--pgj-ink-soft);
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
}

.pgj-fb-abandon__no:hover,
.pgj-fb-abandon__no:focus-visible {
  color: var(--pgj-teal-deep);
}

.pgj-fb-invite {
  margin: 26px 0 8px;
  text-align: center;
}

.pgj-fb-invite__btn {
  padding: 8px 14px;
  border-radius: var(--pgj-r);
  background: none;
  border: 0;
  font-size: 15px;
  color: var(--pgj-ink-soft);
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-color: var(--pgj-line);
  cursor: pointer;
  transition: color 0.12s ease, text-decoration-color 0.12s ease;
}

.pgj-fb-invite__btn:hover,
.pgj-fb-invite__btn:focus-visible {
  color: var(--pgj-teal);
  text-decoration-color: currentColor;
}

/* Screenshot picker. The real <input type="file"> is hidden and driven by the
   label, because the browser's own control is unstyleable and reads as a form
   you have to fill in rather than something optional. */
.pgj-fb-shot {
  margin-bottom: 14px;
}

.pgj-fb-shot__input {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
  pointer-events: none;
}

/* ⚠ `display: flex` + `width: fit-content`, NOT `inline-flex`. Both this and
   the preview thumbnail are inline-level under inline-flex, so they shared a
   line and baseline-aligned — the picture floated up beside the button and
   read as a layout bug. Block-level keeps the button on its own line with the
   thumbnail underneath it, while still hugging its text. */
.pgj-fb-shot__btn {
  display: flex;
  width: fit-content;
  align-items: center;
  gap: 8px;
  padding: 11px 16px;
  min-height: 44px;
  border-radius: 999px;
  background: var(--pgj-cream);
  border: 1.5px dashed var(--pgj-hairline);
  font-size: 15px;
  color: var(--pgj-ink);
  cursor: pointer;
  transition: border-color 0.12s ease, background 0.12s ease;
}

.pgj-fb-shot__btn:hover {
  border-color: var(--pgj-teal-lt);
  background: var(--pgj-teal-soft);
}

/* ⚠ The hidden input still takes keyboard focus, and its focus ring lands on a
   1px invisible box. Mirror it onto the label or the control is unreachable
   for anyone tabbing. */
.pgj-fb-shot__input:focus-visible + .pgj-fb-shot__preview,
.pgj-fb-shot__input:focus-visible ~ .pgj-fb-shot__note,
.pgj-fb-shot__btn:focus-within {
  outline: 2px solid var(--pgj-teal);
  outline-offset: 2px;
}

.pgj-fb-shot__preview {
  position: relative;
  display: inline-block;
  margin-top: 10px;
}

.pgj-fb-shot__preview img {
  display: block;
  max-width: 100%;
  max-height: 160px;
  border-radius: var(--pgj-r);
  border: 1.5px solid var(--pgj-hairline);
}

.pgj-fb-shot__remove {
  position: absolute;
  top: -8px;
  right: -8px;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  background: var(--pgj-ink);
  color: #fff;
  font-size: 15px;
  line-height: 1;
  border: 2px solid var(--pgj-paper);
  cursor: pointer;
}

.pgj-fb-shot__note {
  margin-top: 8px;
  font-size: 14px;
  color: var(--pgj-ink-soft);
}

/* Contact block — hidden until they tick, so the default view asks for
   nothing at all and an email never looks compulsory. */
.pgj-fb-contact {
  margin-bottom: 14px;
}

.pgj-fb-contact__tick {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  font-size: 15px;
  line-height: 1.4;
  color: var(--pgj-ink-soft);
  cursor: pointer;
}

.pgj-fb-contact__tick input {
  flex: none;
  width: 20px;
  height: 20px;
  margin-top: 1px;
  accent-color: var(--pgj-teal);
}

.pgj-fb-email {
  display: block;
  width: 100%;
  margin-top: 10px;
  padding: 12px 14px;
  background: var(--pgj-cream);
  border: 1.5px solid var(--pgj-hairline);
  border-radius: var(--pgj-r);
  font-size: 17px;
}

.pgj-fb-email:focus {
  border-color: var(--pgj-teal);
  box-shadow: 0 0 0 3px rgba(22, 97, 86, 0.15);
  outline: none;
}

.pgj-fb-contact__note {
  display: block;
  margin-top: 8px;
  font-size: 13px;
  line-height: 1.45;
  color: var(--pgj-ink-soft);
}

/* ⚠ Measured at 390×844: `scrollIntoView({block:'nearest'})` scrolls the
   MINIMUM distance, which lands "Send it" with its bottom edge exactly on the
   sheet's bottom edge — gap 0 — and pushes "Back" out of sight altogether. A
   primary action flush against the bottom of a phone sits under the home
   indicator on iOS and reads as cut off. This makes the browser scroll far
   enough to clear both. */
#pgj-fb-send,
#pgj-feedback-send {
  scroll-margin-block-end: 76px;
}

/* A nudge, never a rejection — the send simply waits rather than erroring. */
.pgj-feedback__text.is-asking,

.pgj-feedback__text.is-asking {
  border-color: var(--pgj-orange);
}

.pgj-fb-done {
  padding: 8px 0 4px;
  text-align: center;
}

.pgj-fb-done__h {
  margin-bottom: 8px;
  font-size: 20px;
  font-weight: 800;
  color: var(--pgj-teal);
}

.pgj-fb-done__p {
  margin-bottom: 18px;
  font-size: 16px;
  color: var(--pgj-ink-soft);
}

@keyframes pgj-fb-nudge {
  0%, 100% { transform: translateX(0); }
  25% { transform: translateX(-5px); }
  75% { transform: translateX(5px); }
}

@media (prefers-reduced-motion: reduce) {
    .pgj-feedback__text.is-asking,
}

/* -----------------------------------------------------------------------------
   20. Sheets + backdrop
   -------------------------------------------------------------------------- */
.pgj-dim {
  position: fixed;
  inset: 0;
  z-index: var(--pgj-z-dim);
  background: rgba(28, 40, 36, 0.55);
  -webkit-backdrop-filter: blur(3px);
  backdrop-filter: blur(3px);
  animation: pgj-fade-in 0.2s ease both;
}

.pgj-sheet {
  position: fixed;
  top: 50%;
  left: 50%;
  z-index: var(--pgj-z-sheet);
  width: min(560px, calc(100% - 32px));
  max-height: min(88vh, 780px);
  overflow-y: auto;
  padding: 30px 28px;
  background: var(--pgj-paper);
  border-radius: var(--pgj-r-xl);
  transform: translate(-50%, -50%);
  box-shadow: 0 40px 90px rgba(20, 30, 27, 0.4), 0 12px 28px rgba(20, 30, 27, 0.22);
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
  animation: pgj-sheet-in 0.28s cubic-bezier(0.2, 0.9, 0.3, 1) both;
}

@keyframes pgj-sheet-in {
  from {
    opacity: 0;
    transform: translate(-50%, calc(-50% + 16px)) scale(0.98);
  }
}

.pgj-sheet__close {
  position: absolute;
  top: 12px;
  right: 12px;
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  background: var(--pgj-cream);
  border: 1.5px solid var(--pgj-hairline);
  border-radius: 50%;
  font-size: 17px;
  color: var(--pgj-ink);
  transition: background-color 0.15s ease, border-color 0.15s ease;
}

.pgj-sheet__close:hover {
  background: var(--pgj-teal-soft);
  border-color: var(--pgj-teal);
}

.pgj-sheet__head {
  display: flex;
  align-items: center;
  gap: 16px;
  padding-right: 48px;
  margin-bottom: 20px;
}

.pgj-sheet__art {
  flex: 0 0 auto;
  width: 92px;
  height: 92px;
  object-fit: contain;
  background: #fff;
  border: 1.5px solid var(--pgj-hairline);
  border-radius: var(--pgj-r);
}

/* Mystery Wednesday: the JS strips the src, so this <img> paints as its box
   only — a teal panel standing in for the picture it's hiding. */
.pgj-sheet__art--mystery {
  background: linear-gradient(150deg, var(--pgj-teal-lt), var(--pgj-teal-deep) 78%);
  border-color: var(--pgj-teal-deep);
}

.pgj-sheet__title {
  font-size: 25px;
  color: var(--pgj-teal);
}

.pgj-sheet__sub {
  margin-top: 4px;
  font-size: 16px;
  color: var(--pgj-ink-soft);
}

.pgj-sheet__h {
  margin: 22px 0 12px;
  font-size: 19px;
  color: var(--pgj-ink);
}

.pgj-sheet__resume {
  padding: 18px;
  background: var(--pgj-teal-soft);
  border: 2px solid var(--pgj-teal);
  border-radius: var(--pgj-r);
}

.pgj-sheet__resume p {
  margin-bottom: 12px;
  font-size: 17px;
  font-weight: 600;
  color: var(--pgj-teal);
}

.pgj-sheet__resume .pgj-btn {
  width: 100%;
}

/* -----------------------------------------------------------------------------
   21. Piece-count tiers (6 / 12 / 24 / 48 / 96 / 150 / 300)
   -------------------------------------------------------------------------- */
.pgj-tiers {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(112px, 1fr));
  gap: 10px;
}

.pgj-tier {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  min-height: 88px;
  padding: 12px 8px;
  text-align: center;
  background: var(--pgj-paper);
  border: 1.5px solid var(--pgj-hairline);
  border-radius: 14px;
  transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease,
    box-shadow 0.15s ease;
}

.pgj-tier:hover {
  background: var(--pgj-teal-soft);
  border-color: var(--pgj-teal);
}

.pgj-tier strong {
  font-size: 24px;
  font-weight: 700;
  line-height: 1.1;
  color: var(--pgj-teal);
}

.pgj-tier span {
  font-size: 15px;
  font-weight: 700;
  color: var(--pgj-ink);
}

.pgj-tier small {
  font-size: 14px;
  line-height: 1.3;
  color: var(--pgj-ink-soft);
}

.pgj-tier[aria-checked="true"] {
  background: var(--pgj-teal);
  border-color: var(--pgj-teal-deep);
  box-shadow: 0 6px 16px rgba(22, 97, 86, 0.28);
}

.pgj-tier[aria-checked="true"]::after {
  content: "\2713";
  position: absolute;
  top: 6px;
  right: 6px;
  display: grid;
  place-items: center;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: var(--pgj-paper);
  font-size: 12px;
  font-weight: 700;
  color: var(--pgj-teal);
}

.pgj-tier[aria-checked="true"] strong,
.pgj-tier[aria-checked="true"] span {
  color: var(--pgj-paper);
}

.pgj-tier[aria-checked="true"] small {
  color: rgba(250, 246, 238, 0.85);
}

/* -----------------------------------------------------------------------------
   22. Options, menu, fields
   -------------------------------------------------------------------------- */
.pgj-opts {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

/* The JS hides this row for a mystery puzzle with style.display = 'none' | '' —
   the empty string reverts to whatever is declared here, so keep it declared. */
.pgj-opt {
  display: flex;
  align-items: center;
  gap: 14px;
  min-height: 60px;
  padding: 12px 16px;
  background: var(--pgj-cream);
  border: 1.5px solid var(--pgj-hairline);
  border-radius: var(--pgj-r);
  cursor: pointer;
  transition: border-color 0.15s ease, background-color 0.15s ease;
}

.pgj-opt:hover {
  border-color: var(--pgj-teal);
}

/* A proper switch, not a 24px checkbox — text left, control right, the
   settings pattern every phone has already taught this audience. The input
   itself is restyled (appearance: none), so :focus-visible still rings it
   and the label's click wiring is untouched. */
.pgj-opt input[type="checkbox"] {
  position: relative;
  flex: 0 0 auto;
  order: 2;
  width: 50px;
  height: 30px;
  margin-left: auto;
  appearance: none;
  -webkit-appearance: none;
  background: #cfc7b4;
  border-radius: 999px;
  cursor: pointer;
  transition: background-color 0.18s ease;
}

.pgj-opt input[type="checkbox"]::after {
  content: "";
  position: absolute;
  top: 3px;
  left: 3px;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.28);
  transition: translate 0.18s ease;
}

.pgj-opt input[type="checkbox"]:checked {
  background: var(--pgj-teal);
}

.pgj-opt input[type="checkbox"]:checked::after {
  translate: 20px 0;
}

.pgj-opt strong {
  display: block;
  font-size: 17px;
  font-weight: 700;
  color: var(--pgj-ink);
}

.pgj-opt small {
  display: block;
  margin-top: 2px;
  font-size: 15px;
  line-height: 1.35;
  color: var(--pgj-ink-soft);
}

.pgj-menu {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-top: 20px;
}

.pgj-menu__item {
  min-height: 64px;
  padding: 14px 18px;
  background: var(--pgj-cream);
  border: 1.5px solid var(--pgj-hairline);
  border-radius: var(--pgj-r);
  transition: background-color 0.15s ease, border-color 0.15s ease;
}

.pgj-menu__item:hover {
  background: var(--pgj-teal-soft);
  border-color: var(--pgj-teal);
}

.pgj-menu__item strong {
  display: block;
  font-size: 17px;
  font-weight: 700;
  color: var(--pgj-ink);
}

.pgj-menu__item small {
  display: block;
  margin-top: 2px;
  font-size: 15px;
  line-height: 1.35;
  color: var(--pgj-ink-soft);
}

.pgj-menu__item--danger strong {
  color: var(--pgj-danger);
}

.pgj-menu__item--danger:hover {
  background: #fbeeea;
  border-color: var(--pgj-danger);
}

.pgj-field {
  display: block;
  margin: 22px 0 20px;
}

.pgj-field > span {
  display: block;
  margin-bottom: 8px;
  font-size: 16px;
  font-weight: 700;
  color: var(--pgj-ink);
}

.pgj-field input {
  display: block;
  width: 100%;
  min-height: 54px;
  padding: 12px 16px;
  background: var(--pgj-cream);
  border: 1.5px solid var(--pgj-hairline);
  border-radius: var(--pgj-r);
  /* 17px: never below 16px, or iOS zooms the page on focus. */
  font-size: 17px;
}

.pgj-field input:focus {
  border-color: var(--pgj-teal);
  box-shadow: 0 0 0 3px rgba(22, 97, 86, 0.15);
  outline: none;
}

/* -----------------------------------------------------------------------------
   23. SEO prose (snippets/pg-jigsaw-seo.liquid)
   --------------------------------------------------------------------------
   Rendered by the same section, below #pgj-root, and this is the only
   stylesheet that section loads — so its styles live here. Every selector is
   prefixed, so it still can't leak into Horizon.
   -------------------------------------------------------------------------- */
.pg-jigsaw-seo {
  padding: 48px 0 56px;
  background: var(--pgj-paper);
  color: var(--pgj-ink);
}

.pg-jigsaw-seo__inner {
  width: min(1440px, 100% - 32px);
  margin-inline: auto;
}

.pg-jigsaw-seo__heading {
  margin: 0 0 12px;
  font-size: 28px;
  font-weight: 700;
  line-height: 1.25;
  color: var(--pgj-teal);
}

.pg-jigsaw-seo__intro,
.pg-jigsaw-seo__text {
  max-width: 72ch;
  margin: 0 0 14px;
  font-size: 17px;
  line-height: 1.65;
  color: var(--pgj-ink-soft);
}

.pg-jigsaw-seo__block {
  margin-bottom: 40px;
}

.pg-jigsaw-seo__steps {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 14px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.pg-jigsaw-seo__step {
  padding: 18px 20px;
  background: var(--pgj-cream);
  border: 1.5px solid var(--pgj-hairline);
  border-radius: var(--pgj-r);
  font-size: 17px;
  line-height: 1.5;
}

.pg-jigsaw-seo__faq-item {
  padding: 18px 0;
  border-top: 1px solid var(--pgj-hairline);
}

.pg-jigsaw-seo__faq-question {
  margin: 0 0 6px;
  font-size: 20px;
  font-weight: 700;
  color: var(--pgj-ink);
}

.pg-jigsaw-seo__faq-answer {
  max-width: 72ch;
  margin: 0;
  font-size: 17px;
  line-height: 1.6;
  color: var(--pgj-ink-soft);
}

.pg-jigsaw-seo__links {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.pg-jigsaw-seo__link-item {
  display: block;
}

.pg-jigsaw-seo__link {
  display: inline-flex;
  align-items: center;
  min-height: 46px;
  padding: 10px 20px;
  background: var(--pgj-cream);
  border: 2px solid var(--pgj-teal);
  border-radius: 999px;
  font-size: 16px;
  font-weight: 700;
  text-decoration: none;
  color: var(--pgj-teal);
  transition: background-color 0.15s ease;
}

.pg-jigsaw-seo__link:hover {
  background: var(--pgj-teal-soft);
}

.pg-jigsaw-seo :focus-visible {
  outline: 3px solid var(--pgj-orange);
  outline-offset: 2px;
}

/* -----------------------------------------------------------------------------
   24. Mobile — ≤749px (the store's breakpoint; ~75% of this shop's traffic)
   -------------------------------------------------------------------------- */
@media (max-width: 749px) {
  /* Engine contract — must stay on :root, must stay plain px. See §1. */
  :root {
    --pgj-tray-h: 96px;
    --pgj-topbar-h: 52px;
  }

  #pgj-root {
    font-size: 16px;
  }

  .pgj-select {
    padding-block: 16px 40px;
  }

  .pgj-hero {
    padding: 4px 0 20px;
  }

  .pgj-hero__h1 {
    font-size: 30px;
  }

  .pgj-hero__sub {
    font-size: 17px;
  }

  /* Daily hero stacks: picture on top, then the words and the button. */
  .pgj-daily {
    grid-template-columns: minmax(0, 1fr);
    margin-bottom: 28px;
  }

  .pgj-daily__art {
    min-height: 0;
    aspect-ratio: 16 / 10;
  }

  .pgj-daily__art--mystery span {
    font-size: 88px;
  }

  .pgj-daily__body {
    padding: 22px 20px 26px;
  }

  .pgj-daily__title {
    font-size: 26px;
  }

  .pgj-daily .pgj-btn {
    width: 100%;
  }

  /* 2x2 rather than a swipe rail — all four panels stay visible. */
  .pgj-panel-tab {
    flex: 1 1 44%;
    padding: 10px 8px;
    font-size: 16px;
  }

  .pgj-panel__title {
    font-size: 22px;
  }

  .pgj-shelf__title {
    font-size: 19px;
  }

  /* Two cards across on a phone. Below 380px one card, so the button and the
     piece-count chip never get squeezed to nothing. */
  .pgj-cards {
    gap: 12px;
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .pgj-card__body {
    padding: 10px 12px 12px;
  }

  .pgj-card__title {
    font-size: 16px;
  }

  .pgj-card__artist {
    font-size: 13px;
  }

  .pgj-card__play {
    min-height: 46px;
    font-size: 15px;
  }

  /* The ring duplicates the % already on the button — drop it, keep the tap
     target full width. */
  .pgj-ring {
    display: none;
  }

  .pgj-stat-row {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .pgj-stat strong {
    font-size: 26px;
  }

  .pgj-best-row {
    grid-template-columns: repeat(auto-fit, minmax(88px, 1fr));
  }

  .pgj-badge-grid {
    grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
  }

  .pgj-gal-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .pgj-lb__row {
    grid-template-columns: 40px minmax(0, 1fr) auto;
    gap: 10px;
    padding: 8px 12px;
  }

  .pgj-lb__rank {
    width: 38px;
    height: 38px;
    font-size: 16px;
  }

  /* Top bar is tight — drop what's already said elsewhere on screen. */
  .pgj-tb__label,
  .pgj-topbar__title,
  .pgj-topbar__pct,
  .pgj-zoom-pct {
    display: none;
  }

  /* …and the zoom buttons too, which the brief's hide-list doesn't name — but
     the arithmetic leaves no choice. Back + timer + five action buttons needs
     ~396px; a 360px phone clips the rightmost one, and that one is Menu (sound,
     guide, tidy, restart). Losing Menu is not survivable; losing these is:
     the engine has real pinch-to-zoom (pointers.size === 2 → pinchStart), and
     "Fit" still resets the view. Dropping the pair frees ~92px and the bar then
     fits a 320px screen. Consistent, too, with the brief already hiding the
     zoom percentage here. Flag for review if the zoom buttons must stay. */
  #pgj-zoom-in,
  #pgj-zoom-out {
    display: none;
  }

  .pgj-topbar {
    gap: 4px;
    padding: 0 6px;
  }

  /* The title is hidden here, so .pgj-topbar__info carries only the progress
     bar — and as a flex child wedged between the back button and five action
     buttons it gets squeezed to ZERO width on a 360px phone, taking the only
     progress feedback mobile has with it (the % readout is hidden too).
     Lift it out of the flex row and run it full-width along the bar's bottom
     edge: always visible, and it costs no horizontal space. 4px tall sits
     exactly in the 48–52px band left free under the 44px buttons. */
  .pgj-topbar__info {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    flex: none;
    gap: 0;
  }

  .pgj-progress {
    height: 4px;
    border-radius: 0;
  }

  /* Still 44px — the bar tightens by dropping words and padding, never the
     touch target. 44 + 2x4 padding is exactly the 52px bar. */
  .pgj-tb {
    height: 44px;
    padding: 0 10px;
    font-size: 15px;
  }

  .pgj-topbar__actions {
    gap: 4px;
  }

  .pgj-timer {
    height: 38px;
    padding: 0 10px;
    font-size: 16px;
  }

  .pgj-traybar {
    gap: 6px;
    padding: 6px 8px;
  }

  .pgj-chip {
    min-height: 44px;
    padding: 8px 14px;
    font-size: 15px;
  }

  .pgj-traybar__count {
    padding: 6px 12px;
    font-size: 14px;
  }

  .pgj-toasts {
    bottom: calc(var(--pgj-tray-h) + 58px);
  }

  .pgj-toast {
    padding: 11px 16px;
    font-size: 15px;
  }

  .pgj-lid {
    top: calc(var(--pgj-topbar-h) + 8px);
    left: 8px;
    right: 8px;
    width: auto;
  }

  .pgj-lid img {
    max-height: 38vh;
  }

  .pgj-finish {
    padding: 0;
    place-items: end stretch;
  }

  .pgj-finish__card {
    width: 100%;
    max-height: 92vh;
    padding: 26px 20px calc(24px + env(safe-area-inset-bottom));
    border-radius: var(--pgj-r-lg) var(--pgj-r-lg) 0 0;
  }

  .pgj-finish__title {
    font-size: 25px;
  }

  .pgj-finish__stars {
    font-size: 34px;
  }

  .pgj-finish__art {
    width: calc(100% + 40px);
    height: 136px;
    margin: -26px -20px 18px;
  }

  /* Bottom sheets — thumb-reachable, and clear of the home indicator. */
  .pgj-sheet {
    top: auto;
    bottom: 0;
    left: 0;
    width: 100%;
    max-height: 90vh;
    padding: 24px 18px calc(24px + env(safe-area-inset-bottom));
    border-radius: var(--pgj-r-lg) var(--pgj-r-lg) 0 0;
    transform: none;
  }

  /* Bottom sheets slide UP. The desktop keyframes animate a translate(-50%)
     that a bottom sheet doesn't have, so they're redeclared for this width. */
  @keyframes pgj-sheet-in {
    from {
      opacity: 0;
      transform: translateY(44px);
    }

    to {
      opacity: 1;
      transform: none;
    }
  }

  .pgj-sheet__head {
    gap: 12px;
    margin-bottom: 16px;
  }

  .pgj-sheet__art {
    width: 74px;
    height: 74px;
  }

  .pgj-sheet__title {
    font-size: 22px;
  }

  .pgj-tiers {
    grid-template-columns: repeat(auto-fit, minmax(96px, 1fr));
    gap: 8px;
  }

  .pgj-tier {
    min-height: 82px;
  }

  .pg-jigsaw-seo {
    padding: 36px 0 44px;
  }

  .pg-jigsaw-seo__heading {
    font-size: 23px;
  }
}

/* -----------------------------------------------------------------------------
   25. Reduced motion
   --------------------------------------------------------------------------
   The cutting spinner stops too — its text ("Cutting the pieces… 12 of 48")
   keeps reporting progress, so nothing is lost. The engine reads the same
   media query itself and skips the confetti.
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  #pgj-root *,
  #pgj-root *::before,
  #pgj-root *::after,
  .pg-jigsaw-seo * {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }

  .pgj-card:hover,
  .pgj-gal:hover,
  .pgj-btn:active {
    transform: none;
  }
}

/* =============================================================
   Version line + changelog
   -------------------------------------------------------------
   Operator, 2026-08-28: "subtl but so people can use it if
   wanted". So it is a footnote under the menu items, not a menu
   item — deliberately quieter than everything above it. Nobody
   comes to a jigsaw for a changelog, but the players who told us
   the pieces had changed shape should have somewhere that shows
   we listened.
   ============================================================= */
.pgj-ver {
  display: block;
  width: 100%;
  margin: 14px 0 2px;
  padding: 8px 4px;
  background: none;
  border: 0;
  border-top: 1px solid var(--pgj-hairline);
  color: var(--pgj-ink-soft);
  font: inherit;
  font-size: 13px;
  text-align: center;
  cursor: pointer;
  border-radius: 8px;
  transition: color 0.15s ease, background-color 0.15s ease;
}
.pgj-ver:hover,
.pgj-ver:focus-visible { color: var(--pgj-teal); background: var(--pgj-teal-soft); }

.pgj-log__rel + .pgj-log__rel { margin-top: 22px; }
.pgj-log__v {
  display: flex;
  align-items: baseline;
  gap: 10px;
  margin: 0 0 10px;
  font-size: 17px;
  color: var(--pgj-ink);
}
.pgj-log__v small { font-size: 13px; font-weight: 400; color: var(--pgj-ink-soft); }
.pgj-log__list { list-style: none; margin: 0; padding: 0; display: grid; gap: 10px; }
.pgj-log__item {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 10px;
  align-items: start;
  font-size: 15.5px;
  line-height: 1.5;
  color: var(--pgj-ink);
}
/* A word, not a colour alone — the tag has to survive being read by
   somebody who cannot tell the two greens apart. */
.pgj-log__tag {
  padding: 2px 9px;
  border-radius: 999px;
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: 0.3px;
  text-transform: uppercase;
  white-space: nowrap;
  background: var(--pgj-teal-soft);
  color: var(--pgj-teal-deep);
}
.pgj-log__tag--fixed  { background: #fdeee2; color: #9a4a12; }
.pgj-log__tag--new    { background: var(--pgj-teal-soft); color: var(--pgj-teal-deep); }
.pgj-log__tag--better { background: #eef0f7; color: #3c4a7a; }

/* =============================================================
   Paused
   -------------------------------------------------------------
   Asked for on 12 Aug 2026 by a player 76 minutes into a
   300-piece. The COVER is the feature: a pause that only stops
   the clock leaves the picture on screen and you carry on
   solving it.

   ⚠ Sits at the veil layer so it covers the top bar as well as
   the board — otherwise you can still zoom, fit and open the
   picture while "paused". Being above the canvas is also what
   blocks input, with no change to the engine's pointer handling.
   ============================================================= */
.pgj-paused {
  position: absolute;
  inset: 0;
  z-index: var(--pgj-z-veil);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  text-align: center;
  background: rgba(14, 74, 65, 0.96);
}
.pgj-paused[hidden] { display: none; }
.pgj-paused__inner {
  width: min(420px, 100%);
  padding: 30px 26px;
  background: var(--pgj-paper, #fffdf8);
  border-radius: var(--pgj-r-xl, 22px);
  box-shadow: 0 30px 70px rgba(10, 26, 22, 0.42);
}
.pgj-paused__eyebrow {
  display: inline-block;
  margin-bottom: 12px;
  padding: 4px 12px;
  border-radius: 999px;
  background: var(--pgj-teal-soft, #e3efec);
  color: var(--pgj-teal-deep, #0e4a41);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.6px;
  text-transform: uppercase;
}
.pgj-paused__title {
  margin: 0 0 8px;
  font-size: 22px;
  line-height: 1.25;
  color: var(--pgj-ink, #22312d);
}
.pgj-paused__sub {
  margin: 0 0 18px;
  font-size: 15.5px;
  line-height: 1.5;
  color: var(--pgj-ink-soft, #5b6b66);
}
.pgj-paused__time {
  margin: 0 0 18px;
  font-size: 14px;
  font-weight: 600;
  color: var(--pgj-teal-deep, #0e4a41);
}
.pgj-paused__time[hidden] { display: none; }

/* =============================================================
   "See it bigger" — the picture, before you commit to it
   -------------------------------------------------------------
   The setup sheet showed the artwork at 92px and there was no
   other way to look at the picture before starting: the in-game
   Picture button only exists once you are playing, and #pgj-lid
   lives inside the hidden game container so it cannot be reused
   from the picker. Asked for on 15 Aug 2026.

   ⚠ Expands IN PLACE rather than opening a second overlay — the
   sheet already scrolls, so there is no z-index or focus-trap to
   get wrong.
   ============================================================= */
.pgj-sheet__artbtn {
  position: relative;
  flex: 0 0 auto;
  display: block;
  padding: 0;
  background: none;
  border: 0;
  cursor: zoom-in;
  border-radius: var(--pgj-r);
  transition: width 0.22s ease;
}
.pgj-sheet__artbtn[hidden] { display: none; }
.pgj-sheet__artcue {
  display: block;
  margin-top: 5px;
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: 0.2px;
  color: var(--pgj-teal, #1d7a34);
  text-align: center;
}
.pgj-sheet__artbtn:hover .pgj-sheet__artcue,
.pgj-sheet__artbtn:focus-visible .pgj-sheet__artcue { text-decoration: underline; }

/* Expanded: the artwork takes the whole sheet width and the head
   stacks, so the title sits under the picture rather than beside
   a very tall thumbnail. */
.pgj-sheet--artbig .pgj-sheet__head { flex-direction: column; align-items: stretch; }
.pgj-sheet--artbig .pgj-sheet__artbtn { width: 100%; cursor: zoom-out; }
.pgj-sheet--artbig .pgj-sheet__art {
  width: 100%;
  height: auto;
  max-height: 52vh;
}
