{"spec_id":"chessboard-basic","library":"echarts","language":"javascript","code":"// anyplot.ai\n// chessboard-basic: Chess Board Grid Visualization\n// Library: echarts 6.1.0 | JavaScript 22.23.2\n// Quality: 91/100 | Created: 2026-09-01\n\n//# anyplot-orientation: square\nconst t = window.ANYPLOT_TOKENS;\n\n// --- Data (in-memory, deterministic) ----------------------------------------\n// Standard algebraic notation: files a-h (columns), ranks 1-8 (rows).\n// A square is light when (file index + rank index) is odd — h1 light, a1 dark.\nconst files = [\"a\", \"b\", \"c\", \"d\", \"e\", \"f\", \"g\", \"h\"];\nconst ranks = [\"1\", \"2\", \"3\", \"4\", \"5\", \"6\", \"7\", \"8\"];\n\nconst squares = [];\nfor (let file = 0; file < files.length; file++) {\n  for (let rank = 0; rank < ranks.length; rank++) {\n    const isLight = (file + rank) % 2 === 1;\n    squares.push([file, rank, isLight ? 1 : 0]);\n  }\n}\n\n// Wood-toned board: dark squares use the Imprint ochre hue (semantic\n// exception — wood → ochre); light squares use the amber semantic anchor, a\n// fixed non-theme-adaptive gold tone, so the light/dark square pair keeps the\n// same identity in both themes (data colors must not flip with the theme).\nconst DARK_SQUARE = t.palette[3];\nconst LIGHT_SQUARE = t.amber;\n\n// --- Init --------------------------------------------------------------------\nconst chart = echarts.init(document.getElementById(\"container\"));\n\n// --- Option --------------------------------------------------------------------\nchart.setOption({\n  animation: false,\n  backgroundColor: \"transparent\",\n  title: {\n    text: \"chessboard-basic · javascript · echarts · anyplot.ai\",\n    subtext: \"White's near-right square (h1) is light — standard orientation\",\n    left: \"center\",\n    top: 20,\n    textStyle: { color: t.ink, fontSize: 22 },\n    subtextStyle: { color: t.inkSoft, fontSize: 16 },\n  },\n  grid: { left: 140, right: 140, top: 140, bottom: 140 },\n  xAxis: {\n    type: \"category\",\n    data: files,\n    position: \"bottom\",\n    axisLabel: { color: t.inkSoft, fontSize: 20 },\n    axisLine: { show: false },\n    axisTick: { show: false },\n    splitLine: { show: false },\n  },\n  yAxis: {\n    type: \"category\",\n    data: ranks,\n    position: \"left\",\n    axisLabel: { color: t.inkSoft, fontSize: 20 },\n    axisLine: { show: false },\n    axisTick: { show: false },\n    splitLine: { show: false },\n  },\n  series: [\n    {\n      type: \"custom\",\n      encode: { x: 0, y: 1 },\n      data: squares,\n      renderItem: (params, api) => {\n        const [x, y] = api.coord([api.value(0), api.value(1)]);\n        const [cellWidth, cellHeight] = api.size([1, 1]);\n        return {\n          type: \"rect\",\n          shape: {\n            x: x - cellWidth / 2,\n            y: y - cellHeight / 2,\n            width: cellWidth,\n            height: cellHeight,\n          },\n          style: {\n            fill: api.value(2) === 1 ? LIGHT_SQUARE : DARK_SQUARE,\n            stroke: t.grid,\n            lineWidth: 1,\n          },\n        };\n      },\n    },\n  ],\n});\n"}