/* ABOUTME: Mobile-first styles for tug-of-war: brand header, field halves, dot, mesh, modal. */
/* ABOUTME: All colors and layout-critical sizes are CSS custom properties for easy override. */

:root {
  --qrky-blue: #1a73e8;
  --qrky-green: #34a853;
  --field-red: #e53935;
  --field-blue: #1e88e5;
  --field-bg: #fafafa;
  /* Hemp-rope colours: warm tan with darker shade for the diagonal twist. */
  --rope-color: #c89669;
  --rope-shade: #8b5a2b;
  --rope-thickness: 12px;
  --modal-overlay: rgba(0, 0, 0, 0.45);
  --header-height: 56px;
  --safe-top: env(safe-area-inset-top, 0px);
  --text-primary: #212121;
  --text-muted: #757575;
  --tile-bg: #ffffff;
  --tile-border: #e0e0e0;
  --error: #c62828;
  --font-ui:
    'Montserrat', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
}

* {
  box-sizing: border-box;
}

html,
body {
  margin: 0;
  padding: 0;
  height: 100%;
  font-family: var(--font-ui);
  background: var(--field-bg);
  color: var(--text-primary);
  overscroll-behavior: none;
  touch-action: manipulation;
}

body {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

.brand-header {
  height: var(--header-height);
  padding-top: var(--safe-top);
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 800;
  font-size: 1.5rem;
  letter-spacing: 0.02em;
  background: #ffffff;
  border-bottom: 1px solid var(--tile-border);
}

.brand-tug {
  color: var(--qrky-blue);
}
.brand-of {
  color: var(--text-primary);
}
.brand-war {
  color: var(--qrky-green);
}

#app-root {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  min-height: 0;
}

.screen {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
}

.screen[hidden] {
  display: none;
}

/* --- Home screen --- */
.screen-home {
  padding: 24px 16px;
  gap: 16px;
}

.tile {
  background: var(--tile-bg);
  border: 1px solid var(--tile-border);
  border-radius: 12px;
  padding: 24px;
  display: flex;
  flex-direction: column;
  gap: 12px;
  align-items: stretch;
}

.tile-label {
  font-size: 1rem;
  color: var(--text-muted);
}

.primary-button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--qrky-blue);
  color: #ffffff;
  border: none;
  border-radius: 8px;
  padding: 14px 20px;
  font-size: 1.05rem;
  font-weight: 600;
  cursor: pointer;
}

.primary-button:focus {
  outline: 2px solid var(--qrky-green);
  outline-offset: 2px;
}

.join-form {
  display: flex;
  gap: 8px;
  justify-content: center;
}

.code-input {
  flex: 0 1 200px;
  max-width: 200px;
  font-size: 1.5rem;
  letter-spacing: 0.4em;
  text-align: center;
  padding: 12px;
  border-radius: 8px;
  border: 1px solid var(--tile-border);
}

.join-submit {
  width: 56px;
  background: var(--qrky-green);
  color: #ffffff;
  border: none;
  border-radius: 8px;
  font-size: 1.5rem;
  font-weight: 700;
  cursor: pointer;
}

.inline-error {
  color: var(--error);
  font-size: 0.95rem;
  margin: 0;
}

/* --- Game screen shell --- */
.screen-game {
  position: relative;
  overflow: hidden;
}

.game-header {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  padding: 8px 12px;
  border-bottom: 1px solid var(--tile-border);
  background: #ffffff;
}

.game-header .exit-button {
  position: absolute;
  left: 12px;
  top: 50%;
  transform: translateY(-50%);
}

.exit-button {
  background: transparent;
  border: 1px solid var(--tile-border);
  border-radius: 6px;
  padding: 6px 10px;
  font-size: 0.95rem;
  cursor: pointer;
}

.game-timer {
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  font-size: 20px;
  min-width: 6ch;
  text-align: center;
}

/* Per-side counts and live scores overlaid on the field halves, centred
   between the QR boundary (~80 px wide, centred on screen) and the screen
   edge. They sit at the top of the field, just below the game-header, so
   they don't compete with the rope/dot area near the bottom. */
