/* ---------- reset / base ---------- */
*, *::before, *::after { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
html { -webkit-text-size-adjust: 100%; }

:root {
  /* App container width.
     - Mobile / tablet portrait: full viewport width (set via media query
       below; effectively `none`).
     - Tablet landscape & desktop: capped at 700px and centred. */
  --app-max: none;

  --bg:       #e8ddd0;   /* richer warm stone — makes white cards pop clearly */
  --bg-board: #e8ddd0;   /* board table — same as page background */
  --surface:  #ffffff;
  --surface-2:#f3ece0;
  --surface-3:#fdf9f4;

  --ink:   #1c1408;
  --ink-2: #7c6e58;
  --ink-3: #b8a990;

  --line:   rgba(28,20,8,.07);
  --line-2: rgba(28,20,8,.13);

  --amber:      #c17a2f;
  --amber-2:    #d9923e;
  --amber-3:    #8f5519;
  --amber-soft: #fbecd6;
  --amber-tint: #fdf5ea;

  --shadow-sm: 0 1px 4px rgba(28,20,8,.06);
  --shadow-md: 0 4px 16px rgba(28,20,8,.08);
  --shadow-lg: 0 12px 36px rgba(28,20,8,.12);

  --font-display: "Fraunces", ui-serif, "New York", Georgia, serif;
  --font-ui:      "DM Sans", ui-sans-serif, -apple-system, BlinkMacSystemFont,
                  "Segoe UI", Helvetica, Arial, sans-serif;
}

body {
  font-family: var(--font-ui);
  background: var(--bg);
  color: var(--ink);
  min-height: 100dvh;
  overscroll-behavior: none;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  font-size: 15px;
  line-height: 1.5;
  letter-spacing: -.01em;
}
.app {
  max-width: var(--app-max);
  margin: 0 auto;
  min-height: 100dvh;
  background: var(--bg);
}
/* Cap the app width on landscape tablets and desktops; keep it full
   width on phones (any orientation) and on tablets in portrait mode. */
@media (min-width: 900px) and (orientation: landscape),
       (min-width: 1100px) {
  :root { --app-max: 600px; }
  /* On the play page we want the WHOLE viewport to be parking space for
     pieces, so the .app spans the full width here (the square puzzle frame
     stays centred via FRAME_PAD_X in the board math). The topbar and the
     tray are constrained back to the original 600px column so they look
     identical to the rest of the site. */
  body.page-play { --app-max: none; }
  body.page-play .topbar,
  body.page-play .tray-wrap {
    max-width: 600px;
    margin-left: auto;
    margin-right: auto;
  }
}
button { font: inherit; color: inherit; cursor: pointer; }
a { color: inherit; }

/* =========================================================
   TOPBAR
   ========================================================= */
.topbar {
  display: flex; align-items: center; justify-content: space-between;
  gap: 10px;
  padding: 0 20px;
  height: 68px;
  padding-top: env(safe-area-inset-top);
  background: rgba(232,221,208,.92);
  backdrop-filter: saturate(180%) blur(14px);
  -webkit-backdrop-filter: saturate(180%) blur(14px);
  position: sticky; top: 0; z-index: 30;
  border-bottom: 1px solid var(--line);
}
.app .topbar { width: 100%; }

/* Centred logo on the home page only */
body.page-home .topbar { justify-content: center; }

.brand { display: inline-flex; text-decoration: none; }
.brand-name {
  font-family: var(--font-display);
  font-optical-sizing: auto;
  font-weight: 900;
  font-size: 28px;
  letter-spacing: -.03em;
  line-height: 1;
}
.brand-name .b1 { color: var(--ink); }
.brand-name .b2 { color: var(--amber); font-style: italic; }

.play-actions { display: flex; gap: 8px; align-items: center; }
.icon-btn {
  background: transparent;
  border: none;
  width: 44px; height: 44px;
  border-radius: 12px;
  display: inline-flex; align-items: center; justify-content: center;
  color: var(--ink-2);
  transition: color .15s, background .15s, transform .1s;
}
.icon-btn svg { width: 22px; height: 22px; }
.icon-btn:hover  { color: var(--ink); background: var(--line); }
.icon-btn:active { transform: scale(.9); }
.icon-btn[disabled] { opacity: .3; cursor: not-allowed; pointer-events: none; }
.icon-btn svg { display: block; }

/* =========================================================
   HOME
   ========================================================= */
main { padding: 28px 20px 48px; }
body.page-home main {
  display: flex;
  flex-direction: column;
  gap: 14px;
  padding: 28px clamp(20px, 7%, 48px) 40px;
  max-width: 440px;
  margin-left: auto;
  margin-right: auto;
  width: 100%;
}

/* Footer */
body.page-home .site-footer {
  padding: 16px 20px calc(24px + env(safe-area-inset-bottom));
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
}
.footer-copy {
  font-size: 12px;
  font-weight: 500;
  color: var(--ink-3);
  letter-spacing: -.005em;
}
.footer-nav {
  display: flex;
  gap: 16px;
  flex-wrap: wrap;
  justify-content: center;
}
.footer-nav a {
  font-size: 12px;
  font-weight: 500;
  color: var(--ink-3);
  text-decoration: none;
  letter-spacing: -.005em;
  transition: color .15s;
}
.footer-nav a:hover { color: var(--ink-2); }

/* ---- Step sections ---- */
/* Each step is a card. Active (unlocked) cards are crisp white, standing
   clearly above the warm stone page background. Locked cards blend into
   the background — transparent fill, dashed border, content faded to 40%
   — so the player's eye goes straight to the current action. */
body.page-home .step-section {
  background: var(--surface);
  border: 1.5px solid rgba(28,20,8,.10);
  border-radius: 20px;
  padding: 14px 16px;
  display: flex;
  flex-direction: column;
  gap: 12px;
  box-shadow: 0 2px 12px rgba(28,20,8,.07);
  transition: background .25s, border-color .25s, box-shadow .25s;
}
/* Locked: a subtle warm tint that's distinct from both the white active
   cards and the stone page background, plus a dashed border. Content is
   readable but clearly muted. */
body.page-home .step-section.is-locked {
  background: rgba(255,255,255,.45);
  border-style: dashed;
  border-color: rgba(28,20,8,.22);
  box-shadow: none;
}
/* Fade the step content (buttons, rows) but not the header */
body.page-home .step-section.is-locked > *:not(.step-head) {
  opacity: .65;
  pointer-events: none;
}

/* Step header: number+label on the left, lock hint on the right */
.step-head {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: 20px;
}
.step-label {
  font-size: 17px;
  font-weight: 700;
  color: var(--ink);
  letter-spacing: -.015em;
  text-align: center;
  transition: color .25s;
}
.step-lock {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: 11px;
  font-weight: 600;
  color: var(--ink-3);
  letter-spacing: -.005em;
  white-space: nowrap;
}
.step-lock[hidden] { display: none; }

/* Header text in locked steps — must come AFTER the base .step-label rule
   so it wins the cascade. */
body.page-home .step-section.is-locked .step-label {
  color: var(--ink-3);
}

/* Photo step: square preview capped at a sensible size */
body.page-home .upload-wrap {
  display: flex;
  flex-direction: column;
  gap: 10px;
  align-items: center;
}
body.page-home .upload-drop {
  width: 100%;
  max-width: 320px;
  aspect-ratio: 1 / 1;
}

/* Slimmer buttons inside steps */
body.page-home .btn-primary   { padding: 13px 20px; }
body.page-home .btn-secondary { padding: 12px 20px; }

/* Side-by-side share / play buttons */
body.page-home .actions {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
}
body.page-home .actions .btn-primary,
body.page-home .actions .btn-secondary {
  padding: 12px 10px;
  font-size: 14px;
  gap: 7px;
  white-space: nowrap;
  min-width: 0;
}

.hero {
  text-align: center;
  margin-bottom: 10px;
}
.hero h1 {
  font-family: var(--font-display);
  font-optical-sizing: auto;
  font-weight: 900;
  font-size: clamp(26px, 7vw, 36px);
  line-height: 1.1;
  letter-spacing: -.025em;
  margin: 0;
  color: var(--ink);
}
.hero h1 .italic {
  font-style: italic;
  color: var(--amber);
}
.hero-sub {
  margin: 24px 0 0;
  font-size: 15px;
  font-weight: 500;
  color: var(--ink-2);
  letter-spacing: -.005em;
}
.hero-sub .dot {
  color: var(--ink-3);
  margin: 0 4px;
  font-weight: 700;
}

/* Upload zone — preview tile + a primary CTA below it. The tile is a
   <label> that wraps the hidden file input, so clicking the preview is
   a shortcut for "open file picker"; the button is the explicit entry. */
.upload-wrap { margin-bottom: 20px; display: grid; gap: 12px; }

.upload-drop {
  position: relative;
  display: block;
  aspect-ratio: 1 / 1;
  border-radius: 20px;
  overflow: hidden;
  cursor: pointer;
  /* Warm cream base — only visible if the preview image fails to load. */
  background: var(--surface-3);
  box-shadow: inset 0 0 0 1px var(--line);
  transition: box-shadow .18s;
}
.upload-drop.dragover {
  box-shadow: inset 0 0 0 2px var(--amber);
}

/* Photo: sits behind the overlay. */
.upload-photo-wrap {
  position: absolute; inset: 0; z-index: 1;
}
.upload-photo-wrap .upload-photo {
  width: 100%; height: 100%;
  object-fit: cover; object-position: center;
  display: block;
  user-select: none; -webkit-user-drag: none;
}

/* Piece-grid overlay drawn on top of the photo. */
.upload-overlay {
  position: absolute; inset: 0; pointer-events: none; z-index: 2;
}
.upload-overlay svg { width: 100%; height: 100%; display: block; }
.upload-overlay path {
  fill: none;
  stroke: rgba(255,255,255,.35);
  stroke-width: 1;
  stroke-linejoin: round; stroke-linecap: round;
  vector-effect: non-scaling-stroke;
  transition: stroke .25s ease;
}

/* Loader shown while a freshly-picked photo is decoding. */
.upload-spinner {
  position: absolute; inset: 0; z-index: 3;
  display: flex; align-items: center; justify-content: center;
  background: rgba(255,255,255,.55);
  backdrop-filter: blur(2px);
  -webkit-backdrop-filter: blur(2px);
  border-radius: inherit;
}
.upload-spinner[hidden] { display: none; }
.upload-spinner .spinner {
  width: 38px; height: 38px;
  border-radius: 999px;
  border: 3px solid rgba(193,122,47,.22);
  border-top-color: var(--amber);
  animation: spin .7s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* Upload CTA button — a touch tighter than the main action buttons so it
   reads as a control on the preview tile, not as a primary page action. */
.upload-btn { padding: 13px 20px; }

.upload-privacy {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 5px;
  margin: 0;
  font-size: 12px;
  font-weight: 500;
  color: var(--ink-3);
  text-align: center;
  letter-spacing: -.005em;
}
.upload-privacy svg { flex: 0 0 auto; color: var(--ink-3); }


/* Difficulty */
.diff-section { margin-bottom: 20px; }
.section-label {
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin-bottom: 10px;
}
.diff-row {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: 6px;
}
.diff {
  background: var(--surface);
  border: 1.5px solid var(--line);
  color: var(--ink);
  padding: 12px 2px 10px;
  border-radius: 14px;
  display: flex; flex-direction: column; align-items: center; gap: 4px;
  transition: border-color .15s, background .15s, box-shadow .15s, transform .1s;
  min-width: 0;
}
.diff:active { transform: scale(.96); }
.diff .num {
  font-family: var(--font-display);
  font-optical-sizing: auto;
  font-weight: 900;
  font-size: 22px;
  line-height: 1;
  color: var(--ink);
  letter-spacing: -.02em;
  font-variant-numeric: tabular-nums;
}
.diff .tier {
  font-size: 9px;
  font-weight: 700;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--ink-3);
  white-space: nowrap;
}
.diff[aria-checked="true"] {
  background: var(--amber-tint);
  border-color: var(--amber-2);
  box-shadow: 0 2px 10px rgba(193,122,47,.14);
}
.diff[aria-checked="true"] .num  { color: var(--amber-3); }
.diff[aria-checked="true"] .tier { color: var(--amber);   }

/* Buttons */
.actions { display: grid; gap: 10px; }

.btn-primary {
  display: inline-flex; align-items: center; justify-content: center;
  gap: 9px; width: 100%;
  padding: 16px 20px;
  border-radius: 999px; border: none;
  background: var(--amber);
  color: #fff;
  font-family: var(--font-ui);
  font-size: 15.5px; font-weight: 700; letter-spacing: -.01em;
  box-shadow: 0 4px 16px rgba(193,122,47,.28);
  transition: background .15s, box-shadow .15s, transform .1s;
  text-decoration: none;
  cursor: pointer;
}
.btn-primary:hover  { background: var(--amber-3); }
.btn-primary:active { transform: scale(.985); }
.btn-primary:disabled {
  background: var(--surface-2); color: var(--ink-3);
  box-shadow: none; cursor: not-allowed;
}
/* Play-it-yourself and difficulty buttons share the same disabled look as
   the primary (share) button: a warm muted surface, no border emphasis. */
.btn-primary svg { width: 16px; height: 16px; flex: 0 0 auto; }

.btn-secondary {
  display: inline-flex; align-items: center; justify-content: center;
  gap: 9px; width: 100%;
  padding: 15px 20px;
  border-radius: 999px;
  border: 1.5px solid var(--line-2);
  background: var(--surface);
  color: var(--ink);
  font-family: var(--font-ui);
  font-size: 15.5px; font-weight: 600; letter-spacing: -.01em;
  box-shadow: var(--shadow-sm);
  transition: background .15s, border-color .15s, transform .1s;
  text-decoration: none;
  cursor: pointer;
}
.btn-secondary:hover  { background: var(--surface-3); }
.btn-secondary:active { transform: scale(.985); }
.btn-secondary:disabled {
  background: var(--surface-2); color: var(--ink-3);
  border-color: transparent; box-shadow: none;
  cursor: not-allowed; opacity: 1;
}
/* Difficulty buttons while photo not yet chosen */
.diff:disabled,
.diff[data-locked] {
  background: var(--surface-2);
  border-color: transparent;
  color: var(--ink-3);
  box-shadow: none;
  cursor: not-allowed;
  pointer-events: none;
}
.diff:disabled .num,
.diff[data-locked] .num { color: var(--ink-3); }
.diff:disabled .tier,
.diff[data-locked] .tier { color: var(--ink-3); opacity: .7; }
.btn-secondary svg { width: 16px; height: 16px; flex: 0 0 auto; color: var(--ink-2); }
.btn-secondary:disabled svg { color: inherit; }

/* =========================================================
   PLAY PAGE
   ========================================================= */
body.page-play {
  background: var(--bg-board);
  color: var(--ink);
  height: 100dvh; height: 100svh;
  overflow: hidden;
  overscroll-behavior: none;
  touch-action: manipulation;
  -webkit-user-select: none; -ms-user-select: none; user-select: none;
  -webkit-touch-callout: none;
  -webkit-tap-highlight-color: transparent;
}
body.page-play * {
  -webkit-user-select: none; user-select: none;
  -webkit-touch-callout: none;
  -webkit-tap-highlight-color: transparent;
}
body.page-play .app {
  height: 100dvh; height: 100svh;
  min-height: 0;
  overflow: hidden;
  display: flex; flex-direction: column;
  background: var(--bg-board);
}
/* Play page topbar matches the board background */
body.page-play .topbar {
  background: rgba(232,221,208,.95);
  border-bottom-color: rgba(28,20,8,.06);
}

.play-main {
  display: grid;
  grid-template-rows: 1fr auto;
  grid-template-columns: minmax(0, 1fr);
  flex: 1 1 0;
  min-width: 0; min-height: 0;
  width: 100%;
  padding: 0;
  overflow: hidden;
}

/* Board wrapper — just a sizing/clipping shell now. */
.board-wrap {
  position: relative;
  overflow: hidden;
  min-height: 0;
}

/* The board fills the entire wrapper area (rectangular). Plain warm
   "table" colour that sits BEHIND the puzzle. The square puzzle frame
   is drawn INSIDE .board-content so it scales/pans with zoom; on
   zoom-in, the puzzle expands into all of this rectangular space,
   between the topbar and the tray. */
.board {
  position: absolute;
  inset: 0;
  overflow: hidden;
  touch-action: none;
  cursor: grab;
}
.board.panning { cursor: grabbing; }

.board-content {
  position: absolute; inset: 0;
  transform-origin: 0 0;
  /* Note: NOT using `will-change: transform` here. It promotes this subtree
     to a GPU layer that gets rasterized once at its natural CSS-pixel size
     and then upscaled when the user zooms in — which is a major source of
     blur on the photo at higher zoom levels. Without will-change, browsers
     re-rasterize the SVG content at the new effective resolution, keeping
     the photo crisp at every zoom. The pan/zoom is still cheap because the
     transform itself is composited; we just don't lock the rasterization. */
}

/* The puzzle frame: lives inside .board-content so it scales/pans with
   the puzzle. Plain warm "paper" colour for the puzzle interior, plus a
   soft border so the player can see the bounds when zoomed out. Zoom in
   far enough and the border scales off-screen — a clear "you're zoomed
   in" cue. */
.board .frame-outline {
  position: absolute;
  background-color: #ffffff;
  border: 1.5px solid var(--amber);
  pointer-events: none;
}

/* Tray — two horizontal rows that scroll left/right together. */
:root { --tray-h: 90px; --tray-gap: 10px; --tray-pad-y: 12px; }
.tray-wrap {
  position: relative;
  background: var(--bg-board);
  box-shadow: inset 0 1px 0 rgba(28,20,8,.06);
  padding-bottom: env(safe-area-inset-bottom);
  width: 100%; max-width: 100%; min-width: 0;
  overflow: hidden;
}
.tray {
  /* CSS Grid laid out as two rows; pieces flow column-major (top-bottom,
     then left to next column). grid-auto-columns: max-content lets each
     column size to its widest piece. The container scrolls horizontally
     to reveal more columns as needed. */
  display: grid;
  grid-template-rows: var(--tray-h) var(--tray-h);
  grid-auto-flow: column;
  grid-auto-columns: max-content;
  gap: var(--tray-gap);
  align-items: center; justify-items: start;
  padding: var(--tray-pad-y) 18px;
  height: calc(var(--tray-h) * 2 + var(--tray-gap) + var(--tray-pad-y) * 2);
  width: 100%; max-width: 100%; min-width: 0;
  overflow-x: auto; overflow-y: hidden;
  -webkit-overflow-scrolling: touch;
  /* touch-action:none — the browser must NOT claim touches for native
     pan-x scrolling. Without this, iOS Safari fires `pointercancel` mid
     piece-drag the moment the gesture trends mostly-horizontal, ripping
     the piece out of the user's hand. We drive the tray's scrollLeft
     manually from JS instead — both for free tray scrubbing and while
     a piece is in hand — which lets a diagonal drag move the piece AND
     scroll the tray simultaneously. */
  touch-action: none;
  scrollbar-width: none;
  overscroll-behavior: contain;
}
.tray::-webkit-scrollbar { display: none; }

/* Pieces */
.piece {
  position: absolute;
  /* touch-action:none — pieces own all touch gestures themselves; tray
     scrolling is handled in JS while a piece is in hand so the browser
     never tries to claim the pointer. This keeps pickup reliable on
     fast/diagonal drags. */
  touch-action: none;
  user-select: none; -webkit-user-drag: none;
  will-change: transform;
  pointer-events: none;
}
.piece.in-tray {
  position: relative; flex: 0 0 auto;
  height: var(--tray-h);
  width: calc(var(--tray-h) * var(--ar, 1));
  filter: drop-shadow(0 2px 6px rgba(28,20,8,.18));
}
.piece-placeholder { flex: 0 0 auto; pointer-events: none; }
.piece.dragging { z-index: 1000; }
.piece svg {
  display: block; pointer-events: none;
  width: 100%; height: 100%;
  shape-rendering: geometricPrecision;
  /* Photo-quality scaling on the embedded <image>. Browsers default to
     `auto` which is bilinear, but setting it explicitly defends against
     any global override and matches our intent. */
  image-rendering: auto;
  overflow: visible;
}
.piece svg image {
  image-rendering: auto;
}
.piece svg .hit { pointer-events: fill; cursor: grab; }
.piece.dragging svg .hit { cursor: grabbing; }
.piece.locked  svg .hit { pointer-events: none; cursor: default; }
.piece svg .edge {
  stroke: rgba(28,20,8,.45); stroke-width: 1.1; fill: none;
  vector-effect: non-scaling-stroke;
  stroke-linejoin: round; stroke-linecap: round;
}
.piece svg .gloss {
  stroke: rgba(255,255,255,.28); stroke-width: .8; fill: none;
  vector-effect: non-scaling-stroke; stroke-linejoin: round;
}

/* Win card */
.win-card {
  position: fixed; inset: 0; z-index: 100;
  background: rgba(28,20,8,.45);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  display: flex; align-items: center; justify-content: center; padding: 24px;
  animation: fade .3s ease both;
}
.win-card[hidden] { display: none; }
[hidden] { display: none !important; }
@keyframes fade { from { opacity: 0; } to { opacity: 1; } }

.win-inner {
  background: var(--surface);
  border-radius: 28px;
  padding: 32px 28px;
  max-width: 360px; width: 100%;
  text-align: center;
  box-shadow: var(--shadow-lg);
  animation: pop .35s cubic-bezier(.3,1.4,.5,1) both;
}
@keyframes pop { from { transform: scale(.88); opacity: 0; } }

.win-inner h2 {
  font-family: var(--font-display);
  font-optical-sizing: auto;
  font-weight: 900;
  font-style: italic;
  font-size: 40px;
  letter-spacing: -.025em;
  color: var(--amber);
  margin: 0 0 6px;
}
.win-inner p { color: var(--ink-2); margin: 0; font-size: 15px; }
.win-actions { display: grid; gap: 10px; margin-top: 22px; }

/* Settings card */
.settings-card {
  position: fixed; inset: 0; z-index: 110;
  background: rgba(28,20,8,.45);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  display: flex; align-items: center; justify-content: center; padding: 24px;
  animation: fade .25s ease both;
}
.settings-card[hidden] { display: none; }

.settings-inner {
  background: var(--surface);
  border-radius: 28px;
  padding: 22px 24px 26px;
  max-width: 420px; width: 100%;
  box-shadow: var(--shadow-lg);
  animation: pop .3s cubic-bezier(.3,1.4,.5,1) both;
}

.settings-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px;
  margin-bottom: 18px;
}
.settings-head h2 {
  font-family: var(--font-display);
  font-optical-sizing: auto;
  font-weight: 900;
  font-size: 24px;
  letter-spacing: -.02em;
  color: var(--ink);
  margin: 0;
}
.settings-head .icon-btn {
  width: 36px; height: 36px;
  border-radius: 10px;
  color: var(--ink-2);
}

