/* Santorini board, on top of terminal-theme.css.
   Towers are drawn top-down as nested squares, the way the physical building
   pieces actually stack: each level is a smaller slab sitting on the one below,
   and a dome is the disc that caps it. */

:root {
  --p0: var(--ansi-cyan);
  --p1: var(--portal-orange);
  /* Santorini's buildings are whitewashed, and the stack has to be readable at
     a glance, so the levels climb hard towards white rather than creeping up
     in near-identical grays. */
  --slab-0: hsl(220, 20%, 13%);
  --slab-1: hsl(215, 12%, 33%);
  --slab-2: hsl(210, 12%, 55%);
  --slab-3: hsl(205, 18%, 80%);
}

/* The board is a square; a page four times wider than its content just puts
   the eye a long way from the thing it is looking at. */
.screen { max-width: 44rem; }

.status-bar {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  flex-wrap: wrap;
  min-height: 2.1rem;
  margin-bottom: 1rem;
  font-size: 0.9rem;
}
.status-bar .p0-text { color: var(--p0); font-weight: 600; }
.status-bar .p1-text { color: var(--p1); font-weight: 600; }
.status-bar.won { font-weight: 600; }

.badge.p0 { color: var(--p0); border-color: var(--p0); }
.badge.p1 { color: var(--p1); border-color: var(--p1); }

/* --- The board ------------------------------------------------------------ */

/* `relative` so the win screen can sit over the board it was won on. Note it
   must stay a plain positioning context and never gain a transform or a
   backdrop-filter: either one would become the containing block for anything
   fixed inside it. */
.board-wrap { position: relative; display: flex; justify-content: center; }

.board {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 6px;
  width: min(100%, 34rem);
  aspect-ratio: 1;
  padding: 6px;
  border: 1px solid var(--window-border);
  border-radius: 10px;
  background:
    radial-gradient(circle at 50% 40%, rgba(56, 189, 248, 0.07), transparent 70%),
    var(--panel-bg);
}

/* Every cell is a button so it is reachable by keyboard and reads as tappable.
   The theme's generic button styling is not wanted here, so reset it. */
.cell {
  position: relative;
  aspect-ratio: 1;
  height: auto;
  width: 100%;
  padding: 0;
  border-radius: 6px;
  border: 1px solid rgba(148, 163, 184, 0.16);
  background: var(--slab-0);
  color: inherit;
  font-family: inherit;
  cursor: default;
  overflow: visible;
  transition: border-color 0.12s ease, box-shadow 0.12s ease;
}

/* Stacked levels. Each is inset inside the one before it, so the tower
   narrows as it climbs. */
.lvl {
  position: absolute;
  inset: 13%;
  border-radius: 4px;
  display: none;
  box-shadow: 0 3px 6px rgba(0, 0, 0, 0.7);
  border: 1px solid rgba(0, 0, 0, 0.45);
  border-top-color: rgba(255, 255, 255, 0.22);
}
.l1 { background: var(--slab-1); }
.l2 { background: var(--slab-2); }
.l3 { background: var(--slab-3); }

.cell[data-h="1"] .l1,
.cell[data-h="2"] .l1,
.cell[data-h="3"] .l1 { display: block; }
.cell[data-h="2"] .l2,
.cell[data-h="3"] .l2 { display: block; }
.cell[data-h="3"] .l3 { display: block; }

/* The dome is one physical piece, so seen from above it is the same size
   wherever it sits. Atlas caps a space at any level, which is why the dome is
   sized against the cell rather than nested inside level 3: a dome on bare
   ground shows no rings under it, a dome on a finished tower shows three. */
.dome {
  position: absolute;
  inset: 28%;
  z-index: 3;
  display: none;
  border-radius: 50%;
  background: radial-gradient(circle at 35% 30%, hsl(205, 85%, 72%), hsl(205, 75%, 42%) 65%, hsl(205, 65%, 28%));
  box-shadow: 0 0 10px rgba(56, 189, 248, 0.35), inset 0 -2px 6px rgba(0, 0, 0, 0.45);
}
.cell[data-domed="1"] .dome { display: block; }

