:root {
  --hub-size: 34%;          /* diameter of center cutout relative to screen min-dim */
  --bar-h: 56px;            /* bottom bar height, excluding the safe area */
  /* Total space the bottom bar occupies above the screen edge. */
  --bar-space: calc(var(--bar-h) + env(safe-area-inset-bottom, 0px));
}

* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }

html {
  margin: 0;
  width: 100%;
  /* Overshoot the bottom safe area so iOS standalone PWAs paint black under
     the home indicator instead of a blank strip (khmyznikov.com/pwa-install). */
  height: calc(100vh + env(safe-area-inset-bottom, 0px));
  background: #000;
}

body {
  margin: 0;
  height: 100%;
  /* Same black as .screen so any gap the viewport leaves below it
     (Safari toolbars, PWA safe areas) is indistinguishable from it. */
  background: #000;
  color: #f4f1ea;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
  overflow: hidden;
  user-select: none;
  -webkit-user-select: none;
  touch-action: manipulation;
}

/* ---------- Device frame ---------- */
.device {
  position: fixed;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}

.screen {
  position: relative;
  width: 100vw;
  height: 100vh;
  height: -webkit-fill-available; /* iOS: true viewport height in standalone PWAs */
  height: 100dvh;
  background: #000;
  overflow: hidden;
}

/* Desktop: render an iPhone-sized frame instead of a real browser layout. */
@media (min-width: 520px) {
  body { background: #0a0c10; }
  .device { padding: 24px; }
  .screen {
    width: 390px;
    height: 844px;
    max-height: calc(100vh - 36px);
    border-radius: 46px;
    box-shadow: 0 0 0 12px #1c1f27, 0 0 0 14px #2a2e38,
                0 30px 70px rgba(0,0,0,.65);
  }
  /* notch */
  .screen::before {
    content: "";
    position: absolute;
    top: 10px; left: 50%;
    transform: translateX(-50%);
    width: 120px; height: 26px;
    background: #05070b;
    border-radius: 16px;
    z-index: 60;
    pointer-events: none;
  }
}

/* ---------- Board ---------- */
/* Square board area pinned just below the notch, so the dead space that used
   to sit above the centered circle goes to the dice strip at the bottom. */
.board-area {
  position: absolute;
  top: max(calc(env(safe-area-inset-top, 0px) + 6px), 42px);
  left: 0;
  width: 100%;
  aspect-ratio: 1;
}
/* Dark leather backing inside the mask square so the felt doesn't shine
   through the corners around the dial. Bleeds 2px past the square to meet
   the frame stroke (which is drawn half inside / half outside the edge). */
.board-area::before {
  content: "";
  position: absolute;
  inset: -2px;
  background: #221913 url("leather.png") repeat;
  background-size: 512px 512px;
}
#board {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  /* Let the frame's outer stroke half and edge-hugging wedge outlines paint
     past the square instead of being shaved off against the felt. */
  overflow: visible;
}

/* Outline of the board mask itself, so wedges squared off at the mask edge
   keep the same border the circular arcs have. Width matches .wedge .sep. */
#board .frame { fill: none; stroke: #000; stroke-width: 1.1; }

