/* ═══════════════════════════════════════════════════════════════════════════
   Battle AIrena — Shared Base CSS
   Structural layout, unified sizing, neutral defaults.
   No font-family declarations — themes set fonts.
   No decorative effects (glow, text-shadow, decorative ::before/::after).
   ═══════════════════════════════════════════════════════════════════════════ */

@layer defaults, theme, responsive, user;

@layer defaults {

/* ── Neutral Defaults ── */
:root {
  --bg:       #1a1a2e;
  --panel:    #24243e;
  --border:   #3a3a5a;
  --accent1:  #4a9eff;
  --accent2:  #ff8a50;
  --success:    #4ade80;
  --error:      #f87171;
  --warning:   #fbbf24;
  --text:     #e0e0e0;
  --dim:      #8888aa;
  --glow:     none;
  --glow2:    none;
  /* Damage primitive — themes may override */
  --damage:   #f87171;
  /* Semantic status tokens (element layer binds to these, not to primitives) */
  --status-hit-color:  var(--damage);
  --status-sunk-color: var(--damage);
  --status-miss-color: var(--dim);
  /* Semantic play-order tokens (T66 D68). Element rules reference these,
     never --accent1/--accent2 directly, for any role-colored surface. */
  --play-order-first-color:  var(--accent1);
  --play-order-second-color: var(--accent2);
  /* Mode colours */
  --mode-practice:   #5ab87a;
  --mode-ranked:     #d4a030;
  --mode-tournament: #c9a830;
  /* Severity tokens (notify widget + any future message surfaces).
     Themes inherit via the primitive bindings below. */
  --severity-info:      var(--dim);
  --severity-important: var(--warning);
  --severity-error:     var(--error);
  /* Board sizing (T66 G2a). JS may rewrite --cell-size via fitCellSize
     and --board-w / --board-h when board dimensions change. */
  --cell-size: 24px;
  --board-w:   10;
  --board-h:   10;
}

/* ── Reset ── */
* { margin: 0; padding: 0; box-sizing: border-box; }
[hidden] { display: none !important; }

/* ── Body ── */
body {
  background: var(--bg);
  color: var(--text);
  font-size: 12px;
  min-height: 100vh;
  overflow-x: hidden;
}

.everything { position: relative; z-index: 2; }

/* ── Header ── */
header {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 8px 16px;
  padding: 12px 24px;
  border-bottom: 1px solid var(--border);
}

.logo {
  font-size: 20px;
  font-weight: 900;
  letter-spacing: 3px;
  color: var(--accent1);
}

.logo span { color: var(--accent2); }

.header-left {
  display: flex;
  align-items: baseline;
  gap: 12px;
}

.header-right {
  display: flex;
  align-items: center;
  gap: 16px;
}

/* ── Connection Badge ── */
.connection-badge {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  letter-spacing: 2px;
  color: var(--dim);
}

.connection-badge.connected { color: var(--success); }
.connection-badge.error { color: var(--error); }

.conn-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--dim);
  transition: all 0.3s;
}

.connection-badge.connected .conn-dot {
  background: var(--success);
  animation: pulse 1.4s ease-in-out infinite;
}

.connection-badge.error .conn-dot {
  background: var(--error);
}

@keyframes pulse {
  0%, 100% { opacity: 1; transform: scale(1); }
  50%      { opacity: 0.5; transform: scale(0.7); }
}

/* ── Version Label ── */
.version-label {
  font-size: 11px;
  color: var(--dim);
  letter-spacing: 1px;
}

/* ── Buttons ── */
.btn {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 2px;
  padding: 6px 14px;
  border: 1px solid;
  border-radius: 2px;
  cursor: pointer;
  transition: all 0.2s;
  text-transform: uppercase;
  background: transparent;
}

.btn-accent { color: var(--accent1); border-color: var(--accent1); }
.btn-accent:hover { background: rgba(74,158,255,0.15); }

.btn-green { color: var(--success); border-color: var(--success); }
.btn-green:hover { background: rgba(74,222,128,0.15); }