.settings-body { display: grid; gap: 18px; }

.setting-row {
  display: grid;
  gap: 10px;
  padding: 14px 16px;
  background: var(--surface-3);
  border: 1px solid var(--line);
  border-radius: 16px;
}
.setting-row-head {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 12px;
}
.setting-label {
  font-size: 14px;
  font-weight: 600;
  color: var(--ink);
}
.setting-value {
  font-family: var(--font-display);
  font-optical-sizing: auto;
  font-weight: 900;
  font-size: 16px;
  color: var(--amber);
  letter-spacing: -.01em;
  font-variant-numeric: tabular-nums;
}

/* Range slider — custom amber thumb on a tinted track. */
input[type="range"].setting-slider,
.setting-row input[type="range"] {
  -webkit-appearance: none; appearance: none;
  width: 100%;
  height: 28px;
  background: transparent;
  cursor: pointer;
  margin: 0;
}
.setting-row input[type="range"]:focus { outline: none; }

.setting-row input[type="range"]::-webkit-slider-runnable-track {
  height: 6px;
  background: var(--amber-soft);
  border-radius: 999px;
}
.setting-row input[type="range"]::-moz-range-track {
  height: 6px;
  background: var(--amber-soft);
  border-radius: 999px;
  border: none;
}

.setting-row input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none;
  width: 22px; height: 22px;
  margin-top: -8px;
  border-radius: 999px;
  background: var(--amber);
  border: 3px solid #fff;
  box-shadow: 0 2px 8px rgba(193,122,47,.35);
  cursor: grab;
}
.setting-row input[type="range"]::-moz-range-thumb {
  width: 22px; height: 22px;
  border-radius: 999px;
  background: var(--amber);
  border: 3px solid #fff;
  box-shadow: 0 2px 8px rgba(193,122,47,.35);
  cursor: grab;
}
.setting-row input[type="range"]:active::-webkit-slider-thumb { cursor: grabbing; }
.setting-row input[type="range"]:active::-moz-range-thumb     { cursor: grabbing; }