.count {
  position: absolute;
  top: 12px;
  font-weight: 700;
  font-size: 44px;
  letter-spacing: 0.05em;
  transform: translateX(-50%);
  z-index: 3;
  pointer-events: none;
  text-shadow: 0 1px 2px rgba(255, 255, 255, 0.7);
  line-height: 1;
}

.count-blue {
  left: calc(75% + 20px);
  color: var(--field-blue);
}

.count-red {
  left: calc(25% - 20px);
  color: var(--field-red);
}

/* Live score (0–100) per side, updated every render frame from dotX.
   Sits beneath the matching count. Only the winning side shows a non-zero
   value; the other shows 0 until the dot is pulled past centre. */
.score {
  position: absolute;
  top: 72px;
  font-weight: 600;
  font-size: 22px;
  letter-spacing: 0.04em;
  transform: translateX(-50%);
  z-index: 3;
  pointer-events: none;
  text-shadow: 0 1px 2px rgba(255, 255, 255, 0.7);
  line-height: 1;
}

.score-blue {
  left: calc(75% + 20px);
  color: var(--field-blue);
  opacity: 0.85;
}

.score-red {
  left: calc(25% - 20px);
  color: var(--field-red);
  opacity: 0.85;
}

/* --- Field --- */
.field {
  position: relative;
  flex: 1 1 auto;
  width: 100%;
  overflow: hidden;
  background: var(--field-bg);
  contain: strict;
  /* Suppress mobile gesture defaults so a long-press / drag on the dot is
     interpreted as gameplay input, not a system action (text selection,
     callout, double-tap zoom, scroll). preventDefault() in input.js does
     the runtime side. */
  touch-action: none;
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  user-select: none;
  -webkit-tap-highlight-color: transparent;
}

.field-half {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 50%;
}

.field-half-red {
  left: 0;
  background: rgba(229, 57, 53, 0.06);
}

.field-half-blue {
  right: 0;
  background: rgba(30, 136, 229, 0.06);
}

/* Mesh overlay sits on the user's *opposite* half. JS sets the side via a class
   so we never paint-invalidate. */
.mesh-overlay {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 50%;
  pointer-events: none;
  z-index: 2;
  background-image:
    repeating-linear-gradient(
      45deg,
      rgba(0, 0, 0, 0.08) 0,
      rgba(0, 0, 0, 0.08) 2px,
      transparent 2px,
      transparent 8px
    ),
    repeating-linear-gradient(
      -45deg,
      rgba(0, 0, 0, 0.08) 0,
      rgba(0, 0, 0, 0.08) 2px,
      transparent 2px,
      transparent 8px
    );
  display: none;
}

.mesh-overlay.mesh-left {
  left: 0;
  display: block;
}

.mesh-overlay.mesh-right {
  right: 0;
  display: block;
}

/* Rope: 3D-ish twisted hemp. Three stacked background layers:
     1. Top: regularly-spaced elliptical highlights (the "crowns" of the
        twist) to suggest an undulated top surface — repeated every 20 px.
     2. Middle: full-height vertical gradient (light → mid → shadow) for
        cylindrical shading so the rope looks rounded.
     3. Bottom: diagonal repeating stripes for the weave itself.
   A border-radius + drop shadow finish the 3D effect. */
.rope {
  position: absolute;
  bottom: 2in;
  left: 0;
  right: 0;
  height: var(--rope-thickness);
  background-image:
    radial-gradient(
      ellipse 6px 3px at 10px 3px,
      rgba(255, 255, 255, 0.55) 0%,
      rgba(255, 255, 255, 0) 70%
    ),
    linear-gradient(
      to bottom,
      rgba(255, 255, 255, 0.35) 0%,
      rgba(255, 255, 255, 0.1) 35%,
      rgba(0, 0, 0, 0) 55%,
      rgba(0, 0, 0, 0.35) 100%
    ),
    repeating-linear-gradient(
      115deg,
      var(--rope-color) 0 6px,
      var(--rope-shade) 6px 10px,
      var(--rope-color) 10px 16px
    );
  background-size:
    20px 100%,
    100% 100%,
    auto auto;
  background-repeat: repeat-x, no-repeat, repeat;
  background-position:
    top left,
    center,
    center;
  border-top: 1px solid rgba(255, 255, 255, 0.4);
  border-bottom: 1px solid rgba(0, 0, 0, 0.45);
  border-radius: 4px;
  box-shadow: 0 3px 4px rgba(0, 0, 0, 0.25);
  transform: translateY(50%);
  z-index: 3;
}