.btn-red { color: var(--error); border-color: var(--error); }
.btn-red:hover { background: rgba(248,113,113,0.15); }

.btn-orange { color: var(--accent2); border-color: var(--accent2); }
.btn-orange:hover { background: rgba(255,138,80,0.15); }

.btn-dim { color: var(--dim); border-color: var(--dim); }
.btn-dim:hover { color: var(--text); border-color: var(--text); }

.btn-sm { font-size: 10px; padding: 4px 10px; letter-spacing: 1px; }

.btn:disabled { opacity: 0.4; cursor: not-allowed; }

/* ── Loading indicator ──
   Element-level modifier. Consumers add `.is-loading` to disable interaction
   and (on buttons) render a small rotating spinner inline after the label.
   Theme-overridable via --loading-spinner-color. */
:root {
  --loading-spinner-color: var(--accent1);
}
.is-loading {
  pointer-events: none;
  position: relative;
}
.btn.is-loading {
  padding-right: 28px;
}
.btn.is-loading::after {
  content: "";
  position: absolute;
  top: calc(50% - 6px);
  right: 10px;
  width: 12px;
  height: 12px;
  box-sizing: border-box;
  border: 1.5px solid transparent;
  border-top-color: var(--loading-spinner-color);
  border-right-color: var(--loading-spinner-color);
  border-radius: 50%;
  animation: is-loading-spin 0.7s linear infinite;
}
@keyframes is-loading-spin {
  to { transform: rotate(360deg); }
}

/* ── Panels ── */
.panel {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 2px;
  overflow: hidden;
  position: relative;
  display: flex;
  flex-direction: column;
}

.panel-title {
  font-size: 12px;
  letter-spacing: 3px;
  color: var(--accent1);
  padding: 8px 14px;
  border-bottom: 1px solid var(--border);
  display: flex;
  align-items: center;
  gap: 8px;
  flex-shrink: 0;
}

.panel-body {
  padding: 10px 14px;
  overflow-y: auto;
  flex: 1;
  min-height: 0;
}

.panel-placeholder {
  color: var(--dim);
  font-size: 14px;
  letter-spacing: 1px;
  text-align: center;
  padding: 24px 0;
}

/* ── Game Board (24px unified) ── */
/* Default arrangement H-below: vertical stack (label, board, fleet).
   Other arrangements override below via theme / user preference /
   responsive container-query. See T66 G3c. */
.board-wrapper {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
}

/* ── Game-panel board arrangements (T66 G3c) ───────────────────────────
   Three arrangements:
     H-below — side-by-side boards, fleets below each (default).
     H-outer — side-by-side boards, fleets on opposite outer sides.
     V       — stacked boards, fleets on same side. Responsive.

   Cascade order (later wins on specificity tie):
     1. Default H-below (.board-wrapper flex-column, above).
     2. Theme preference — body.theme-retro → H-outer.
     3. User preference — body[data-game-arrangement=...] overrides theme.
     4. Responsive V — @container (max-width: 720px) overrides all.

   Arrangement rules key on DOM position (:first-child / :last-child of
   .game-inner) — positional, not semantic. data-play-order would be
   wrong here because play dashboard perspective-flips "my team" to the
   left regardless of who moves first. */

/* 2. Theme defaults — none. Both themes inherit H-below by default.
   Retro H-outer considered but dropped in G3c: the fleet-beside budget
   squeezes boards and legends too small to read comfortably. User can
   still opt in via data-game-arrangement="H-outer" on <body>. */

/* 3a. User forces H-below regardless of theme */
body[data-game-arrangement="H-below"] .game-inner > .board-wrapper {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  grid-template-areas: none;
}

/* 3b. User forces H-outer regardless of theme */
body[data-game-arrangement="H-outer"] .game-inner > .board-wrapper {
  display: grid;
  grid-template-columns: auto auto;
  grid-template-rows: auto 1fr;
  gap: 4px 8px;
  align-items: start;
}
body[data-game-arrangement="H-outer"] .game-inner > .board-wrapper:first-child {
  grid-template-areas: ". label" "fleet board";
}
body[data-game-arrangement="H-outer"] .game-inner > .board-wrapper:last-child {
  grid-template-areas: "label ." "board fleet";
}
body[data-game-arrangement="H-outer"] .game-inner > .board-wrapper > .board-label  { grid-area: label; text-align: center; }
body[data-game-arrangement="H-outer"] .game-inner > .board-wrapper > .board        { grid-area: board; }
body[data-game-arrangement="H-outer"] .game-inner > .board-wrapper > .ships-status { grid-area: fleet; }