/* Height readout, so the level is legible without counting rings. */
.hgt {
  position: absolute;
  top: 2px;
  left: 4px;
  z-index: 6;
  font-size: 0.68rem;
  font-weight: 600;
  line-height: 1;
  color: var(--terminal-fg);
  opacity: 0.8;
  text-shadow: 0 1px 3px #000;
  pointer-events: none;
}
.cell[data-h="0"] .hgt,
.cell[data-domed="1"] .hgt { display: none; }

/* --- Workers -------------------------------------------------------------- */

/* Sized to sit on top of a level-3 tower without overhanging it. */
.worker {
  position: absolute;
  inset: 28%;
  z-index: 5;
  display: none;
  border: 2px solid;
  box-shadow: 0 3px 8px rgba(0, 0, 0, 0.8);
}
.cell.has-worker .worker { display: block; }
/* Color and shape both carry the difference, so the two sides stay apart for
   anyone who does not read the colors. */
.worker.p0 {
  border-radius: 50%;
  border-color: var(--p0);
  background: radial-gradient(circle at 35% 30%, hsl(180, 80%, 70%), hsl(180, 70%, 30%));
}
.worker.p1 {
  border-radius: 4px;
  border-color: var(--p1);
  background: radial-gradient(circle at 35% 30%, hsl(32, 100%, 70%), hsl(28, 90%, 38%));
}

/* --- Interaction states --------------------------------------------------- */

/* Anything the current player can act on. Rendered state, never a hover
   state: the reader is usually holding a phone. */
.cell.actionable { cursor: pointer; }

.cell.pickable { border-color: rgba(148, 163, 184, 0.55); }
.cell.pickable .worker { animation: breathe 1.9s ease-in-out infinite; }

.cell.selected {
  border-color: var(--ansi-yellow);
  box-shadow: 0 0 0 2px rgba(255, 209, 61, 0.35), 0 0 14px rgba(255, 209, 61, 0.3);
}

/* Prompts must never be mistaken for pieces, so they are marks rather than
   tokens: a hollow ring means "your worker can stand here", a plus means
   "you can build here". A filled disc the size of a worker reads as a third
   color of worker, which is exactly the confusion to avoid. */
.cell.target::after,
.cell.buildable::after,
.cell.placeable::after {
  position: absolute;
  inset: 0;
  z-index: 4;
  display: flex;
  align-items: center;
  justify-content: center;
  pointer-events: none;
  font-weight: 700;
  line-height: 1;
}

.cell.target::after {
  content: "";
  inset: 30%;
  border-radius: 50%;
  border: 3px solid rgba(94, 234, 122, 0.85);
  background: rgba(94, 234, 122, 0.12);
  box-shadow: 0 0 12px rgba(94, 234, 122, 0.45), inset 0 0 8px rgba(94, 234, 122, 0.3);
}
.cell.buildable::after {
  content: "+";
  font-size: 1.5rem;
  color: var(--ansi-yellow);
  text-shadow: 0 0 10px rgba(255, 209, 61, 0.8), 0 2px 4px #000;
}
.cell.placeable::after {
  content: "+";
  font-size: 1.1rem;
  color: rgba(148, 163, 184, 0.5);
}
/* A move that wins on arrival gets called out rather than left to be spotted. */
.cell.target.winning::after {
  border-width: 4px;
  border-color: rgb(94, 234, 122);
  background: rgba(94, 234, 122, 0.4);
  box-shadow: 0 0 22px rgba(94, 234, 122, 0.85), inset 0 0 12px rgba(94, 234, 122, 0.6);
}

.cell.mover {
  border-color: var(--ansi-yellow);
  box-shadow: 0 0 0 2px rgba(255, 209, 61, 0.3);
}
.cell.just-built .lvl,
.cell.just-built .dome { animation: pop 0.28s ease-out; }
.cell.winner .worker {
  animation: breathe 1.1s ease-in-out infinite;
  box-shadow: 0 0 18px 4px rgba(94, 234, 122, 0.75);
}