.wedge {
  cursor: pointer;
  transition: filter .15s ease;
}
.wedge .sep { fill: none; stroke: #000; stroke-width: 1.1; }

/* Only the current player's wedge is filled with their colour; everyone
   else is shown as a thick coloured outline over the leather. */
.wedge .slice { fill-opacity: 0; transition: fill-opacity .25s ease; }
.wedge.current .slice { fill-opacity: 1; }
.wedge .ring { fill: none; pointer-events: none; transition: opacity .25s ease; }
.wedge.current .ring { opacity: 0; }

/* White overlay that pulses on the active player's section. */
.wedge .glow {
  fill: #fff;
  opacity: 0;
  pointer-events: none;
}
.wedge.active .glow {
  animation: flash 1.5s ease-in-out infinite;
}
@keyframes flash {
  0%, 100% { opacity: 0; }
  50%      { opacity: 0.34; }
}
/* Brightness swing as well, so the flash is visible even on the white wedge. */
.wedge.active .slice {
  animation: pulse 1.5s ease-in-out infinite;
}
@keyframes pulse {
  0%, 100% { filter: brightness(1.12); }
  50%      { filter: brightness(0.70); }
}

.wedge .time {
  font-weight: 700;
  text-anchor: middle;
  dominant-baseline: middle;
  paint-order: stroke;
  stroke: rgba(0,0,0,.28);
  stroke-width: .3;
  pointer-events: none;
}
.wedge.low .time { fill: #fff !important; }
.wedge.dead .slice { filter: saturate(.35) brightness(.6); }

/* ---------- Center hub ---------- */
/* One circle, sliced by a horizontal chord: the upper two thirds are the
   marble play/pause button, the lower third is the undo-turn button. */
.hub {
  position: absolute;
  top: 50%; left: 50%;
  transform: translate(-50%, -50%);
  width: var(--hub-size);
  aspect-ratio: 1;
  min-width: 120px;
  border-radius: 50%;
  /* Real border, not an inset shadow: overflow clipping stops the buttons at
     the border's inner edge, so the marble can't bleed past the ring. */
  border: 4px solid #000;
  overflow: hidden;               /* clips the stacked buttons to the circle */
  background: #10131a;
  box-shadow: 0 6px 22px rgba(0,0,0,.5);
  display: flex;
  flex-direction: column;
  z-index: 30;
}
.hub-btn {
  appearance: none;
  border: none;
  background: #20242e;
  color: #f4f1ea;
  border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  box-shadow: 0 2px 8px rgba(0,0,0,.4);
  cursor: pointer;
}
.hub-btn:active { transform: scale(.92); background: #2b3140; }

/* Hub sections: full-width slices of the circle, no pill styling. */
.hub .hub-btn { width: 100%; border-radius: 0; box-shadow: none; }
.hub .hub-btn:active { transform: none; }

.hub-btn.play {
  flex: 0 0 66.7%;
  background: #e9e6df url("marble.png");
  background-size: 256px 256px;
  color: #000;
  border-bottom: 3px solid #000;   /* chord between the two sections */
}
/* Nudge the glyph toward the circle's center: the section's visual weight
   sits lower than its geometric middle. */
.hub-btn.play svg { transform: translateY(9%); }
.hub-btn.play:active { background-color: #cfccc5; filter: brightness(.92); }
.hub-btn.undo {
  flex: 1 1 auto;
  /* Inverted marble: black stone with light veins. */
  background: #16191f url("marble_dark.png");
  background-size: 256px 256px;
  color: #f4f1ea;
}
.hub-btn.undo:active { filter: brightness(.8); }

.hub-btn.small { width: 40px; height: 40px; }

/* ---------- Bottom bar ---------- */
/* Black strip along the bottom edge: timer settings left, dice settings
   right. Replaces the two floating corner gears. */
.bottom-bar {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  /* No safe-area padding: the buttons stretch the full strip (home-indicator
     area included) so the icons sit at the visual center of the black bar. */
  height: var(--bar-space);
  background: #000;
  display: flex;
  align-items: stretch;
  z-index: 50;
}
.bar-btn {
  appearance: none;
  flex: 1;
  border: none;
  background: transparent;
  color: #8b93a3;
  display: flex;
  align-items: center;
  justify-content: center;
  /* Lift the icon off the credit line at the bar's bottom edge. */
  padding-bottom: 14px;
  cursor: pointer;
}
.bar-btn:active { color: #f4f1ea; background: #12151c; }

/* Discreet footer credit hugging the very bottom edge of the screen,
   inside the safe-area strip under the buttons. */
.bar-credit {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 2px;
  text-align: center;
  font-size: 9px;
  letter-spacing: .06em;
  color: #4a5160;
  pointer-events: none;
}

/* Toggle play/pause glyphs based on .running on the hub. */
.ic-pause { display: none; }
.hub.running .ic-play { display: none; }
.hub.running .ic-pause { display: block; }

/* ---------- Felt dice table ---------- */
/* The only green-felt surface in the app: a full-width rounded panel filling
   the strip between the board square and the bottom of the screen. Top edge
   sits just below the board (board bottom = board top offset + screen width,
   since the board is a full-width square). */
.dice-felt {
  position: absolute;
  left: 0;
  right: 0;
  top: calc(max(calc(env(safe-area-inset-top, 0px) + 6px), 42px) + 100vw + 10px);
  bottom: var(--bar-space);
  border-radius: 22px;
  background:
    radial-gradient(ellipse at 50% 30%, rgba(255,255,255,.05), rgba(0,0,0,.30) 80%),
    #166738 url("felt.png") repeat;
  background-size: auto, 512px 512px;
  box-shadow: inset 0 0 0 1px rgba(0,0,0,.5);
  z-index: 10;
  /* Centers the "Dice disabled" label when dice are off. */
  display: flex;
  align-items: center;
  justify-content: center;
}
.dice-disabled {
  font-size: 13px;
  font-weight: 600;
  letter-spacing: .22em;
  text-transform: uppercase;
  color: rgba(244,241,234,.38);
  text-shadow: 0 1px 3px rgba(0,0,0,.6);
  user-select: none;
}
.dice-disabled[hidden] { display: none; }
/* Desktop frame: the screen is a fixed 390px wide, not 100vw. */
@media (min-width: 520px) {
  .dice-felt { top: calc(42px + 390px + 10px); }
}

/* ---------- 3D dice (WebGL canvas over the felt) ---------- */
.dice {
  position: absolute;
  left: 0;
  /* Canvas is a replaced element: left+right / top+bottom alone won't stretch
     it. dice3d.js sets top/height inline so the canvas overlays the felt
     (plus bounce headroom) and the camera axis hits the felt's center; the
     values here are only a pre-JS fallback. */
  width: 100%;
  top: calc(max(calc(env(safe-area-inset-top, 0px) + 6px), 42px) + 100vw + 10px);
  height: 300px;
  z-index: 40;
  /* Clickable: when paused a tap here resumes play (app.js); when running the
     click bubbles to the screen handler and advances the turn as before. */
}

/* Dice mode (balance) indicator, bottom-right corner of the felt */
.dice-ui {
  position: absolute;
  right: 12px;
  bottom: calc(var(--bar-space) + 10px);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  z-index: 45;
}
.dice-mode { color: #8b93a3; opacity: .55; line-height: 0; }
.dice-ui.dice-off .dice-mode { opacity: .18; }

/* ---------- Settings modal ---------- */
.modal-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(0,0,0,.62);
  backdrop-filter: blur(3px);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 80;
  padding: 18px;
}
.modal-backdrop[hidden] { display: none; }
.modal {
  width: 100%;
  max-width: 340px;
  max-height: 92%;
  overflow-y: auto;
  background: #181c25;
  border: 1px solid #2a2e38;
  border-radius: 20px;
  padding: 18px 18px 16px;
  box-shadow: 0 20px 60px rgba(0,0,0,.6);
}
.modal h2 { margin: 0 0 14px; font-size: 20px; }
.row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 12px;
  font-size: 15px;
}
.row > span:first-child { color: #c6ccd8; }
select, input[type="number"] {
  background: #10131a;
  color: #f4f1ea;
  border: 1px solid #313643;
  border-radius: 10px;
  padding: 8px 10px;
  font-size: 15px;
  font-variant-numeric: tabular-nums;
}
input[type="number"] { width: 56px; text-align: center; }
.time-input { display: inline-flex; align-items: center; gap: 4px; color: #8b93a3; }

.row input[type="checkbox"] { width: 20px; height: 20px; accent-color: #e08e2a; }

/* Segmented dice-mode toggle: Off / Random / Balanced */
.seg {
  display: flex;
  gap: 4px;
  padding: 4px;
  background: #10131a;
  border: 1px solid #313643;
  border-radius: 14px;
  margin-bottom: 10px;
}
.seg-opt {
  appearance: none;
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 5px;
  padding: 10px 4px 8px;
  border: none;
  border-radius: 10px;
  background: transparent;
  color: #8b93a3;
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
  transition: background .15s, color .15s;
}
.seg-opt svg { display: block; }
.seg-opt:not(.active):active { background: #1c212c; }
.seg-opt.active {
  background: #e08e2a;
  color: #1a1206;
  box-shadow: 0 2px 8px rgba(0,0,0,.35);
}
.modal .hint { font-size: 12px; color: #8b93a3; line-height: 1.4; margin: 2px 0 10px; }

.reorder-hint {
  font-size: 12px;
  color: #8b93a3;
  margin: 2px 0 8px;
}
.reorder-hint span { color: #c6ccd8; }

.colors { margin: 2px 0 4px; }
.color-row {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 8px;
  background: #10131a;
  border: 1px solid #262b36;
  border-radius: 10px;
  padding: 6px 10px;
}
.color-row.dragging {
  opacity: .85;
  border-color: #e08e2a;
  box-shadow: 0 6px 18px rgba(0,0,0,.5);
}
.color-row .drag-handle {
  flex: 0 0 auto;
  font-size: 18px;
  line-height: 1;
  color: #6b7280;
  cursor: grab;
  touch-action: none;
  padding: 4px 2px;
}
.color-row .drag-handle:active { cursor: grabbing; }
.color-row input[type="color"] {
  width: 44px; height: 30px;
  background: none; border: none; padding: 0;
  border-radius: 6px;
  flex: 0 0 auto;
}
.color-row .pname { flex: 1; color: #c6ccd8; font-size: 14px; }

.turn-pick { flex: 0 0 auto; display: inline-flex; cursor: pointer; }
.turn-pick input { display: none; }
.turn-pick span {
  font-size: 12px;
  padding: 5px 10px;
  border-radius: 8px;
  background: #262b36;
  color: #9aa3b2;
  border: 1px solid #313643;
}
.turn-pick input:checked + span {
  background: #e08e2a;
  color: #1a1206;
  border-color: #e08e2a;
  font-weight: 700;
}

.modal-actions {
  display: flex;
  gap: 10px;
  margin-top: 14px;
}
.btn {
  flex: 1;
  padding: 12px;
  border-radius: 12px;
  border: none;
  font-size: 15px;
  font-weight: 600;
  cursor: pointer;
}
.btn.primary { background: #e08e2a; color: #1a1206; }
.btn.ghost { background: #262b36; color: #f4f1ea; }
.btn.danger { background: #c0392b; color: #fff; }
.btn.wide { width: 100%; margin-top: 4px; }
.btn:active { transform: scale(.97); }

/* Reset confirmation sits above the settings modal. */
.confirm-backdrop { z-index: 90; }
.modal.confirm { max-width: 300px; text-align: center; }
.modal.confirm p { color: #c6ccd8; font-size: 14px; line-height: 1.4; margin: 0 0 4px; }