/* Dragged-piece overlay */
.piece-layer { position: fixed; inset: 0; pointer-events: none; z-index: 90; }
.piece-layer .piece { pointer-events: auto; }

/* =========================================================
   SHARE MODAL
   Used both on the home page (when "Send to a friend" is clicked) and
   on the play page (toolbar share button + win card share button). The
   modal has three states: loading, ready, error. JS toggles `hidden` on
   each `.share-state` to switch between them.
   ========================================================= */
.share-modal {
  position: fixed; inset: 0; z-index: 120;
  background: rgba(28,20,8,.45);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  display: flex; align-items: center; justify-content: center;
  padding: 24px;
  animation: fade .25s ease both;
}
.share-modal[hidden] { display: none; }

.share-card {
  position: relative;
  background: var(--surface);
  border-radius: 28px;
  padding: 32px 28px 28px;
  max-width: 380px; width: 100%;
  box-shadow: var(--shadow-lg);
  animation: pop .35s cubic-bezier(.3,1.4,.5,1) both;
}

.share-close {
  position: absolute;
  top: 8px; right: 8px;
  width: 36px; height: 36px;
  border-radius: 10px;
}

.share-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
  text-align: center;
  min-height: 200px;
  justify-content: center;
}
.share-state[hidden] { display: none; }