@keyframes breathe {
  0%, 100% { transform: scale(1); }
  50% { transform: scale(1.12); }
}
@keyframes pop {
  from { transform: scale(0.55); opacity: 0.3; }
  to { transform: scale(1); opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
  .cell.pickable .worker,
  .cell.winner .worker,
  .cell.just-built .lvl,
  .cell.just-built .dome { animation: none; }
}

/* Feedback for a finger. Hover is desktop-only and never a solid fill with an
   inverted label - these targets have no label to lose, but the rule holds. */
.cell.actionable:active { filter: brightness(1.35); }
@media (hover: hover) {
  .cell.actionable:hover { border-color: rgba(148, 163, 184, 0.7); }
}

/* --- Controls, rules, log -------------------------------------------------- */

.controls {
  display: flex;
  gap: 0.5rem;
  flex-wrap: wrap;
  justify-content: center;
  margin-top: 1.1rem;
}

.rules { margin-top: 1rem; font-size: 0.82rem; }
.rules p + p { margin-top: 0.6rem; }

.log {
  max-height: 11rem;
  font-size: 0.78rem;
  line-height: 1.7;
}
.log .entry { display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.log .entry.p0 { color: var(--p0); }
.log .entry.p1 { color: var(--p1); }
.log .entry .n { color: var(--terminal-dim); margin-right: 0.5rem; }
.log .empty { color: var(--terminal-dim); }

/* --- Phone ---------------------------------------------------------------- */

@media (max-width: 640px) {
  body { padding: 0.5rem; }
  .terminal-body { padding: 1rem; }
  .board { gap: 4px; padding: 4px; }
  .status-bar { font-size: 0.82rem; margin-bottom: 0.75rem; }
  h2 { margin: 1.2rem 0 0.6rem; }
  .log { max-height: 8rem; }
}

/* --- Choosing cards -------------------------------------------------------- */

/* Two questions on this screen now — who you are playing, and with what — so
   they get headings. Without them the opponent switch reads as a third row of
   god-card controls. */
.setup-head {
  margin: 1.1rem 0 0.5rem;
  font-size: 0.72rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--terminal-dim);
}
/* Scoped to a direct child: the record section has a heading of its own, and
   an unqualified :first-of-type matches that one too — inside its own section
   it is also a first-of-type — which would tighten a heading that is in the
   middle of the screen rather than at the top of it. */
#setup > .setup-head:first-of-type { margin-top: 0.4rem; }

/* Four choices do not fit across a phone in one row. Wrapping them leaves
   [hard] alone on a second line, so on a narrow screen they become a 2x2 grid
   instead — even blocks, bigger tap targets, and each keeps its own corners
   since a wrapped segmented row would put the rounded ends in the middle.

   Qualified `.seg.opponent`, not `.opponent`: the shared `.seg` rule further
   down this file sets `display: inline-flex` and ties on specificity, so the
   later declaration wins and a bare `.opponent { display: grid }` silently
   does nothing at all. */
.seg.opponent { margin-bottom: 0.4rem; }
@media (max-width: 560px) {
  .seg.opponent {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 0.4rem;
  }
  .seg.opponent .seg-btn { border-radius: 4px; }
}

/* The two picks, always on screen while choosing, so it is never a mystery
   which player a tap is choosing for. */
.slots {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.6rem;
  margin-bottom: 1rem;
}
.slot {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.15rem;
  height: auto;
  padding: 0.6rem 0.8rem;
  text-align: left;
  border-radius: 6px;
  background: rgba(148, 163, 184, 0.05);
  border: 1px solid var(--window-border);
}
.slot .slot-who { font-size: 0.72rem; color: var(--terminal-dim); }
.slot .slot-god { font-size: 0.95rem; font-weight: 600; }
.slot.p0 .slot-god { color: var(--p0); }
.slot.p1 .slot-god { color: var(--p1); }
.slot.p0.active { border-color: var(--p0); box-shadow: 0 0 0 1px var(--p0); }
.slot.p1.active { border-color: var(--p1); box-shadow: 0 0 0 1px var(--p1); }
/* The seat the computer is taking, called out before the game starts rather
   than discovered when the board will not answer a tap. Player 2's own color,
   not a new one: it is still Player 2's seat, just nobody is sitting in it. */
.slot.robot .slot-who { color: var(--p1); font-weight: 600; }

.card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(13rem, 1fr));
  gap: 0.6rem;
}

/* Each card carries its whole rule. A player picking Hephaestus for the first
   time should not have to go and look up what he does. */
