File size: 4,475 Bytes
e4d7d50
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
/**
 * ChessBoard component — live chess board with piece animations
 * Design: Quantitative Finance Dark — cream/brown squares, high-contrast pieces
 *
 * White pieces: bright white (#FFFFFF) with thick dark stroke — visible on ALL squares
 * Black pieces: vivid gold (#FFD700) with dark shadow — visible on ALL squares
 * Layout: fully self-contained, no overflow, stable position
 */
import { PIECES, type GameState } from "@/lib/simulation";

interface ChessBoardProps {
  state: GameState;
}

const LIGHT_SQ = "#F0D9B5";
const DARK_SQ  = "#B58863";
const FILES = ["a","b","c","d","e","f","g","h"];
const RANKS = ["8","7","6","5","4","3","2","1"];

export default function ChessBoard({ state }: ChessBoardProps) {
  return (
    <div style={{ width: "100%", height: "100%", display: "flex", flexDirection: "column" }}>
      {/* Board + rank labels row */}
      <div style={{ flex: 1, display: "flex", minHeight: 0 }}>
        {/* Rank labels */}
        <div style={{ display: "flex", flexDirection: "column", justifyContent: "space-around", width: "14px", flexShrink: 0, paddingBottom: "14px" }}>
          {RANKS.map((r) => (
            <span key={r} style={{
              fontFamily: "IBM Plex Mono, monospace",
              fontSize: "9px",
              fontWeight: 600,
              color: "rgba(255,255,255,0.55)",
              textAlign: "center",
              lineHeight: 1,
            }}>
              {r}
            </span>
          ))}
        </div>
        {/* Board + file labels column */}
        <div style={{ flex: 1, display: "flex", flexDirection: "column", minWidth: 0 }}>
          {/* Board grid */}
          <div style={{
            flex: 1,
            display: "grid",
            gridTemplateColumns: "repeat(8, 1fr)",
            gridTemplateRows: "repeat(8, 1fr)",
            border: "1px solid rgba(255,255,255,0.15)",
            borderRadius: "2px",
            overflow: "hidden",
            minHeight: 0,
          }}>
            {state.board.map((row, rankIdx) =>
              row.map((piece, fileIdx) => {
                const isLight = (rankIdx + fileIdx) % 2 === 0;
                const isWhitePiece = piece !== null && piece === piece.toUpperCase();
                return (
                  <div
                    key={`${rankIdx}-${fileIdx}`}
                    style={{
                      background: isLight ? LIGHT_SQ : DARK_SQ,
                      display: "flex",
                      alignItems: "center",
                      justifyContent: "center",
                      overflow: "hidden",
                    }}
                  >
                    {piece && (
                      <span
                        style={{
                          fontSize: "clamp(14px, 2.5vw, 28px)",
                          lineHeight: 1,
                          userSelect: "none",
                          // White pieces use hollow Unicode symbols (♔♕♖♗♘♙)
                          // Rendered in dark navy so the outline is visible on BOTH cream and brown squares
                          // Black pieces use filled Unicode symbols (♚♛♜♝♞♟) in vivid gold
                          color: isWhitePiece ? "#1a2744" : "#E8B400",
                          textShadow: isWhitePiece
                            ? "0 1px 2px rgba(255,255,255,0.5)"
                            : "0 1px 3px rgba(0,0,0,0.9), 0 0 8px rgba(232,180,0,0.5)",
                          filter: isWhitePiece
                            ? "drop-shadow(0 0 1px rgba(255,255,255,0.4))"
                            : "drop-shadow(0 0 3px rgba(232,180,0,0.6))",
                        }}
                      >
                        {PIECES[piece] ?? piece}
                      </span>
                    )}
                  </div>
                );
              })
            )}
          </div>
          {/* File labels */}
          <div style={{ display: "flex", height: "14px", flexShrink: 0 }}>
            {FILES.map((f) => (
              <span key={f} style={{
                flex: 1,
                textAlign: "center",
                fontFamily: "IBM Plex Mono, monospace",
                fontSize: "9px",
                fontWeight: 600,
                color: "rgba(255,255,255,0.55)",
                lineHeight: "14px",
              }}>
                {f}
              </span>
            ))}
          </div>
        </div>
      </div>
    </div>
  );
}