/* 4. Responsive V — very narrow .game-panel → stack boards, fleets same
   side (fleet-right on both). Threshold 480px: below this, even at 14px
   cells two side-by-side 10×10 boards + chrome + divider don't fit. */
@container (max-width: 480px) {
  body .game-panel .game-inner {
    flex-direction: column;
    align-items: center;
  }
  body .game-panel .game-inner > .board-wrapper {
    display: grid;
    grid-template-columns: auto auto;
    grid-template-rows: auto 1fr;
    gap: 4px 8px;
    align-items: start;
    grid-template-areas: "label ." "board fleet";
  }
  body .game-panel .board-wrapper .board-label  { grid-area: label; text-align: center; }
  body .game-panel .board-wrapper .board        { grid-area: board; }
  body .game-panel .board-wrapper .ships-status { grid-area: fleet; }
  body .game-panel .vs-divider { flex-direction: row; }
}

.board-label {
  font-size: 14px;
  font-weight: 700;
  letter-spacing: 2px;
  color: var(--dim);
  transition: all 0.3s;
}

.board-label[data-play-order="first"]  { color: var(--play-order-first-color); }
.board-label[data-play-order="second"] { color: var(--play-order-second-color); }

/* Per-game first-mover marker (D67). `.plays-first` toggles per game;
   positional data-play-order stays match-locked. System-stack font ensures
   the ▸ glyph renders across themes (Patrick Hand lacks it). */
/* Reserved space for ▸ on both labels so the marker's size never
   changes label box height/width — otherwise the two boards misalign
   when only one label carries .plays-first. */
.board-label { position: relative; padding-left: 1.4em; padding-right: 1.4em; }
.board-label.plays-first::before {
  content: "\25B8";
  position: absolute;
  left: 0;
  top: 50%;
  transform: translateY(-50%);
  font-family: system-ui, -apple-system, sans-serif;
  font-size: 18px;
  font-weight: 900;
  line-height: 1;
}

.board {
  display: grid;
  grid-template-columns: repeat(var(--board-w), var(--cell-size));
  grid-template-rows: repeat(var(--board-h), var(--cell-size));
  gap: 1px;
  border: 1px solid var(--border);
  padding: 3px;
  background: rgba(0,0,0,0.3);
  position: relative;
}

/* SVG overlay drawn on top of the cell grid; pointer-events:none so it
   doesn't block hover/click. Straight-line perimeters for now (plan Q2);
   stroke weight distinguishes sunk (bold red) from own-unhit (thin,
   F2d). */
.board-svg-overlay {
  position: absolute;
  inset: 0;
  pointer-events: none;
  overflow: visible;
}

.board-svg-overlay .ship-perim-sunk {
  fill: none;
  stroke: var(--status-sunk-color);
  stroke-width: 1;
}

/* Thin theme-neutral perimeter around own unhit ships (play dashboard only,
   F2d / D57). Re-rendered on each sunk event so sunk ships drop out. */
/* Own-unhit perimeter: grid-neutral colour so it reads consistently
   regardless of team-colour contrast (placeholder white teams, etc.).
   Per-ship rects already produce visible seams at the 1px CELL_GAP
   between adjacent ships. */
.board-svg-overlay .ship-perim-own-unhit {
  fill: none;
  stroke: var(--dim);
  stroke-width: 3;
}

.cell {
  width: var(--cell-size);
  height: var(--cell-size);
  background: rgba(74,158,255,0.03);
  border: 1px solid rgba(74,158,255,0.06);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 10px;
  transition: all 0.3s ease;
  position: relative;
}