.god-card {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.2rem;
  height: auto;
  padding: 0.7rem 0.8rem;
  text-align: left;
  white-space: normal;
  border-radius: 6px;
  border: 1px solid var(--window-border);
  background: rgba(148, 163, 184, 0.04);
}
.god-card-name { font-size: 0.95rem; font-weight: 700; color: var(--terminal-fg); }
.god-card-tag { font-size: 0.75rem; color: var(--ansi-yellow); }
.god-card-when { font-size: 0.68rem; color: var(--terminal-dim); text-transform: lowercase; }
.god-card-text { margin-top: 0.25rem; font-size: 0.74rem; line-height: 1.55; color: var(--terminal-dim); }
.god-card.taken-0 { border-color: var(--p0); background: rgba(56, 189, 248, 0.08); }
.god-card.taken-1 { border-color: var(--p1); background: rgba(255, 145, 40, 0.08); }
.god-card.taken-0 .god-card-name { color: var(--p0); }
.god-card.taken-1 .god-card-name { color: var(--p1); }
/* Taken by the other player: still readable, plainly not yours to take. */
.god-card:disabled { opacity: 0.45; cursor: not-allowed; }

/* --- The cards in play ----------------------------------------------------- */

.gods-banner {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.5rem;
  margin-bottom: 0.8rem;
}
.god-chip {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.1rem;
  height: auto;
  padding: 0.45rem 0.7rem;
  text-align: left;
  border-radius: 6px;
  border: 1px solid var(--window-border);
  background: rgba(148, 163, 184, 0.04);
}
.chip-who { font-size: 0.68rem; color: var(--terminal-dim); }
.chip-god { font-size: 0.88rem; font-weight: 700; }
.chip-tag { font-size: 0.7rem; color: var(--terminal-dim); }
.god-chip.p0 .chip-god { color: var(--p0); }
.god-chip.p1 .chip-god { color: var(--p1); }
/* Whose turn it is, said a second time next to what they can do about it. */
.god-chip.p0.acting { border-color: var(--p0); background: rgba(56, 189, 248, 0.1); }
.god-chip.p1.acting { border-color: var(--p1); background: rgba(255, 145, 40, 0.1); }
.god-chip.acting .chip-tag { color: var(--ansi-yellow); }

.god-detail { margin-bottom: 0.8rem; font-size: 0.8rem; }
.god-detail p { margin-top: 0.35rem; line-height: 1.6; color: var(--terminal-dim); }

.status-bar .warn { color: var(--ansi-yellow); }

/* --- The computer's turn ---------------------------------------------------- */

/* Nothing is tappable while the computer holds the turn, and the board says so
   rather than sitting there looking live and ignoring taps. */
.board.waiting { opacity: 0.72; cursor: progress; }
.board.waiting .cell { cursor: progress; }

/* Three dots that run, so a think that takes a moment reads as working rather
   than as stuck. */
.think-dots i { font-style: normal; opacity: 0.25; animation: think 1.2s infinite; }
.think-dots i:nth-child(2) { animation-delay: 0.2s; }
.think-dots i:nth-child(3) { animation-delay: 0.4s; }
@keyframes think {
  0%, 60%, 100% { opacity: 0.25; }
  30% { opacity: 1; }
}
/* Somebody who has asked for less motion gets three steady dots instead. */
@media (prefers-reduced-motion: reduce) {
  .think-dots i { animation: none; opacity: 0.6; }
}

/* --- Build-a-dome switch (Atlas) ------------------------------------------- */

.seg { display: inline-flex; }
.seg .seg-btn {
  color: var(--terminal-dim);
  background: rgba(148, 163, 184, 0.06);
  border-radius: 0;
}
.seg .seg-btn:first-child { border-radius: 4px 0 0 4px; }
.seg .seg-btn:last-child { border-radius: 0 4px 4px 0; }
.seg .seg-btn.on {
  color: var(--ansi-blue);
  background: rgba(56, 189, 248, 0.14);
  border-color: var(--ansi-blue);
}
/* With the switch on dome, the build prompt has to say so — otherwise the tap
   that seals a space for good looks exactly like the tap that raises it. */
.board.dome-mode .cell.buildable::after {
  content: "";
  inset: 30%;
  border-radius: 50%;
  border: 3px solid hsl(205, 85%, 62%);
  background: rgba(56, 189, 248, 0.18);
  box-shadow: 0 0 12px rgba(56, 189, 248, 0.55);
}