.share-spinner {
  width: 44px; height: 44px;
  border-radius: 999px;
  border: 4px solid var(--amber-soft);
  border-top-color: var(--amber);
  animation: spin .7s linear infinite;
}

.share-loading-text {
  margin: 0;
  font-size: 14px;
  color: var(--ink-2);
  font-weight: 500;
}

.share-state-ready h2 {
  font-family: var(--font-display);
  font-optical-sizing: auto;
  font-weight: 900;
  font-style: italic;
  font-size: 28px;
  letter-spacing: -.02em;
  color: var(--amber);
  margin: 0;
}
.share-sub {
  margin: 0;
  color: var(--ink-2);
  font-size: 14px;
}

/* The two action buttons fade + slide in once the upload completes. */
.share-actions {
  display: grid;
  gap: 10px;
  width: 100%;
  margin-top: 6px;
  opacity: 0;
  transform: translateY(8px);
  transition: opacity .35s ease, transform .35s ease;
}
.share-actions.share-actions-shown {
  opacity: 1;
  transform: translateY(0);
}
.share-actions .btn-primary,
.share-actions .btn-secondary {
  padding: 13px 20px;
  font-size: 14.5px;
}

.share-error-text {
  margin: 0;
  color: var(--ink-2);
  font-size: 14px;
}