/* Cell rendering — keyed off semantic data-* axes (D68).
   data-occupant: empty | ship   (what's in the cell)
   data-state:    untouched | shot | sunk   (what has happened to it)
   Own-ship unhit visibility is handled per-view at render time (play
   dashboard emits occupant=ship on own-board placement events; observer
   views never do). */
.cell[data-occupant="ship"][data-state="untouched"] {
  background: rgba(74,158,255,0.12);
  border-color: rgba(74,158,255,0.25);
}
/* Own-board unhit ships (play dashboard): muted team-color fill (D66 / F2d).
   When --team-color is not set the base neutral fill above remains. */
.board[data-board-owner="self"] .cell[data-occupant="ship"][data-state="untouched"] {
  background: color-mix(in srgb, var(--team-color, transparent) 28%, transparent);
  border-color: color-mix(in srgb, var(--team-color, rgba(74,158,255,0.25)) 50%, transparent);
}
.cell[data-state="shot"] {
  background: rgba(255,138,80,0.3);
  border-color: var(--status-hit-color);
}
.cell[data-state="shot"]::after {
  content: '\2715';
  color: var(--status-hit-color);
  font-size: 12px;
}
.cell[data-occupant="empty"][data-state="shot"] {
  background: rgba(0,0,0,0.4);
  border-color: rgba(74,158,255,0.06);
}
.cell[data-occupant="empty"][data-state="shot"]::after {
  content: '\00B7';
  color: var(--status-miss-color);
  font-size: 18px;
}
.cell[data-state="sunk"] {
  background: rgba(248,113,113,0.3);
  border-color: var(--status-sunk-color);
}
.cell[data-state="sunk"]::after {
  content: '\2715';
  color: var(--status-sunk-color);
  font-size: 12px;
}

/* ── Fleet Status (half-cell grid per Design v3.0 §5.2 / v2.0 §5.2) ──
   Each row is one half-cell tall; each segment is one half-cell wide with
   an orthogonal (narrower-than-square) visual bar. Label occupies K
   half-cells (K=1 cyber, K=2 retro — theme-retro overrides
   --fleet-label-cells). Sized off --cell-size so fleet scales with board. */
.ships-status {
  --half-cell: calc(var(--cell-size, 24px) / 2);
  --fleet-label-cells: 2;
  display: flex;
  flex-direction: column;
  margin-top: 6px;
  max-width: 100%;
}

.ship-row {
  display: flex;
  align-items: center;
  gap: 0;
  height: var(--half-cell);
  transition: opacity 0.3s;
}

.ship-row.sunk { opacity: 0.5; }
.ship-row.sunk .ship-label { text-decoration: line-through; color: var(--status-sunk-color); }

.ship-label {
  width: calc(var(--fleet-label-cells) * var(--half-cell));
  font-size: calc(var(--half-cell) * 0.9);
  line-height: 1;
  letter-spacing: 0;
  color: var(--dim);
  text-align: right;
  padding-right: 2px;
  overflow: hidden;
  white-space: nowrap;
  box-sizing: border-box;
}

.ship-segments { display: flex; gap: 0; }

.ship-seg {
  width: var(--half-cell);
  height: calc(var(--half-cell) * 0.55);
  border: 1px solid var(--border);
  box-sizing: border-box;
  transition: all 0.3s ease;
  display: inline-block;
}

.ship-seg.intact { background: rgba(74,158,255,0.15); border-color: rgba(74,158,255,0.3); }
.ship-seg.hit    { background: rgba(255,138,80,0.5);             border-color: var(--status-hit-color); }
.ship-seg.sunk   { background: color-mix(in srgb, var(--status-sunk-color) 50%, transparent); border-color: var(--status-sunk-color); }

/* ── Board Legend ── */
.board-legend {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  gap: 16px;
  padding: 6px 0;
  font-size: 12px;
  letter-spacing: 1px;
  color: var(--dim);
}

.legend-item { display: flex; align-items: center; gap: 5px; }

/* Legend swatches reuse .cell data-attribute styling for single-source rendering.
   Size override pulls the 24px board cell down to a compact 14px legend swatch. */