/* --- The worker slide ------------------------------------------------------ */

/* A piece being carried to its new square stops breathing for the trip: the
   `breathe` keyframes animate `transform` too, and a running animation beats
   an inline style, so without this the slide simply would not draw. */
.worker.sliding { animation: none !important; z-index: 7; }

/* --- The win screen -------------------------------------------------------- */

.win-screen {
  position: absolute;
  inset: 0;
  z-index: 20;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1rem;
  /* Dark enough to read against, sheer enough to see the final position
     through — the board is most of why the result is interesting. */
  background: rgba(10, 14, 20, 0.72);
  border-radius: 10px;
  animation: win-in 0.25s ease-out;
}
.win-card {
  width: min(100%, 24rem);
  padding: 1.1rem 1.2rem 1.2rem;
  text-align: center;
  border: 1px solid var(--window-border);
  border-radius: 10px;
  /* Solid, and deliberately NOT var(--panel-bg): the theme's panel is 30%
     black, which is right for a panel sitting on the page background and quite
     wrong here — the board showed through the card and the grid lines ran
     straight across the winner's name. */
  background: #0f141c;
  box-shadow: 0 18px 44px rgba(0, 0, 0, 0.6);
}
.win-who {
  margin: 0.7rem 0 0.35rem;
  font-size: 1.35rem;
  letter-spacing: 0.01em;
}
.win-who.p0-text { color: var(--p0); }
.win-who.p1-text { color: var(--p1); }
.win-why { margin: 0; font-size: 0.9rem; }
.win-meta {
  margin: 0.5rem 0 0;
  font-size: 0.74rem;
  color: var(--terminal-dim);
}
.win-actions {
  display: flex;
  gap: 0.45rem;
  flex-wrap: wrap;
  justify-content: center;
  margin-top: 1rem;
}

@keyframes win-in {
  from { opacity: 0; }
  to { opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
  .win-screen { animation: none; }
}

/* --- The record ------------------------------------------------------------ */

.setup-head .btn.tiny {
  margin-left: 0.5rem;
  padding: 0.1rem 0.4rem;
  font-size: 0.65rem;
  vertical-align: middle;
}

.record { font-size: 0.78rem; }
.rec-line {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem 1.1rem;
}
.rec-cell { display: inline-flex; align-items: baseline; gap: 0.35rem; }
.rec-label {
  font-size: 0.66rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--terminal-dim);
}
.rec-score { font-weight: 600; }

.rec-list { margin-top: 0.7rem; }
/* Each finished game on one line: when, who won, and the detail. On a phone
   the detail wraps under the first two rather than being cut off. */
.rec-row {
  display: grid;
  grid-template-columns: 4.6rem auto 1fr;
  gap: 0.1rem 0.5rem;
  padding: 0.2rem 0;
  line-height: 1.5;
  border-top: 1px solid rgba(148, 163, 184, 0.1);
}
.rec-row:first-child { border-top: 0; }
.rec-when { color: var(--terminal-dim); }
.rec-what { font-weight: 600; }
.rec-what.p0-text { color: var(--p0); }
.rec-what.p1-text { color: var(--p1); }
.rec-detail {
  color: var(--terminal-dim);
  overflow: hidden;
  text-overflow: ellipsis;
}
@media (max-width: 560px) {
  .rec-row { grid-template-columns: 4.6rem 1fr; }
  .rec-detail { grid-column: 1 / -1; font-size: 0.72rem; }
}

/* --- Phone ----------------------------------------------------------------- */

@media (max-width: 640px) {
  .card-grid { grid-template-columns: 1fr; gap: 0.5rem; }
  .god-card { padding: 0.6rem 0.7rem; }
  .gods-banner { gap: 0.4rem; }
  .god-chip { padding: 0.4rem 0.55rem; }
  .chip-god { font-size: 0.8rem; }
  .chip-tag { font-size: 0.65rem; }
}

/* A control that cannot be used must not look like one that can - [start game]
   with only one card chosen is the case this exists for. */
.btn:disabled,
button:disabled {
  opacity: 0.4;
  cursor: not-allowed;
  color: var(--terminal-dim);
  border-color: var(--window-border);
  background: rgba(148, 163, 184, 0.04);
}
