/* ── Bonds ────────────────────────────────────────────────────────────────
   A drafted valence diagram on blueprint stock, and it follows the theme (the
   note that used to sit here claiming otherwise was never true of this game).
   Atoms are dials — the ring is the bond count, so the ring and the number say
   the same thing. Bonds are square-capped rods that butt flat into the ball. A
   satisfied atom floods from its centre; an over-bonded one floods warm. It
   borrows the shared puzzle chrome (q-chrome / q-stage / q-foot). Tokens only. */

.bonds-play {
  display: flex;
  flex-direction: column;
  height: 100%;
  min-height: 0;
}

/* ── the board ────────────────────────────────────────────────────────── */

/* Bleed: no frame, no padding, no paper card — the diagram sits straight on the
   app background, so the board has no edge and the lattice runs to the margin. */
.bo-board {
  width: min(92vw, 66vh, 520px);
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
}
.bo-svg { display: block; width: 100%; height: auto; }

/* the faint guide grid: lines through every atom, so each sits on an
   intersection and a bare crossing reads as somewhere a bond could go */
.bo-grid { stroke: var(--bo-frame); stroke-width: 1.5; opacity: 0.35; pointer-events: none; }

/* bonds — rods, not drawn lines: heavier, and square-capped so they butt flat
   into the ball instead of tucking a rounded nose under it */
.bo-bond {
  stroke: var(--bo-ink);
  stroke-width: 10;
  stroke-linecap: butt;
}
.bo-hit {
  stroke: transparent;
  stroke-width: 46;
  stroke-linecap: butt;
  cursor: pointer;
}

/* ── atoms ──────────────────────────────────────────────────────────────────
   Four stacked circles and a numeral, bottom to top: the body, the flood, the
   dial's track, the dial's arc.

   Both animations here depend on src/ui/bonds.js keeping these elements ALIVE
   across a move — repaint() rebuilds the bonds but syncs the atoms in place.
   Replace the atoms and both transitions have no previous state to run from,
   and you get the snap this replaced. */
.bo-atom { cursor: pointer; }
.bo-atom .bo-disc { fill: var(--bo-atom); stroke: none; }

/* The flood: a disc grown from the centre rather than a fill that switches on.
   transform-box: fill-box puts the origin at the circle's own middle — without
   it the scale would happen about the SVG's origin and it would fly in from the
   corner. */
.bo-atom .bo-fill {
  fill: var(--bo-sat);
  pointer-events: none;
  transform: scale(0);
  transform-box: fill-box;
  transform-origin: center;
  transition: transform var(--duration-2) var(--ease), fill var(--t);
}
.bo-atom.sat .bo-fill { transform: scale(1); }
.bo-atom.over .bo-fill { fill: var(--bo-over); transform: scale(1); }

/* The dial: a faint full track, and a bright arc dashed to deg/n. The arc eases
   between counts because bonds.js only rewrites its dasharray — the element
   itself survives the move. */
.bo-atom .bo-dial-track {
  fill: none;
  stroke: var(--bo-frame);
  stroke-width: 5;
  pointer-events: none;
}
.bo-atom .bo-dial-arc {
  fill: none;
  stroke: var(--bo-ink);
  stroke-width: 5;
  stroke-linecap: round;
  pointer-events: none;
  transition: stroke-dasharray var(--duration-2) var(--ease), stroke var(--t);
}
/* at full count the arc closes the ring and merges into the flood, so a done
   atom reads as one solid disc rather than a disc wearing a stripe */
.bo-atom.sat .bo-dial-arc { stroke: var(--bo-sat); }
.bo-atom.over .bo-dial-arc { stroke: var(--bo-over); }
.bo-atom text {
  fill: var(--bo-ink);
  font-family: var(--font-mono);
  font-size: 46px;
  font-weight: 500;
  text-anchor: middle;
  pointer-events: none;
  transition: fill var(--t);
}
/* the numeral knocks out of the flood — the atom is the colour now, so the
   number has to be the hole in it rather than more of the same */
.bo-atom.sat text,
.bo-atom.over text { fill: var(--bo-paper); }

/* the hint pulse on an atom */
.bo-atom.hinted .bo-dial-track { animation: bo-hint 1.4s var(--ease) 2; }
@keyframes bo-hint {
  0%, 100% { stroke: var(--bo-ink); }
  50% { stroke: var(--accent); stroke-width: 8; }
}

/* the red "no bond that way" flash */
.bo-nope {
  stroke: var(--bo-over);
  stroke-width: 6;
  stroke-linecap: round;
  animation: bo-nope 0.5s var(--ease) forwards;
}
@keyframes bo-nope {
  0% { opacity: 0.9; }
  100% { opacity: 0; }
}

/* ── bond flow ────────────────────────────────────────────────────────────
   A new bond draws out from the atom you pulled from to its neighbour; a second
   bond first nudges the first aside (bo-slide) then draws in; a removed bond
   recedes in red. All three ride the dash-draw trick: a line of dash length =
   its own length, its offset run from ±len (hidden) to 0 (whole) or back. The
   sign of --bo-df picks which end draws first, set inline per line from JS. */
@keyframes bo-grow    { from { stroke-dashoffset: var(--bo-df, 0); } to { stroke-dashoffset: 0; } }
@keyframes bo-retract { from { stroke-dashoffset: 0; } to { stroke-dashoffset: var(--bo-df, 0); } }
@keyframes bo-slide   { from { transform: translate(var(--bo-tx, 0), var(--bo-ty, 0)); } to { transform: translate(0, 0); } }
.bo-retract { stroke: var(--bo-over); }

/* ── landscape phone: board left, controls to the sides ───────────────── */
@media (orientation: landscape) and (max-height: 700px) {
  .bonds-play .bo-board { width: min(88vh, 78vw); }
}

/* ── the thumbnail on a journey level card ────────────────────────────── */
.bo-mini {
  width: 100%;
  padding: var(--space-2);
  background: var(--bo-paper);
  outline: 1.5px solid var(--bo-frame);
  border-radius: var(--radius-sm);
}
.bo-mini .bo-svg { width: 100%; }
.bo-mini .bo-atom text { font-size: 40px; }
/* a solved level's thumbnail greens its bonds, the player's own answer */
.bo-mini.done .bo-bond { stroke: var(--bo-sat); }