.cell.legend-cell {
  width: 14px;
  height: 14px;
  cursor: default;
}
.cell.legend-cell::after { font-size: 10px; line-height: 14px; }

/* Own-ship swatch: no --team-color context in the legend, so use a neutral
   accent to hint the muted team-color fill used on the own board. */
.legend-cell.legend-own-ship {
  background: color-mix(in srgb, var(--accent1) 28%, transparent);
  border-color: color-mix(in srgb, var(--accent1) 50%, transparent);
}

.legend-first-mover {
  display: inline-block;
  min-width: 14px;
  text-align: center;
  color: var(--play-order-first-color, var(--accent1));
  font-weight: bold;
  /* System stack — Patrick Hand (retro) lacks the ▸ glyph. */
  font-family: system-ui, -apple-system, sans-serif;
}

.legend-sep { color: var(--border); }

/* ── Score Display ── */
.vs-divider {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 6px;
}

.match-score-header {
  font-size: 12px;
  letter-spacing: 2px;
  color: var(--dim);
}

.score-display {
  display: flex;
  align-items: center;
}

.score-num {
  font-size: 24px;
  font-weight: 700;
  line-height: 1;
}

.score-num[data-play-order="first"]  { color: var(--play-order-first-color); }
.score-num[data-play-order="second"] { color: var(--play-order-second-color); }

.score-divider { color: var(--dim); }

.vs-text {
  font-size: 14px;
  color: var(--dim);
}

/* ── Game Area ── */
.game-inner {
  display: flex;
  gap: 16px;
  align-items: flex-start;
  justify-content: center;
}

.game-info {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
}

.info-item {
  font-size: 12px;
  color: var(--dim);
  letter-spacing: 1px;
}

/* ── Move Log ── */
.log-inner {
  overflow-y: auto;
}

.log-inner::-webkit-scrollbar { width: 4px; }
.log-inner::-webkit-scrollbar-track { background: transparent; }
.log-inner::-webkit-scrollbar-thumb { background: var(--border); }

.log-entry {
  display: flex;
  gap: 8px;
  align-items: baseline;
  padding: 2px 0;
  border-bottom: 1px solid rgba(255,255,255,0.03);
  animation: fadeIn 0.3s ease;
}

@keyframes fadeIn {
  from { opacity: 0; }
  to   { opacity: 1; }
}

.log-turn   { color: var(--dim); font-size: 12px; min-width: 36px; }
.log-team   { font-size: 13px; min-width: 100px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.log-team[data-play-order="first"]  { color: var(--play-order-first-color); }
.log-team[data-play-order="second"] { color: var(--play-order-second-color); }
.log-team.system { color: var(--warning); }
.log-move   { color: var(--text); font-size: 13px; min-width: 30px; }
.log-result { font-size: 12px; letter-spacing: 1px; }
.log-result.hit    { color: var(--accent2); }
.log-result.miss   { color: var(--dim); }
.log-result.sunk   { color: var(--error); font-weight: bold; }
.log-result.system { color: var(--warning); }

/* ── Mode Badges ── */
.badge-mode {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 1px;
  padding: 1px 4px;
  border-radius: 2px;
}

.badge-mode-practice {
  color: var(--mode-practice);
  background: rgba(90,184,122,0.15);
  border: 1px solid rgba(90,184,122,0.3);
}

.badge-mode-ranked {
  color: var(--mode-ranked);
  background: rgba(212,160,48,0.15);
  border: 1px solid rgba(212,160,48,0.3);
}

.badge-mode-tournament {
  color: var(--mode-tournament);
  background: rgba(201,168,48,0.15);
  border: 1px solid rgba(201,168,48,0.3);
}

/* ── Theme Toggle ── */
.theme-toggle-btn {
  background: none;
  border: 1px solid var(--dim);
  color: var(--dim);
  padding: 3px 10px;
  cursor: pointer;
  font-family: inherit;
  font-size: inherit;
  letter-spacing: 1px;
  border-radius: 2px;
  transition: all 0.2s;
}

.theme-toggle-btn:hover {
  color: var(--accent1);
  border-color: var(--accent1);
}

}


