/* Loopline tokens: dark mode only changes these values. */
:root {
  --g-loopline: #4b5fd6;
  --loop-paper: #ffffff;
  --loop-dot: #1b1b1b;
  --loop-guide: #e2e2dc;
  --loop-line: #1b1b1b;
  --loop-cross: #9a9a94;
  --loop-clue: #1b1b1b;
  --loop-clue-done: #2f9e6e;
  --loop-clue-bad: #d64545;
  --loop-cursor: #4b5fd6;
  --loop-solved: #4b5fd6;
}
:root[data-theme='dark'] {
  --g-loopline: #8796f0;
  --loop-paper: #1a1a1a;
  --loop-dot: #e8e8e8;
  --loop-guide: #343434;
  --loop-line: #f2f2f2;
  --loop-cross: #8a8a8a;
  --loop-clue: #f2f2f2;
  --loop-clue-done: #4cc38a;
  --loop-clue-bad: #ff6b6b;
  --loop-cursor: #8796f0;
  --loop-solved: #8796f0;
}

.loopline-shell {
  --game-accent: var(--g-loopline);
}
.loopline-shell .shell-stage {
  gap: var(--space-3);
  padding: 0 var(--space-4);
}
.loopline-shell .shell-board-area {
  display: flex;
  width: 100%;
  flex-direction: column;
  align-items: center;
  gap: var(--space-3);
}
/* --ratio is (columns + 0.7) / (rows + 0.7): the board keeps a margin of 0.35 cell around the outer dots. */
.loopline-board-wrap {
  width: min(calc(540px * max(1, var(--ratio))), calc(100vw - 32px), calc((100dvh - 250px) * var(--ratio)));
  margin: 0 auto;
}
.loopline-board {
  display: block;
  width: 100%;
  height: auto;
  border-radius: 12px;
  background: var(--loop-paper);
  box-shadow: inset 0 0 0 1px var(--board-grid);
  /* Drawing must not scroll or zoom the page. */
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
  -webkit-tap-highlight-color: transparent;
  cursor: pointer;
}
.loopline-board:focus-visible {
  outline: 3px solid var(--loop-cursor);
  outline-offset: 2px;
}
.loop-guide line {
  stroke: var(--loop-guide);
  stroke-width: 0.04;
}
.loop-lines line {
  stroke: var(--loop-line);
  stroke-width: 0.13;
  stroke-linecap: round;
}
.loop-crosses path {
  fill: none;
  stroke: var(--loop-cross);
  stroke-width: 0.05;
  stroke-linecap: round;
}
.loop-dots circle {
  fill: var(--loop-dot);
}
.loop-clues text {
  fill: var(--loop-clue);
  font: 700 0.56px var(--font-app);
  letter-spacing: 0;
  text-anchor: middle;
  dominant-baseline: central;
}
.loop-clues text.done {
  fill: var(--loop-clue-done);
}
.loop-clues text.bad {
  fill: var(--loop-clue-bad);
}
.loop-hint-cells rect {
  fill: var(--hint-context);
  opacity: 0.18;
}
.loop-hint-dots circle {
  fill: none;
  stroke: var(--hint-context);
  stroke-width: 0.06;
}
.loop-hint-edges line {
  stroke: var(--hint-target);
  stroke-width: 0.13;
  stroke-linecap: round;
  stroke-dasharray: 0.16 0.12;
}
.loop-hint-edges path {
  fill: none;
  stroke: var(--hint-target);
  stroke-width: 0.07;
  stroke-linecap: round;
}
.loop-hint-edges .earlier {
  stroke-dasharray: none;
  opacity: 0.45;
}
.loop-hint-edges .wrong {
  stroke: var(--danger);
  stroke-dasharray: none;
  opacity: 0.85;
}
.loop-issues circle {
  fill: none;
  stroke: var(--loop-clue-bad);
  stroke-width: 0.06;
}
.loop-cursor {
  fill: none;
  stroke: var(--loop-cursor);
  stroke-width: 0.05;
  opacity: 0;
}
.loopline-board:focus-visible .loop-cursor {
  opacity: 1;
}
.loopline-board.solved .loop-lines line,
.loopline-board.solved-static .loop-lines line {
  stroke: var(--loop-solved);
}
.loopline-board.solved .loop-lines {
  animation: loop-glow 900ms ease-out;
}
@keyframes loop-glow {
  50% {
    opacity: 0.55;
  }
}
@media (prefers-reduced-motion: reduce) {
  .loopline-board.solved .loop-lines {
    animation: none;
  }
}
.loopline-status {
  margin: 0;
  color: var(--text-muted);
  font-size: 14px;
}
.loopline-status b {
  color: var(--text);
}

/* Picture rules: the 3 × 3 demo board, drawn with the same layers, fills its stage. */
.loopline-demo-board {
  position: relative;
  width: 100%;
}
.loopline-demo-board .loopline-board {
  cursor: default;
}