.dot {
  position: absolute;
  bottom: 2in;
  left: 50%;
  width: 80px;
  height: 80px;
  border: 2px solid #000;
  box-sizing: border-box;
  border-radius: 50%;
  /* Initial gradient; ui.js#rafLoop overrides per-frame based on dotX. */
  background: linear-gradient(90deg, var(--field-red), var(--field-blue));
  transform: translate3d(-50%, 50%, 0);
  will-change: transform, background;
  z-index: 4;
  /* Block mobile long-press / callout / selection / tap-highlight on the dot
     itself so a deliberate long press registers as mass measurement, not as
     a system action. */
  touch-action: none;
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  user-select: none;
  -webkit-tap-highlight-color: transparent;
}

/* During Running the prestart pane stays visible (so latecomers can scan the
   QR) but compacts to a small QR + code label docked just below the game
   header. The per-side counts and live scores straddle it in the field
   halves. */
.prestart-pane--during-running {
  position: absolute;
  top: 60px;
  left: 50%;
  transform: translateX(-50%);
  flex-direction: column;
  align-items: center;
  gap: 4px;
  padding: 6px;
  background: rgba(255, 255, 255, 0.9);
  border-radius: 6px;
  z-index: 5;
  pointer-events: none;
}
.prestart-pane--during-running .prestart-hint {
  display: none;
}
.prestart-pane--during-running .primary-button,
.prestart-pane--during-running .muted {
  display: none !important;
}
.prestart-pane--during-running canvas {
  width: 80px !important;
  height: 80px !important;
}
.prestart-pane--during-running .qr-code-label {
  font-size: 14px;
}

/* Game-code label rendered directly under the QR so it's obvious which code
   the QR encodes. Shown in both PreStart and Running (compact). */
.qr-code-label {
  font-weight: 700;
  letter-spacing: 0.2em;
  font-size: 18px;
  color: var(--text-base, #111);
}

/* --- PreStart --- */
.prestart-pane {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  padding: 16px;
}

.prestart-hint {
  margin: 0;
  color: var(--text-muted);
}

.muted {
  color: var(--text-muted);
}

#qr-canvas {
  width: 220px;
  height: 220px;
}

.prestart-pane[hidden] {
  display: none;
}

/* --- Splash --- */
.splash-pane {
  position: absolute;
  inset: 0;
  background: rgba(255, 255, 255, 0.92);
  z-index: 10;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 12px;
  padding: 16px;
}

.splash-pane[hidden] {
  display: none;
}

.splash-winner {
  font-size: 2rem;
  font-weight: 800;
  margin: 0;
}

.splash-score {
  font-size: 1.25rem;
  margin: 0;
}

.splash-counts {
  margin: 0;
  color: var(--text-muted);
}

/* --- Gate overlay (3-2-1 for mid-game joiners) --- */
.gate-overlay {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.35);
  z-index: 11;
  display: flex;
  align-items: center;
  justify-content: center;
}

.gate-overlay[hidden] {
  display: none;
}

.gate-countdown {
  font-size: 6rem;
  font-weight: 800;
  color: #ffffff;
}

/* --- Exit modal --- */
.modal {
  position: fixed;
  inset: 0;
  z-index: 100;
  background: var(--modal-overlay);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 16px;
}

.modal[hidden] {
  display: none;
}

.modal-card {
  background: #ffffff;
  border-radius: 12px;
  padding: 20px;
  max-width: 360px;
  width: 100%;
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.18);
}

.modal-title {
  margin: 0 0 8px 0;
  font-size: 1.2rem;
}

.modal-body {
  margin: 0 0 16px 0;
  color: var(--text-muted);
}

.modal-actions {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
}

.modal-button {
  padding: 10px 14px;
  border-radius: 8px;
  border: 1px solid var(--tile-border);
  background: #ffffff;
  font-size: 1rem;
  cursor: pointer;
}

.modal-confirm {
  background: var(--error);
  color: #ffffff;
  border-color: var(--error);
}
