chesspal 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (209) hide show
  1. package/README.md +45 -82
  2. package/dist/cli/chat-hook.js +1 -1
  3. package/dist/cli/command-line.d.ts +1 -2
  4. package/dist/cli/command-line.js +2 -3
  5. package/dist/commands/agents.d.ts +26 -0
  6. package/dist/commands/agents.js +72 -0
  7. package/dist/commands/ai-move.d.ts +5 -14
  8. package/dist/commands/ai-move.js +28 -35
  9. package/dist/commands/ai-say.d.ts +3 -1
  10. package/dist/commands/ai-say.js +24 -6
  11. package/dist/commands/analyse-game.d.ts +4 -0
  12. package/dist/commands/analyse-game.js +43 -16
  13. package/dist/commands/annotate-game.d.ts +4 -0
  14. package/dist/commands/annotate-game.js +65 -12
  15. package/dist/commands/answer-lines.d.ts +28 -0
  16. package/dist/commands/answer-lines.js +144 -0
  17. package/dist/commands/coach.d.ts +45 -0
  18. package/dist/commands/coach.js +344 -0
  19. package/dist/commands/context.d.ts +16 -5
  20. package/dist/commands/context.js +1 -0
  21. package/dist/commands/delete-game.d.ts +7 -0
  22. package/dist/commands/delete-game.js +30 -0
  23. package/dist/commands/delete-review.d.ts +8 -0
  24. package/dist/commands/delete-review.js +34 -0
  25. package/dist/commands/drawings.d.ts +0 -2
  26. package/dist/commands/drawings.js +5 -3
  27. package/dist/commands/end-game.js +5 -2
  28. package/dist/commands/export-game.d.ts +1 -1
  29. package/dist/commands/export-game.js +4 -3
  30. package/dist/commands/game-summary.d.ts +21 -38
  31. package/dist/commands/game-summary.js +30 -167
  32. package/dist/commands/index.d.ts +15 -0
  33. package/dist/commands/index.js +47 -2
  34. package/dist/commands/init.d.ts +3 -3
  35. package/dist/commands/init.js +4 -4
  36. package/dist/commands/lead-input.d.ts +8 -0
  37. package/dist/commands/lead-input.js +21 -0
  38. package/dist/commands/look.js +4 -1
  39. package/dist/commands/new-game.d.ts +2 -3
  40. package/dist/commands/new-game.js +7 -4
  41. package/dist/commands/play-move.d.ts +8 -15
  42. package/dist/commands/play-move.js +5 -13
  43. package/dist/commands/player-move.d.ts +2 -6
  44. package/dist/commands/player-move.js +13 -6
  45. package/dist/commands/player-say.d.ts +1 -1
  46. package/dist/commands/player-say.js +1 -1
  47. package/dist/commands/ponder.d.ts +10 -0
  48. package/dist/commands/ponder.js +33 -21
  49. package/dist/commands/position.d.ts +1 -1
  50. package/dist/commands/position.js +3 -1
  51. package/dist/commands/profiles.d.ts +13 -4
  52. package/dist/commands/profiles.js +49 -15
  53. package/dist/commands/registry.d.ts +8 -3
  54. package/dist/commands/registry.js +12 -11
  55. package/dist/commands/say.d.ts +1 -1
  56. package/dist/commands/say.js +16 -16
  57. package/dist/commands/speech.d.ts +8 -0
  58. package/dist/commands/speech.js +20 -0
  59. package/dist/commands/status.d.ts +9 -3
  60. package/dist/commands/status.js +40 -15
  61. package/dist/commands/study-games.js +1 -1
  62. package/dist/commands/study.js +3 -19
  63. package/dist/core/facts.js +15 -15
  64. package/dist/core/game.d.ts +3 -1
  65. package/dist/core/game.js +8 -4
  66. package/dist/core/illegal.js +1 -1
  67. package/dist/core/index.d.ts +5 -4
  68. package/dist/core/index.js +5 -4
  69. package/dist/core/lead.d.ts +15 -0
  70. package/dist/core/lead.js +40 -0
  71. package/dist/core/levels.d.ts +1 -1
  72. package/dist/core/levels.js +1 -1
  73. package/dist/core/moods.d.ts +0 -2
  74. package/dist/core/moods.js +2 -2
  75. package/dist/core/openings.d.ts +0 -2
  76. package/dist/core/openings.js +1 -1
  77. package/dist/core/profile.js +1 -1
  78. package/dist/core/record.d.ts +1 -1
  79. package/dist/core/record.js +1 -1
  80. package/dist/core/review.d.ts +9 -3
  81. package/dist/core/review.js +29 -9
  82. package/dist/games/analysis.d.ts +1 -1
  83. package/dist/games/archive.d.ts +24 -3
  84. package/dist/games/archive.js +96 -22
  85. package/dist/games/coach.d.ts +57 -0
  86. package/dist/games/coach.js +144 -0
  87. package/dist/games/current-game.d.ts +2 -0
  88. package/dist/games/current-game.js +7 -1
  89. package/dist/games/files.js +1 -0
  90. package/dist/games/index.d.ts +4 -3
  91. package/dist/games/index.js +4 -3
  92. package/dist/games/talk.d.ts +1 -5
  93. package/dist/games/talk.js +14 -14
  94. package/dist/home/open-folder.js +1 -1
  95. package/dist/host-files/{ponder-agents.d.ts → agents.d.ts} +10 -2
  96. package/dist/host-files/agents.js +53 -0
  97. package/dist/host-files/host-files.d.ts +7 -2
  98. package/dist/host-files/host-files.js +27 -12
  99. package/dist/host-files/index.d.ts +2 -2
  100. package/dist/host-files/index.js +3 -3
  101. package/dist/index.d.ts +1 -3
  102. package/dist/index.js +1 -0
  103. package/dist/page/app/anchor.js +88 -0
  104. package/dist/page/{app.js → app/app.js} +112 -230
  105. package/dist/page/app/keys.js +94 -0
  106. package/dist/page/app/phase.js +30 -0
  107. package/dist/page/app/served.js +73 -0
  108. package/dist/page/avatars/avatars.js +19 -0
  109. package/dist/page/avatars/thought.js +10 -0
  110. package/dist/page/base.css +160 -0
  111. package/dist/page/board/board.css +959 -0
  112. package/dist/page/board/board.js +125 -0
  113. package/dist/page/{explain.js → board/explain.js} +1 -1
  114. package/dist/page/board/marks.js +160 -0
  115. package/dist/page/board/motion.js +71 -0
  116. package/dist/page/board/pointer.js +239 -0
  117. package/dist/page/board/squares.js +26 -0
  118. package/dist/page/dialogs/analyses.js +195 -0
  119. package/dist/page/{dialog.js → dialogs/dialog.js} +1 -1
  120. package/dist/page/dialogs/dialogs.css +1228 -0
  121. package/dist/page/{new-game-dialog.js → dialogs/new-game.js} +3 -3
  122. package/dist/page/{profile-dialogs.js → dialogs/profiles.js} +40 -11
  123. package/dist/page/dialogs/search.js +31 -0
  124. package/dist/page/dialogs/settings.js +42 -0
  125. package/dist/page/dialogs/studied.js +39 -0
  126. package/dist/page/dialogs/study.js +51 -0
  127. package/dist/page/{badges.js → game/badges.js} +1 -1
  128. package/dist/page/{browse.js → game/browse.js} +1 -1
  129. package/dist/page/game/card-fold.js +40 -0
  130. package/dist/page/game/column.js +51 -0
  131. package/dist/page/{ending.js → game/ending.js} +2 -2
  132. package/dist/page/game/game.css +577 -0
  133. package/dist/page/{move-list.js → game/move-list.js} +10 -6
  134. package/dist/page/{plies.js → game/plies.js} +30 -10
  135. package/dist/page/game/result-tile.js +14 -0
  136. package/dist/page/helps/helps.css +689 -0
  137. package/dist/page/helps/helps.js +220 -0
  138. package/dist/page/helps/view.js +127 -0
  139. package/dist/page/layout/fold-tab.js +11 -0
  140. package/dist/page/{folds.js → layout/folds.js} +1 -1
  141. package/dist/page/{header.js → layout/header.js} +5 -4
  142. package/dist/page/layout/layout.css +834 -0
  143. package/dist/page/lead/lead.js +82 -0
  144. package/dist/page/lead/view.js +38 -0
  145. package/dist/page/main.js +2 -2
  146. package/dist/page/pieces/CREDITS.md +12 -29
  147. package/dist/page/pieces/capablanca-small.svg +20 -0
  148. package/dist/page/pieces/capablanca.svg +22 -0
  149. package/dist/page/pieces/nitida-small.svg +3 -2
  150. package/dist/page/pieces/nitida.svg +3 -2
  151. package/dist/page/{pieces.js → pieces/pieces.js} +2 -2
  152. package/dist/page/pieces/torretta-small.svg +15 -14
  153. package/dist/page/pieces/torretta.svg +17 -15
  154. package/dist/page/{player-card.js → players/card.js} +2 -6
  155. package/dist/page/{clock-time.js → players/clock-time.js} +2 -2
  156. package/dist/page/{profile.js → profile/profile.js} +9 -5
  157. package/dist/page/{settings.js → profile/settings.js} +5 -4
  158. package/dist/page/style.css +9 -4398
  159. package/dist/page/talk/talk.css +958 -0
  160. package/dist/page/{talk.js → talk/talk.js} +39 -46
  161. package/dist/page/text.js +137 -19
  162. package/dist/page/theme.css +292 -0
  163. package/dist/profiles/index.d.ts +1 -1
  164. package/dist/profiles/profiles.d.ts +15 -4
  165. package/dist/profiles/profiles.js +24 -7
  166. package/dist/server/bell.d.ts +10 -2
  167. package/dist/server/bell.js +28 -12
  168. package/dist/server/caller.d.ts +14 -3
  169. package/dist/server/caller.js +44 -11
  170. package/dist/server/mcp.d.ts +1 -2
  171. package/dist/server/mcp.js +42 -14
  172. package/dist/server/page/analyses.d.ts +23 -0
  173. package/dist/server/page/analyses.js +65 -0
  174. package/dist/server/page/files.d.ts +5 -0
  175. package/dist/server/page/files.js +92 -0
  176. package/dist/server/page/game.d.ts +6 -0
  177. package/dist/server/page/game.js +381 -0
  178. package/dist/server/{http.d.ts → page/http.d.ts} +13 -0
  179. package/dist/server/{http.js → page/http.js} +11 -0
  180. package/dist/server/{page.d.ts → page/page.d.ts} +8 -13
  181. package/dist/server/page/page.js +229 -0
  182. package/dist/server/{profile-routes.d.ts → page/profiles.d.ts} +2 -2
  183. package/dist/server/{profile-routes.js → page/profiles.js} +47 -18
  184. package/instructions/analysis.md +4 -0
  185. package/instructions/analyst-agent.md +8 -0
  186. package/instructions/analyst.md +3 -7
  187. package/instructions/coach.md +11 -0
  188. package/instructions/opponent.md +4 -4
  189. package/package.json +1 -1
  190. package/dist/host-files/ponder-agents.js +0 -40
  191. package/dist/page/avatars.js +0 -16
  192. package/dist/page/board.js +0 -566
  193. package/dist/page/fold-tab.js +0 -9
  194. package/dist/page/game-column.js +0 -44
  195. package/dist/page/helps-view.js +0 -51
  196. package/dist/page/helps.js +0 -90
  197. package/dist/page/pieces/cburnett-small.svg +0 -20
  198. package/dist/page/pieces/cburnett.svg +0 -20
  199. package/dist/page/settings-panel.js +0 -32
  200. package/dist/page/studied.js +0 -14
  201. package/dist/page/study-dialog.js +0 -58
  202. package/dist/server/analyses.d.ts +0 -17
  203. package/dist/server/analyses.js +0 -46
  204. package/dist/server/page.js +0 -657
  205. /package/dist/page/{torretta.js → avatars/torretta.js} +0 -0
  206. /package/dist/page/{opening-book.js → game/opening-book.js} +0 -0
  207. /package/dist/page/{model-name.js → players/model-name.js} +0 -0
  208. /package/dist/page/{sounds.js → sounds/sounds.js} +0 -0
  209. /package/dist/page/{voice.js → talk/voice.js} +0 -0
@@ -1,4398 +1,9 @@
1
- /* The page in Zoe's Salotto azzurro (D-46), in three columns (D-53): the talk, the board, the game; one column on a phone; light and dark. */
2
- :root {
3
- --page: color-mix(in oklab, var(--dark-square) 12%, #fbfbfa);
4
- --card: color-mix(in oklab, var(--dark-square) 3%, #ffffff);
5
- --ink: #1d2733;
6
- --soft: #626d7b;
7
- --line: color-mix(in oklab, var(--dark-square) 24%, #f1f1ef);
8
- --accent: #2d6aa8;
9
- --on-accent: #ffffff;
10
- --quote: color-mix(in oklab, var(--dark-square) 9%, #fafafa);
11
- --say: color-mix(in oklab, var(--dark-square) 38%, #fafafa);
12
- --say-ink: #1d2733;
13
- --warn-back: #fff4d6;
14
- --light-square: #eaf1f8;
15
- --dark-square: #86abd0;
16
- --last-move: rgba(255, 196, 80, 0.5);
17
- --selected: rgba(255, 196, 80, 0.7);
18
- --mark: #f07c1e;
19
- --mark-square: rgba(240, 124, 30, 0.65);
20
- --mated: rgba(214, 40, 40, 0.8);
21
- --low-time: #c62828;
22
- --hint: rgba(0, 0, 0, 0.14);
23
- --hover-edge: #f4c84c;
24
- --explain-ink: #1d2733;
25
- --lift-shadow: rgba(16, 28, 44, 0.32);
26
- --ghost: 0.35;
27
- --white-piece: #fff;
28
- --black-piece: #000;
29
- --torretta-body: #6d9fd1;
30
- --torretta-shade: #4b7cb0;
31
- --torretta-screen: #16263a;
32
- --torretta-face: #f2f7fc;
33
- --torretta-light: #f4c84c;
34
- --torretta-alarm: #ef6a4c;
35
- --torretta-ponder: #8f9a8a;
36
- /* The badges of the moves (D-69, T-41): white signs, dark on the yellow one; each disc at least 3:1 with its sign */
37
- --badge-ink: #fff;
38
- --badge-note: #7b8794;
39
- --badge-brilliant: #0f9a9e;
40
- --badge-great: #2f74c8;
41
- --badge-best: #3c9a3a;
42
- --badge-excellent: #6b9c2c;
43
- --badge-good: #7d9a62;
44
- --badge-book: #94704c;
45
- --badge-inaccuracy: #e6b422;
46
- --badge-inaccuracy-ink: #3b2c00;
47
- --badge-mistake: #d4650f;
48
- --badge-miss: #c2407d;
49
- --badge-blunder: #d22c2c;
50
- --shadow: 0 1px 2px rgba(29, 39, 51, 0.06), 0 6px 18px rgba(29, 39, 51, 0.06);
51
- /* On a light page the board keeps a thin edge in its dark squares colour, and a deeper shadow, so its light squares do not melt into the page (T-83) */
52
- --board-shadow: 0 0 0 1px color-mix(in oklab, var(--dark-square) 55%, transparent), 0 2px 4px rgba(29, 39, 51, 0.1), 0 10px 28px rgba(29, 39, 51, 0.12);
53
- --gap: 20px;
54
- --left: 300px;
55
- --right: 300px;
56
- /* The board's least size beside the talk: room for the AI's words, the box and both cards; a lower window scrolls (T-103) */
57
- --least: 440px;
58
- --tab: 16px;
59
- --rail: 56px;
60
- --coin: 40px;
61
- /* How far from the board's top and bottom edges the faces sit, in the cards and folded, and the tabs */
62
- --ear: 36px;
63
- --tuck: 10px;
64
- --bar: 36px;
65
- /* The cards' corners, as the board's; the room between the cards, and between them and the board */
66
- --radius: 6px;
67
- --between: 10px;
68
- --bubble: 14px;
69
- color-scheme: light;
70
- }
71
-
72
- :root[data-theme="dark"] {
73
- --page: color-mix(in oklab, var(--dark-square) 13%, #0b0d10);
74
- --card: color-mix(in oklab, var(--dark-square) 16%, #14171b);
75
- --ink: #e6ebf1;
76
- --soft: #8d98a7;
77
- --line: color-mix(in oklab, var(--dark-square) 24%, #1b1f24);
78
- --accent: #7cb0e4;
79
- --on-accent: #0f1a28;
80
- --low-time: #ff6b6b;
81
- --quote: color-mix(in oklab, var(--dark-square) 20%, #1a1d22);
82
- --say: color-mix(in oklab, var(--dark-square) 34%, #15181c);
83
- --say-ink: #e6ebf1;
84
- --warn-back: #2a2616;
85
- --light-square: #a9bccd;
86
- --dark-square: #61809e;
87
- --hint: rgba(0, 0, 0, 0.17);
88
- --lift-shadow: rgba(0, 0, 0, 0.5);
89
- --torretta-screen: #0f1a28;
90
- --badge-great: #3577c9;
91
- --badge-book: #9c7650;
92
- --badge-miss: #c9478a;
93
- --badge-blunder: #d93434;
94
- --shadow: 0 1px 2px rgba(0, 0, 0, 0.3), 0 8px 22px rgba(0, 0, 0, 0.25);
95
- --board-shadow: var(--shadow);
96
- color-scheme: dark;
97
- }
98
-
99
- * {
100
- box-sizing: border-box;
101
- }
102
-
103
- body {
104
- margin: 0;
105
- min-height: 100vh;
106
- background: var(--page);
107
- color: var(--ink);
108
- font-family: "Segoe UI Variable Text", "Segoe UI", system-ui, -apple-system, "Helvetica Neue", sans-serif;
109
- font-size: 15px;
110
- -webkit-font-smoothing: antialiased;
111
- }
112
-
113
- button,
114
- textarea {
115
- font: inherit;
116
- color: inherit;
117
- }
118
-
119
- button {
120
- cursor: pointer;
121
- }
122
-
123
- /* The header */
124
- .top {
125
- grid-area: head;
126
- height: var(--bar);
127
- margin-top: var(--between);
128
- container-type: inline-size;
129
- display: flex;
130
- align-items: center;
131
- gap: 10px;
132
- padding: 0 var(--gap);
133
- }
134
-
135
- /* In the page's grid the header spans the board, edge to edge, as far from it as the cards */
136
- .app .top {
137
- margin: 0;
138
- padding: 0;
139
- }
140
-
141
- .title {
142
- flex: 1;
143
- font-size: 17px;
144
- font-weight: 600;
145
- letter-spacing: 0.01em;
146
- }
147
-
148
- /* A game over says how it ended by the new game, which stands out in the accent (T-77) */
149
- .verdict {
150
- margin: 0;
151
- min-width: 0;
152
- overflow: hidden;
153
- white-space: nowrap;
154
- text-overflow: ellipsis;
155
- border-radius: 999px;
156
- padding: 6px 12px;
157
- background: color-mix(in srgb, var(--accent) 14%, transparent);
158
- color: var(--ink);
159
- font-size: 14px;
160
- font-weight: 600;
161
- animation: appear 200ms;
162
- }
163
-
164
- .verdict:empty {
165
- display: none;
166
- }
167
-
168
- /* The chip's icon says what it is about; the game in analysis stands out in the accent's colour (D-69) */
169
- .verdict:has(.icon) {
170
- display: flex;
171
- align-items: center;
172
- gap: 6px;
173
- }
174
-
175
- .verdict .icon {
176
- flex: none;
177
- width: 16px;
178
- height: 16px;
179
- stroke-width: 2;
180
- }
181
-
182
- .verdict.analysis {
183
- background: color-mix(in srgb, var(--accent) 22%, transparent);
184
- color: var(--ink);
185
- }
186
-
187
- .icon {
188
- width: 17px;
189
- height: 17px;
190
- fill: none;
191
- stroke: currentColor;
192
- stroke-width: 1.7;
193
- stroke-linecap: round;
194
- stroke-linejoin: round;
195
- }
196
-
197
- .command {
198
- display: inline-flex;
199
- align-items: center;
200
- gap: 7px;
201
- background: none;
202
- border: 1px solid transparent;
203
- border-radius: 8px;
204
- padding: 7px 11px;
205
- font-size: 14px;
206
- color: var(--soft);
207
- }
208
-
209
- .command:hover,
210
- .command[aria-pressed="true"] {
211
- color: var(--ink);
212
- border-color: var(--line);
213
- background: var(--card);
214
- }
215
-
216
- .command.primary {
217
- background: var(--accent);
218
- border-color: var(--accent);
219
- color: var(--on-accent);
220
- }
221
-
222
- .command.primary:hover {
223
- background: color-mix(in oklab, var(--accent) 85%, var(--ink));
224
- border-color: transparent;
225
- color: var(--on-accent);
226
- }
227
-
228
- /* A draw the player cannot offer now: before a move each, on the AI's turn, or with an offer standing (D-65); their own offer stands pressed, at full strength */
229
- .command[aria-disabled="true"]:not([aria-pressed="true"]) {
230
- cursor: default;
231
- opacity: 0.5;
232
- }
233
-
234
- .command[aria-disabled="true"]:not([aria-pressed="true"]):hover {
235
- color: var(--soft);
236
- border-color: transparent;
237
- background: none;
238
- }
239
-
240
- /* The answer to the AI's offer: accepting and declining weigh the same */
241
- .command.answer {
242
- color: var(--ink);
243
- border-color: var(--line);
244
- }
245
-
246
- /* While the AI's draw offer stands, the answer keeps its words and the other commands only their icons; in a game going on, a narrow board keeps icons alone */
247
- .top:has(.answer) .command:not(.answer) span {
248
- display: none;
249
- }
250
-
251
- @container (max-width: 800px) {
252
- .top:has(.icon.resign) .command:not(.answer) span {
253
- display: none;
254
- }
255
-
256
- /* Beside a narrow board the offer and its answer take the room of the other commands, which come back once it is answered */
257
- .top:has(.answer) .command:not(.answer) {
258
- display: none;
259
- }
260
- }
261
-
262
- /* The AI's name gives way before its verb (D-65) */
263
- .verdict:has(.ai-name) {
264
- display: flex;
265
- gap: 0.3em;
266
- }
267
-
268
- .verdict .ai-name {
269
- min-width: 0;
270
- overflow: hidden;
271
- text-overflow: ellipsis;
272
- }
273
-
274
- .verdict .ai-name + span {
275
- flex-shrink: 0;
276
- }
277
-
278
- .top .torretta {
279
- flex-shrink: 0;
280
- }
281
-
282
- /* The header's buttons never wrap or shrink: the word on a game over gives way */
283
- .top .command,
284
- .top .theme {
285
- flex-shrink: 0;
286
- white-space: nowrap;
287
- }
288
-
289
- :focus-visible {
290
- outline: 2px solid var(--accent);
291
- outline-offset: 2px;
292
- }
293
-
294
- .theme {
295
- display: grid;
296
- place-items: center;
297
- width: 36px;
298
- height: 36px;
299
- background: none;
300
- border: 1px solid var(--line);
301
- border-radius: 8px;
302
- color: var(--soft);
303
- }
304
-
305
- .theme:hover {
306
- color: var(--ink);
307
- }
308
-
309
- :root[data-theme="dark"] .theme .sun,
310
- :root:not([data-theme="dark"]) .theme .moon {
311
- display: none;
312
- }
313
-
314
- /* Three columns: the talk, the board, the game, under the header, which spans the board. The side columns take the board's height and scroll inside it; folded,
315
- they slide under the board, which grows into the room */
316
- .app {
317
- --left-now: var(--left);
318
- --right-now: var(--right);
319
- --rows: var(--between);
320
- display: grid;
321
- gap: var(--rows) var(--between);
322
- padding: var(--between) var(--gap);
323
- grid-template-columns: var(--left-now) auto var(--right-now);
324
- transition: grid-template-columns 200ms cubic-bezier(0.2, 0, 0, 1);
325
- grid-template-rows: auto minmax(var(--least), auto);
326
- grid-template-areas: ". head ." "talk board side";
327
- justify-content: center;
328
- }
329
-
330
- /* Beside a narrow board the header's buttons keep only their icons */
331
- @container (max-width: 560px) {
332
- .command span {
333
- display: none;
334
- }
335
- }
336
-
337
- /* Beside the word on a game over, the Torretta alone stands for the name, and the flip keeps only its icon; a phone gives the word a line of its own */
338
- @media (min-width: 841px) {
339
- @container (max-width: 720px) {
340
- .top:has(.verdict:not(:empty)) .title,
341
- .top:has(.verdict:not(:empty)) .command:not(.primary):not(.answer) span {
342
- display: none;
343
- }
344
-
345
- .top:has(.verdict:not(:empty)) .verdict {
346
- margin-right: auto;
347
- }
348
- }
349
- }
350
-
351
- .app.talk-rail {
352
- --left-now: var(--rail);
353
- }
354
-
355
- .app.talk-folded {
356
- --left-now: 0px;
357
- }
358
-
359
- .app.folded {
360
- --right-now: 0px;
361
- }
362
-
363
- .board-wrap {
364
- grid-area: board;
365
- position: relative;
366
- /* 12.5cqw is a square, for the lifted piece too */
367
- container-type: inline-size;
368
- width: min(calc(100vw - var(--left-now) - var(--right-now) - 2 * var(--gap) - 2 * var(--between)), max(var(--least), calc(100vh - var(--bar) - 3 * var(--between))));
369
- transition: width 200ms cubic-bezier(0.2, 0, 0, 1);
370
- }
371
-
372
- .talk {
373
- grid-area: talk;
374
- display: flex;
375
- flex-direction: column;
376
- justify-content: space-between;
377
- gap: var(--between);
378
- contain: size;
379
- min-height: 0;
380
- }
381
-
382
- /* Narrowing, the talk fades into its card of faces while it slides under the board, in the same 200ms */
383
- .app.talk-rail .talk,
384
- .app.talk-folded .talk {
385
- visibility: hidden;
386
- opacity: 0;
387
- transition: opacity 120ms 80ms, visibility 0s 200ms;
388
- }
389
-
390
- /* A column's tab (T-84), a drawer's handle at the top: open, on the outer edge of the column's first card; folded, the column slides under the board and the
391
- tab peeks out from under it */
392
- .fold-tab {
393
- align-self: start;
394
- position: relative;
395
- display: flex;
396
- width: var(--tab);
397
- height: 48px;
398
- margin-top: calc(var(--ear) - 24px);
399
- transition: width 200ms cubic-bezier(0.2, 0, 0, 1), margin 200ms cubic-bezier(0.2, 0, 0, 1);
400
- }
401
-
402
- .fold-tab.folded {
403
- width: calc(var(--tab) + var(--tuck));
404
- }
405
-
406
- .fold-tab.of-talk {
407
- grid-area: talk;
408
- justify-self: start;
409
- margin-left: calc(-1 * var(--tab));
410
- }
411
-
412
- .fold-tab.of-talk.folded {
413
- margin-left: calc(var(--between) - var(--tab));
414
- }
415
-
416
- .fold-tab.of-game {
417
- grid-area: side;
418
- justify-self: end;
419
- margin-right: calc(-1 * var(--tab));
420
- }
421
-
422
- .fold-tab.of-game.folded {
423
- margin-right: calc(var(--between) - var(--tab));
424
- }
425
-
426
- .fold-tab button {
427
- flex: 1;
428
- position: relative;
429
- display: grid;
430
- place-items: center;
431
- padding: 0;
432
- background: var(--card);
433
- border: 1px solid var(--line);
434
- box-shadow: var(--shadow);
435
- color: var(--soft);
436
- }
437
-
438
- .fold-tab button:hover {
439
- color: var(--ink);
440
- }
441
-
442
- .fold-tab .icon {
443
- width: 14px;
444
- height: 14px;
445
- stroke-width: 2;
446
- }
447
-
448
- /* Rounded on the outer side, its icon clear of the board; the card it leans on gives its inner edge */
449
- .fold-tab.of-talk button {
450
- border-right: 0;
451
- border-radius: var(--radius) 0 0 var(--radius);
452
- }
453
-
454
- .fold-tab.of-game button {
455
- border-left: 0;
456
- border-radius: 0 var(--radius) var(--radius) 0;
457
- }
458
-
459
- .fold-tab.of-talk.folded button {
460
- padding-right: var(--tuck);
461
- }
462
-
463
- .fold-tab.of-game.folded button {
464
- padding-left: var(--tuck);
465
- }
466
-
467
- /* The talk narrowed to a card beside the board, with two equal coins where the faces sat in the cards: the Torretta above and the player below, once the talk
468
- has slid under the board */
469
- .faces {
470
- grid-area: talk;
471
- justify-self: start;
472
- display: none;
473
- flex-direction: column;
474
- justify-content: space-between;
475
- align-items: center;
476
- gap: 16px;
477
- width: var(--rail);
478
- min-height: 0;
479
- overflow: hidden;
480
- padding: calc(var(--ear) - var(--coin) / 2 - 1px) 0;
481
- background: var(--card);
482
- border: 1px solid var(--line);
483
- border-radius: var(--radius);
484
- box-shadow: var(--shadow);
485
- }
486
-
487
- .app.talk-rail .faces {
488
- display: flex;
489
- animation: faces-in 120ms 80ms both;
490
- }
491
-
492
- /* Folding, the card of faces slides under the board in its turn */
493
- .app.talk-folded .faces {
494
- display: flex;
495
- visibility: hidden;
496
- transition: visibility 0s 200ms;
497
- }
498
-
499
- .app.flipped .faces {
500
- flex-direction: column-reverse;
501
- }
502
-
503
- @keyframes faces-in {
504
- from {
505
- opacity: 0;
506
- }
507
- }
508
-
509
- /* Each face with the name and side written down the card from it: the lower one's run up to it */
510
- .rail-player {
511
- display: flex;
512
- flex-direction: column;
513
- align-items: center;
514
- gap: 10px;
515
- min-height: 0;
516
- }
517
-
518
- .rail-player.you,
519
- .app.flipped .rail-player.ai {
520
- flex-direction: column-reverse;
521
- }
522
-
523
- .app.flipped .rail-player.you {
524
- flex-direction: column;
525
- }
526
-
527
- /* The lower name reads upwards, its letters' tops to the left */
528
- .rail-player.you .rail-name,
529
- .app.flipped .rail-player.ai .rail-name {
530
- rotate: 180deg;
531
- }
532
-
533
- .app.flipped .rail-player.you .rail-name {
534
- rotate: none;
535
- }
536
-
537
- .rail-name {
538
- min-height: 0;
539
- overflow: hidden;
540
- writing-mode: vertical-rl;
541
- white-space: nowrap;
542
- text-overflow: ellipsis;
543
- font-size: 13px;
544
- font-weight: 600;
545
- }
546
-
547
- .face {
548
- flex: none;
549
- position: relative;
550
- display: grid;
551
- place-items: center;
552
- width: var(--coin);
553
- height: var(--coin);
554
- border-radius: 50%;
555
- background: var(--say);
556
- }
557
-
558
- /* Both faces fill their circle, with no edge */
559
- .face svg,
560
- .face img {
561
- width: var(--coin);
562
- height: var(--coin);
563
- clip-path: circle(50%);
564
- }
565
-
566
- /* Who moves: their name in the accent */
567
- .rail-player.moving .rail-name {
568
- color: var(--accent);
569
- }
570
-
571
- /* The AI spoke while the talk was narrowed or folded: on the Torretta, or on the tab */
572
- .face.unread::after,
573
- .fold-tab button.unread::after {
574
- content: "";
575
- position: absolute;
576
- top: 0;
577
- right: 0;
578
- width: 10px;
579
- height: 10px;
580
- border-radius: 50%;
581
- background: var(--accent);
582
- box-shadow: 0 0 0 2px var(--page);
583
- }
584
-
585
- .fold-tab button.unread::after {
586
- top: -4px;
587
- right: auto;
588
- left: -4px;
589
- }
590
-
591
- /* A long name or model goes to its ellipsis instead of widening the page on a phone (Zoe, round of T-118) */
592
- .ai-block,
593
- .you-block {
594
- display: flex;
595
- flex-direction: column;
596
- min-height: 0;
597
- min-width: 0;
598
- }
599
-
600
- /* Each side's talk has half the column at most: past it, its words scroll; the box and the cards never give way. */
601
- .ai-block,
602
- .you-block {
603
- flex: 0 1 auto;
604
- max-height: calc(50% - var(--between) / 2);
605
- }
606
-
607
- .you-block > .compose,
608
- .you-block > .player {
609
- flex: none;
610
- }
611
-
612
- /* The board */
613
- /* Above the columns' tabs, which slide under it */
614
- .board {
615
- position: relative;
616
- z-index: 1;
617
- display: grid;
618
- grid-template-columns: repeat(8, 1fr);
619
- grid-template-rows: repeat(8, 1fr);
620
- aspect-ratio: 1;
621
- border-radius: var(--radius);
622
- overflow: hidden;
623
- box-shadow: var(--board-shadow);
624
- user-select: none;
625
- container-type: inline-size;
626
- }
627
-
628
- .square {
629
- position: relative;
630
- }
631
-
632
- .square.light {
633
- background-color: var(--light-square);
634
- }
635
-
636
- .square.dark {
637
- background-color: var(--dark-square);
638
- }
639
-
640
- .square.last {
641
- background-image: linear-gradient(var(--last-move), var(--last-move));
642
- }
643
-
644
- .square.selected {
645
- background-image: linear-gradient(var(--selected), var(--selected));
646
- }
647
-
648
- /* The king checkmated (T-77): its square red, over the last move's colour */
649
- .square.mated {
650
- background-image: linear-gradient(var(--mated), var(--mated));
651
- }
652
-
653
- /* The player's marks with the right button (T-73): orange squares and arrows, gone at a left click */
654
- .square.marked {
655
- background-image: linear-gradient(var(--mark-square), var(--mark-square));
656
- }
657
-
658
- /* The square the player points at in the AI's words (T-111): a white ring with a dark edge, which reads on every board and over the rings the AI draws */
659
- .square.pointed {
660
- outline: max(4px, 0.8cqw) solid #fff;
661
- outline-offset: calc(-1 * max(4px, 0.8cqw));
662
- box-shadow: inset 0 0 0 calc(max(4px, 0.8cqw) + 2px) rgba(0, 0, 0, 0.55);
663
- }
664
-
665
- /* On a square the AI marked, the pointer's ring takes the place of the AI's while it lasts */
666
- .square.noted.pointed::after {
667
- box-shadow: inset 0 0 0 max(4px, 0.8cqw) #fff, inset 0 0 0 calc(max(4px, 0.8cqw) + 2px) rgba(0, 0, 0, 0.55);
668
- }
669
-
670
- .arrows {
671
- position: absolute;
672
- left: 0;
673
- top: 0;
674
- width: 100%;
675
- aspect-ratio: 1;
676
- /* Over every square, the sliding piece's too (z-index 1) */
677
- z-index: 2;
678
- pointer-events: none;
679
- opacity: 0.7;
680
- }
681
-
682
- .arrows path {
683
- fill: none;
684
- stroke: var(--mark);
685
- stroke-width: 0.2;
686
- }
687
-
688
- .arrows polygon {
689
- fill: var(--mark);
690
- }
691
-
692
- /* What the AI draws with its note in an analysis (D-69): arrows and squares in the four colours of PGN's %cal and %csl */
693
- .arrows g.green {
694
- --mark: #15a34a;
695
- }
696
-
697
- .arrows g.red {
698
- --mark: #dc2626;
699
- }
700
-
701
- .arrows g.yellow {
702
- --mark: #eab308;
703
- }
704
-
705
- .arrows g.blue {
706
- --mark: #2563eb;
707
- }
708
-
709
- /* The AI's arrows have a white edge, as its rings do (D-78): they read as its own whatever colour the player marks in */
710
- .arrows .edge {
711
- stroke: #fff;
712
- }
713
-
714
- .arrows path.edge {
715
- stroke-width: 0.3;
716
- }
717
-
718
- .arrows polygon.edge {
719
- fill: #fff;
720
- stroke-width: 0.1;
721
- stroke-linejoin: round;
722
- }
723
-
724
- /* The AI's squares are rings (Zoe, T-40): the last move's fill and the player's marks stay seen under them */
725
- .square.noted::after {
726
- content: "";
727
- position: absolute;
728
- inset: 0;
729
- pointer-events: none;
730
- box-shadow: inset 0 0 0 max(3px, 0.6cqw) var(--ring), inset 0 0 0 calc(max(3px, 0.6cqw) + 1.5px) rgba(255, 255, 255, 0.8);
731
- }
732
-
733
- .square.noted.green {
734
- --ring: #15a34a;
735
- }
736
-
737
- .square.noted.red {
738
- --ring: #dc2626;
739
- }
740
-
741
- .square.noted.yellow {
742
- --ring: #eab308;
743
- }
744
-
745
- .square.noted.blue {
746
- --ring: #2563eb;
747
- }
748
-
749
- /* Moving a piece (T-70, Zoe's design): dots for the legal moves, rings on captures, a gold edge on the square a dragged piece would land on */
750
- .square.hint::before {
751
- content: "";
752
- position: absolute;
753
- inset: 0;
754
- margin: auto;
755
- width: 33%;
756
- height: 33%;
757
- border-radius: 50%;
758
- background: var(--hint);
759
- pointer-events: none;
760
- }
761
-
762
- .square.hint.capture::before {
763
- inset: 4%;
764
- width: auto;
765
- height: auto;
766
- margin: 0;
767
- background: none;
768
- border: 1cqw solid var(--hint);
769
- }
770
-
771
- .square.over {
772
- box-shadow: inset 0 0 0 max(2px, 0.625cqw) var(--hover-edge);
773
- }
774
-
775
- @media (hover: hover) {
776
- .board.playable .square.hint:hover,
777
- .board.playable .square.target:hover {
778
- box-shadow: inset 0 0 0 max(2px, 0.625cqw) var(--hover-edge);
779
- }
780
- }
781
-
782
- .square.from .piece {
783
- opacity: var(--ghost);
784
- }
785
-
786
- .board {
787
- -webkit-tap-highlight-color: transparent;
788
- -webkit-touch-callout: none;
789
- }
790
-
791
- .board.playable .square.own {
792
- cursor: grab;
793
- touch-action: none;
794
- }
795
-
796
- .board.playable .square.hint,
797
- .board.playable .square.target {
798
- cursor: pointer;
799
- }
800
-
801
- :root.dragging,
802
- :root.dragging * {
803
- cursor: grabbing !important;
804
- }
805
-
806
- /* The lifted piece follows the pointer without a transition; the piece inside it rises. Fixed to the window, it never gives the page a scrollbar */
807
- .lifted {
808
- position: fixed;
809
- left: 0;
810
- top: 0;
811
- width: 12.5cqw;
812
- height: 12.5cqw;
813
- z-index: 10;
814
- pointer-events: none;
815
- translate: var(--x) var(--y);
816
- }
817
-
818
- .lifted .piece {
819
- display: block;
820
- width: 100%;
821
- height: 100%;
822
- transition: transform 120ms cubic-bezier(0.2, 0.8, 0.2, 1), filter 120ms cubic-bezier(0.2, 0.8, 0.2, 1);
823
- filter: drop-shadow(0 0 0 transparent);
824
- }
825
-
826
- .lifted.up .piece {
827
- transform: scale(1.1);
828
- filter: drop-shadow(0.375cqw 1cqw 0.75cqw var(--lift-shadow));
829
- }
830
-
831
- .lifted.up.touch .piece {
832
- transform: translateY(-75%) scale(1.25);
833
- }
834
-
835
- .lifted.back {
836
- transition: translate 180ms cubic-bezier(0.2, 0.8, 0.2, 1);
837
- }
838
-
839
- .lifted.back .piece {
840
- transform: none;
841
- filter: drop-shadow(0 0 0 transparent);
842
- transition-duration: 180ms;
843
- }
844
-
845
- /* A move not dragged slides from its square, in 12.5cqw a square, and a king in check rings like a bell struck (T-74) */
846
- .square.slide {
847
- z-index: 1;
848
- }
849
-
850
- /* The square's own piece only: one taken or fading on it keeps its own animation */
851
- .square.slide > .piece {
852
- animation: slide 220ms cubic-bezier(0.25, 0.8, 0.35, 1);
853
- }
854
-
855
- .square.shake > .piece {
856
- animation: ring 320ms cubic-bezier(0.3, 0, 0.2, 1) 200ms;
857
- }
858
-
859
- /* The piece taken stays under the one that takes it until it arrives */
860
- .square .taken-piece .piece {
861
- animation: taken 220ms step-end forwards;
862
- }
863
-
864
- /* A jump through the game (T-88): a piece no longer there fades, one that was not there appears */
865
- .square .gone-piece .piece {
866
- animation: taken 220ms forwards;
867
- }
868
-
869
- .square.appear > .piece {
870
- animation: appear 220ms;
871
- }
872
-
873
- @keyframes appear {
874
- from {
875
- opacity: 0;
876
- }
877
- }
878
-
879
- @keyframes taken {
880
- to {
881
- opacity: 0;
882
- }
883
- }
884
-
885
- @keyframes slide {
886
- from {
887
- translate: calc(var(--dx) * 12.5cqw) calc(var(--dy) * 12.5cqw);
888
- }
889
- }
890
-
891
- /* The hammer's blow, then a vibration that dies away: each swing smaller, eased at both ends */
892
- @keyframes ring {
893
- 12% {
894
- translate: -2.5% 0;
895
- }
896
-
897
- 34% {
898
- translate: 1.8% 0;
899
- }
900
-
901
- 56% {
902
- translate: -1.1% 0;
903
- }
904
-
905
- 78% {
906
- translate: 0.5% 0;
907
- }
908
- }
909
-
910
- @media (prefers-reduced-motion: reduce) {
911
- .lifted .piece,
912
- .lifted.back {
913
- transition: none;
914
- }
915
-
916
- .square.slide > .piece,
917
- .square.shake > .piece,
918
- .square.appear > .piece {
919
- animation: none;
920
- }
921
-
922
- .square .taken-piece,
923
- .square .gone-piece {
924
- display: none;
925
- }
926
- }
927
-
928
- /* The end of the game (T-77): the kings' badges and the loser's king laid down stay; the effects play once, when the game ends under the player's eyes */
929
- /* The king laid down keeps its size and lies on the base the other pieces stand on, in the middle of its square: it turns about the point that puts it
930
- there, which each set's drawing places */
931
- .square.fallen .piece {
932
- rotate: -90deg;
933
- transform-origin: var(--fallen-pivot, 50% 50%);
934
- }
935
-
936
- :root[data-set="nitida"] {
937
- --fallen-pivot: 53.7% 54.8%;
938
- }
939
-
940
- :root[data-set="torretta"] {
941
- --fallen-pivot: 52% 50.8%;
942
- }
943
-
944
- :root[data-set="cburnett"] {
945
- --fallen-pivot: 50.2% 50.9%;
946
- }
947
-
948
- .badge {
949
- position: absolute;
950
- top: 2.5%;
951
- right: 2.5%;
952
- z-index: 2;
953
- display: grid;
954
- place-items: center;
955
- width: clamp(14px, 3.8cqw, 30px);
956
- height: clamp(14px, 3.8cqw, 30px);
957
- border-radius: 50%;
958
- color: #fff;
959
- font-size: clamp(9px, 2.5cqw, 19px);
960
- font-weight: 800;
961
- line-height: 1;
962
- /* Edged in white, to stand out on any square, the red one too */
963
- box-shadow: 0 0 0 max(1.5px, 0.25cqw) #fff, 0 0.2cqw 0.6cqw rgba(0, 0, 0, 0.4);
964
- pointer-events: none;
965
- }
966
-
967
- .badge svg {
968
- width: 66%;
969
- height: 66%;
970
- fill: currentColor;
971
- stroke: currentColor;
972
- stroke-width: 2;
973
- stroke-linejoin: round;
974
- stroke-linecap: round;
975
- }
976
-
977
- .badge.crown {
978
- background: #e0a526;
979
- color: #3b2a00;
980
- }
981
-
982
- /* The mate white on the red square, edged in red */
983
- .badge.mate {
984
- background: #fff;
985
- color: #c81e1e;
986
- box-shadow: 0 0 0 max(1.5px, 0.25cqw) #c81e1e, 0 0.2cqw 0.6cqw rgba(0, 0, 0, 0.4);
987
- }
988
-
989
- .badge.flag {
990
- background: #4a4f57;
991
- }
992
-
993
- .badge.half {
994
- background: #69727d;
995
- }
996
-
997
- /* A move's badge (D-69, T-41): 16px beside a move, a third of a square in the corner of its arrival, edged in white as the kings' badges */
998
- .move-badge {
999
- flex: none;
1000
- width: 16px;
1001
- height: 16px;
1002
- vertical-align: -3px;
1003
- }
1004
-
1005
- .square .move-badge {
1006
- position: absolute;
1007
- top: 2.5%;
1008
- right: 2.5%;
1009
- z-index: 2;
1010
- width: clamp(16px, 4.25cqw, 30px);
1011
- height: clamp(16px, 4.25cqw, 30px);
1012
- border-radius: 50%;
1013
- box-shadow: 0 0 0 max(1.5px, 0.25cqw) #fff, 0 0.2cqw 0.6cqw rgba(0, 0, 0, 0.4);
1014
- pointer-events: none;
1015
- }
1016
-
1017
- /* With the king's badge on the same square, at the end, the move's stands beside it (Zoe, T-40) */
1018
- .square:has(.badge) .move-badge {
1019
- right: calc(2.5% + clamp(14px, 3.8cqw, 30px) + max(4px, 0.6cqw));
1020
- }
1021
-
1022
- /* Checkmate: the king rings with the check, its square fills with red from the edges, then it falls */
1023
- @media (prefers-reduced-motion: no-preference) {
1024
- .board.fresh.by-checkmate .square.mated {
1025
- background-image: none;
1026
- animation: mate-in 300ms cubic-bezier(0.2, 0.8, 0.2, 1) 450ms forwards;
1027
- }
1028
- }
1029
-
1030
- .board.fresh.by-checkmate .square.fallen .piece {
1031
- animation: ring 320ms cubic-bezier(0.3, 0, 0.2, 1) 200ms, fall 450ms 800ms backwards;
1032
- }
1033
-
1034
- /* A resignation: the king is laid down slowly, as a player lays theirs */
1035
- .board.fresh.by-resignation .square.fallen .piece {
1036
- animation: lay 1000ms cubic-bezier(0.45, 0, 0.55, 1) 250ms backwards;
1037
- }
1038
-
1039
- /* Stalemate: the king darts one way and the other, and finds no square */
1040
- .board.fresh.by-stalemate .square.stalled .piece {
1041
- animation: dart 700ms cubic-bezier(0.4, 0, 0.2, 1) 250ms;
1042
- }
1043
-
1044
- /* The other draws: both kings light up together */
1045
- .board.fresh:not(.by-stalemate) .square.drawn {
1046
- animation: draw-glow 1000ms ease-in-out 200ms;
1047
- }
1048
-
1049
- /* The badges come once the kings have taken the end */
1050
- .board.fresh .badge {
1051
- animation: badge-in 320ms cubic-bezier(0.3, 1.4, 0.5, 1) 800ms backwards;
1052
- }
1053
-
1054
- .board.fresh.by-checkmate .badge {
1055
- animation-delay: 1350ms;
1056
- }
1057
-
1058
- .board.fresh.by-resignation .badge {
1059
- animation-delay: 1200ms;
1060
- }
1061
-
1062
- .board.fresh.by-stalemate .badge {
1063
- animation-delay: 950ms;
1064
- }
1065
-
1066
- /* The player won: a narrow golden sheen crosses the board once, after the badges; a loss needs no more than the king and its badge */
1067
- .board.fresh.player-won::after {
1068
- content: "";
1069
- position: absolute;
1070
- inset: 0;
1071
- z-index: 3;
1072
- pointer-events: none;
1073
- background: linear-gradient(115deg, transparent 44%, rgba(255, 230, 150, 0.6) 50%, transparent 56%) 0 0 / 300% 100% no-repeat;
1074
- mix-blend-mode: screen;
1075
- animation: sheen 900ms cubic-bezier(0.45, 0, 0.55, 1) 1600ms backwards;
1076
- }
1077
-
1078
- @keyframes mate-in {
1079
- from {
1080
- box-shadow: inset 0 0 0 0 var(--mated);
1081
- }
1082
-
1083
- to {
1084
- box-shadow: inset 0 0 0 7cqw var(--mated);
1085
- }
1086
- }
1087
-
1088
- /* Falling, the king drops fast, bounces once off the board and settles */
1089
- @keyframes fall {
1090
- from {
1091
- rotate: 0deg;
1092
- animation-timing-function: cubic-bezier(0.55, 0, 1, 0.45);
1093
- }
1094
-
1095
- 45% {
1096
- rotate: -90deg;
1097
- animation-timing-function: cubic-bezier(0, 0.55, 0.45, 1);
1098
- }
1099
-
1100
- 68% {
1101
- rotate: -74deg;
1102
- animation-timing-function: cubic-bezier(0.55, 0, 1, 0.45);
1103
- }
1104
-
1105
- 86% {
1106
- rotate: -90deg;
1107
- animation-timing-function: cubic-bezier(0, 0.55, 0.45, 1);
1108
- }
1109
-
1110
- 94% {
1111
- rotate: -86deg;
1112
- animation-timing-function: ease-in;
1113
- }
1114
- }
1115
-
1116
- @keyframes lay {
1117
- from {
1118
- rotate: 0deg;
1119
- }
1120
- }
1121
-
1122
- @keyframes dart {
1123
- 20% {
1124
- translate: 6% -3%;
1125
- }
1126
-
1127
- 40%,
1128
- 80% {
1129
- translate: 0 0;
1130
- }
1131
-
1132
- 60% {
1133
- translate: -6% -3%;
1134
- }
1135
- }
1136
-
1137
- @keyframes draw-glow {
1138
- 40%,
1139
- 60% {
1140
- /* A ring in the skin's colour, much darker than its squares, to show on the light and the dark ones */
1141
- box-shadow: inset 0 0 0 0.6cqw color-mix(in oklab, var(--dark-square) 50%, #1d2733), inset 0 0 2.5cqw 0.4cqw color-mix(in oklab, var(--dark-square) 40%, transparent);
1142
- }
1143
- }
1144
-
1145
- @keyframes badge-in {
1146
- from {
1147
- scale: 0;
1148
- opacity: 0;
1149
- }
1150
- }
1151
-
1152
- @keyframes sheen {
1153
- from {
1154
- background-position: 100% 0;
1155
- }
1156
-
1157
- to {
1158
- background-position: 0 0;
1159
- }
1160
- }
1161
-
1162
- @media (prefers-reduced-motion: reduce) {
1163
- .board.fresh,
1164
- .board.fresh .square,
1165
- .board.fresh .piece,
1166
- .board.fresh .badge {
1167
- animation: none;
1168
- }
1169
-
1170
- .board.fresh::after {
1171
- display: none;
1172
- }
1173
- }
1174
-
1175
- /* The ranks and files grow with the board, as 13 points on 800, tucked into the corners the pieces leave free */
1176
- .coordinate {
1177
- position: absolute;
1178
- font-size: clamp(9px, 1.6cqw, 13px);
1179
- font-weight: 700;
1180
- line-height: 1;
1181
- pointer-events: none;
1182
- }
1183
-
1184
- .coordinate.rank {
1185
- top: 3%;
1186
- left: 4%;
1187
- }
1188
-
1189
- .coordinate.file {
1190
- right: 4%;
1191
- bottom: 2.5%;
1192
- }
1193
-
1194
- .square.light .coordinate,
1195
- .square.light .square-name {
1196
- color: var(--dark-square);
1197
- }
1198
-
1199
- .square.dark .coordinate,
1200
- .square.dark .square-name {
1201
- color: var(--light-square);
1202
- }
1203
-
1204
- /* The square's name in the corner of the file, under the pointer or the piece dragged, in its place on the bottom rank (T-76) */
1205
- .square-name {
1206
- position: absolute;
1207
- right: 4%;
1208
- bottom: 2.5%;
1209
- z-index: 2;
1210
- display: none;
1211
- font-size: clamp(9px, 1.6cqw, 13px);
1212
- font-weight: 700;
1213
- line-height: 1;
1214
- pointer-events: none;
1215
- }
1216
-
1217
- .square.over .square-name {
1218
- display: block;
1219
- }
1220
-
1221
- .square.over .coordinate.file {
1222
- visibility: hidden;
1223
- }
1224
-
1225
- @media (hover: hover) {
1226
- .square:hover .square-name {
1227
- display: block;
1228
- }
1229
-
1230
- .square:hover .coordinate.file {
1231
- visibility: hidden;
1232
- }
1233
- }
1234
-
1235
- .square .piece {
1236
- position: absolute;
1237
- inset: 0;
1238
- width: 100%;
1239
- height: 100%;
1240
- }
1241
-
1242
- /* The pieces: one shape each, in the colour of its side with a black edge (D-49) */
1243
- .piece {
1244
- --piece-edge-width: 6.5px;
1245
- }
1246
-
1247
- /* How much of its colours a piece keeps against the page: all of them, but on a board that is off (D-77). Opaque, so no square shows through it */
1248
- @property --kept {
1249
- syntax: "<percentage>";
1250
- inherits: true;
1251
- initial-value: 100%;
1252
- }
1253
-
1254
- .piece.white {
1255
- --piece-fill: color-mix(in oklab, var(--white-piece) var(--kept), var(--page));
1256
- --piece-edge: color-mix(in oklab, #000 var(--kept), var(--page));
1257
- }
1258
-
1259
- .piece.black {
1260
- --piece-fill: color-mix(in oklab, var(--black-piece) var(--kept), var(--page));
1261
- --piece-edge: color-mix(in oklab, #000 var(--kept), var(--page));
1262
- --piece-detail: color-mix(in oklab, var(--white-piece) var(--kept), var(--page));
1263
- }
1264
-
1265
- /* Why a move was refused (T-11): a bubble over the square it went to, its tail on the square; a ring on the piece that forbids it */
1266
- .notice {
1267
- --shift: -50%;
1268
- position: absolute;
1269
- z-index: 3;
1270
- left: calc((var(--column) + 0.5) * 12.5cqw);
1271
- top: calc(var(--row) * 12.5cqw);
1272
- transform: translate(var(--shift), calc(-100% - 8px));
1273
- display: flex;
1274
- align-items: center;
1275
- gap: 9px;
1276
- width: max-content;
1277
- max-width: min(78cqw, 340px);
1278
- margin: 0;
1279
- padding: 8px 12px;
1280
- border-radius: 7px;
1281
- /* Ink in both themes (T-91), as the arrows that explain */
1282
- background: var(--explain-ink);
1283
- color: #f4f6f9;
1284
- font-size: 13.5px;
1285
- line-height: 1.35;
1286
- box-shadow: var(--shadow);
1287
- pointer-events: none;
1288
- animation: notice-in 160ms ease-out;
1289
- }
1290
-
1291
- .notice::after {
1292
- content: "";
1293
- position: absolute;
1294
- left: calc(-1 * var(--shift) - 6px);
1295
- top: 100%;
1296
- border: 6px solid transparent;
1297
- border-top-color: var(--explain-ink);
1298
- }
1299
-
1300
- /* The kind of reason (T-91): a light tile with the piece, a pin, a bar, castling; the player's king on red */
1301
- .explain-icon {
1302
- flex: none;
1303
- display: grid;
1304
- place-items: center;
1305
- width: 28px;
1306
- height: 28px;
1307
- padding: 2px;
1308
- border-radius: 6px;
1309
- background: #e3e9f0;
1310
- }
1311
-
1312
- .explain-icon.king {
1313
- background: #f3c4c4;
1314
- }
1315
-
1316
- .explain-icon .piece {
1317
- width: 100%;
1318
- height: 100%;
1319
- }
1320
-
1321
- .explain-icon svg {
1322
- width: 20px;
1323
- height: 20px;
1324
- fill: none;
1325
- stroke: var(--explain-ink);
1326
- stroke-width: 2.2;
1327
- stroke-linecap: round;
1328
- stroke-linejoin: round;
1329
- }
1330
-
1331
- .explain-icon .bar {
1332
- stroke-width: 3;
1333
- }
1334
-
1335
- /* The arrow that explains a refused move: ink, apart from the player's orange ones */
1336
- .arrows.explain {
1337
- opacity: 0.78;
1338
- }
1339
-
1340
- .arrows.explain path {
1341
- stroke: var(--explain-ink);
1342
- }
1343
-
1344
- .arrows.explain polygon {
1345
- fill: var(--explain-ink);
1346
- }
1347
-
1348
- .notice.start {
1349
- --shift: 0%;
1350
- left: calc(var(--column) * 12.5cqw + 4px);
1351
- }
1352
-
1353
- .notice.start::after {
1354
- left: calc(6.25cqw - 10px);
1355
- }
1356
-
1357
- .notice.end {
1358
- --shift: -100%;
1359
- left: calc((var(--column) + 1) * 12.5cqw - 4px);
1360
- }
1361
-
1362
- .notice.end::after {
1363
- left: auto;
1364
- right: calc(6.25cqw - 10px);
1365
- }
1366
-
1367
- .notice.below {
1368
- top: calc((var(--row) + 1) * 12.5cqw);
1369
- transform: translate(var(--shift), 8px);
1370
- }
1371
-
1372
- .notice.below::after {
1373
- top: auto;
1374
- bottom: 100%;
1375
- border-top-color: transparent;
1376
- border-bottom-color: var(--explain-ink);
1377
- }
1378
-
1379
- /* Where the bubble hides neither the culprit nor the arrow's point (T-91, Zoe): under the whole board on a phone, beside the piece on a wide board */
1380
- .notice.under-board {
1381
- top: 100cqw;
1382
- transform: translate(var(--shift), 8px);
1383
- }
1384
-
1385
- .notice.under-board::after {
1386
- top: auto;
1387
- bottom: 100%;
1388
- border-top-color: transparent;
1389
- border-bottom-color: var(--explain-ink);
1390
- }
1391
-
1392
- .notice.right,
1393
- .notice.left {
1394
- top: calc((var(--row) + 0.5) * 12.5cqw);
1395
- max-width: min(calc((var(--room) * 12.5cqw) - 12px), 340px);
1396
- }
1397
-
1398
- .notice.right {
1399
- --room: calc(7 - var(--column));
1400
- left: calc((var(--column) + 1) * 12.5cqw + 8px);
1401
- transform: translateY(-50%);
1402
- }
1403
-
1404
- .notice.left {
1405
- --room: var(--column);
1406
- left: calc(var(--column) * 12.5cqw - 8px);
1407
- transform: translate(-100%, -50%);
1408
- }
1409
-
1410
- .notice.right::after,
1411
- .notice.left::after {
1412
- top: calc(50% - 6px);
1413
- }
1414
-
1415
- .notice.right::after {
1416
- left: auto;
1417
- right: 100%;
1418
- border-top-color: transparent;
1419
- border-right-color: var(--explain-ink);
1420
- }
1421
-
1422
- .notice.left::after {
1423
- left: 100%;
1424
- right: auto;
1425
- border-top-color: transparent;
1426
- border-left-color: var(--explain-ink);
1427
- }
1428
-
1429
- /* On a phone's board the bubble takes its width, in two lines, its tail on the piece's column */
1430
- @container (max-width: 519px) {
1431
- .board-wrap .notice:not(.centre) {
1432
- left: 4px;
1433
- width: calc(100cqw - 8px);
1434
- max-width: none;
1435
- --shift: 0%;
1436
- }
1437
-
1438
- .board-wrap .notice:not(.centre)::after {
1439
- left: calc((var(--column) + 0.5) * 12.5cqw - 10px);
1440
- right: auto;
1441
- }
1442
- }
1443
-
1444
- .notice.centre {
1445
- left: 50%;
1446
- top: 50%;
1447
- transform: translate(-50%, -50%);
1448
- }
1449
-
1450
- .notice.centre::after {
1451
- content: none;
1452
- }
1453
-
1454
- @keyframes notice-in {
1455
- from {
1456
- opacity: 0;
1457
- }
1458
- }
1459
-
1460
- /* The choice of the piece a pawn becomes (T-11): four round buttons in a column from its square, over a shade */
1461
- .promotion {
1462
- position: absolute;
1463
- left: 0;
1464
- top: 0;
1465
- z-index: 4;
1466
- width: 100%;
1467
- aspect-ratio: 1;
1468
- }
1469
-
1470
- .promotion-shade {
1471
- position: absolute;
1472
- inset: 0;
1473
- border-radius: var(--radius);
1474
- background: rgba(0, 0, 0, 0.35);
1475
- }
1476
-
1477
- .promotion-piece {
1478
- position: absolute;
1479
- left: calc(var(--column) * 12.5cqw);
1480
- top: calc(var(--row) * 12.5cqw);
1481
- width: 12.5cqw;
1482
- height: 12.5cqw;
1483
- padding: 0.6cqw;
1484
- border: 0;
1485
- border-radius: 50%;
1486
- background: var(--light-square);
1487
- box-shadow: var(--shadow);
1488
- cursor: pointer;
1489
- }
1490
-
1491
- .promotion-piece:hover {
1492
- box-shadow: var(--shadow), inset 0 0 0 max(2px, 0.625cqw) var(--hover-edge);
1493
- }
1494
-
1495
- /* White inside dark reads on every square and every theme. */
1496
- .promotion-piece:focus-visible,
1497
- .square:focus-visible {
1498
- outline: none;
1499
- box-shadow: inset 0 0 0 2px #fff, inset 0 0 0 4.5px #1d2733;
1500
- }
1501
-
1502
- .promotion-piece .piece {
1503
- display: block;
1504
- width: 100%;
1505
- height: 100%;
1506
- }
1507
-
1508
- .square.culprit {
1509
- box-shadow: inset 0 0 0 max(2.5px, 0.5cqw) var(--explain-ink), inset 0 0 0 calc(max(2.5px, 0.5cqw) + 1.5px) rgba(255, 255, 255, 0.85);
1510
- }
1511
-
1512
- /* The players' cards */
1513
- .card {
1514
- background: var(--card);
1515
- border: 1px solid var(--line);
1516
- border-radius: var(--radius);
1517
- padding: 12px 14px;
1518
- box-shadow: var(--shadow);
1519
- }
1520
-
1521
- /* The picture stays at the card's top left, however many lines the card has; the clock in the middle */
1522
- .player-line {
1523
- display: flex;
1524
- align-items: flex-start;
1525
- gap: 12px;
1526
- }
1527
-
1528
- .player-line > .clock {
1529
- align-self: center;
1530
- }
1531
-
1532
- .player-line > svg {
1533
- flex: none;
1534
- }
1535
-
1536
- .who {
1537
- flex: 1;
1538
- min-width: 0;
1539
- line-height: 1.25;
1540
- }
1541
-
1542
- .name {
1543
- font-weight: 600;
1544
- }
1545
-
1546
- .note {
1547
- color: var(--soft);
1548
- font-size: 13px;
1549
- font-weight: 400;
1550
- }
1551
-
1552
- /* The AI's name, which the player may choose long, stays on one line: whole in its tooltip */
1553
- .player.ai .name {
1554
- overflow: hidden;
1555
- white-space: nowrap;
1556
- text-overflow: ellipsis;
1557
- }
1558
-
1559
- /* Under the AI's name, the model it plays with (D-82): one line, whole in its tooltip */
1560
- .player .signed {
1561
- color: var(--soft);
1562
- font-size: 12px;
1563
- overflow: hidden;
1564
- white-space: nowrap;
1565
- text-overflow: ellipsis;
1566
- }
1567
-
1568
- .turn {
1569
- color: var(--accent);
1570
- font-weight: 600;
1571
- white-space: nowrap;
1572
- }
1573
-
1574
- /* A player's clock, in Zoe's pill (T-37): the running one in the accent colour, red in the last seconds */
1575
- .player .clock {
1576
- flex: none;
1577
- padding: 4px 10px;
1578
- border-radius: 7px;
1579
- background: var(--page);
1580
- font-size: 20px;
1581
- font-weight: 600;
1582
- font-variant-numeric: lining-nums tabular-nums;
1583
- letter-spacing: 0.01em;
1584
- }
1585
-
1586
- .player .clock.running {
1587
- background: var(--accent);
1588
- color: var(--on-accent);
1589
- }
1590
-
1591
- .player .clock.low {
1592
- color: var(--low-time);
1593
- }
1594
-
1595
- .player .clock.running.low {
1596
- background: var(--low-time);
1597
- color: #fff;
1598
- }
1599
-
1600
- /* The clocks wait for the player (Zoe): the button that starts them takes a line of the player's card, under the clock it starts, off the board's squares;
1601
- between games the new game takes the same line, in the clock's place (D-77) */
1602
- .player-line:has(> .start-clocks, > .next-game) {
1603
- flex-wrap: wrap;
1604
- row-gap: 10px;
1605
- }
1606
-
1607
- .start-clocks,
1608
- .next-game {
1609
- flex: 1 0 100%;
1610
- justify-content: center;
1611
- padding: 8px 14px;
1612
- font-size: 15px;
1613
- font-weight: 600;
1614
- }
1615
-
1616
- .start-clocks .icon {
1617
- width: 14px;
1618
- height: 14px;
1619
- fill: currentColor;
1620
- }
1621
-
1622
- .next-game .icon {
1623
- width: 16px;
1624
- height: 16px;
1625
- stroke-width: 2.2;
1626
- }
1627
-
1628
- /* Between games a card has no side under the name (D-77): the name alone, in the middle of the picture */
1629
- .player-line > .who:not(:has(.note)) {
1630
- align-self: center;
1631
- }
1632
-
1633
- .player-line > .who:not(:has(.note)) .taken:empty {
1634
- display: none;
1635
- }
1636
-
1637
- /* The pieces taken overlap within a kind, close enough that all fifteen and the score stay on one line */
1638
- .taken {
1639
- display: flex;
1640
- flex-wrap: nowrap;
1641
- align-items: center;
1642
- gap: 0;
1643
- white-space: nowrap;
1644
- min-height: 20px;
1645
- margin-top: 3px;
1646
- }
1647
-
1648
- .taken .group {
1649
- display: inline-flex;
1650
- }
1651
-
1652
- /* A kind starts close to the one before: the piece's own margin is the gap */
1653
- .taken .group + .group {
1654
- margin-left: -3px;
1655
- }
1656
-
1657
- /* The pieces taken are the set's small ones (T-94), whose colours and edges are their own */
1658
- .taken .piece {
1659
- width: 20px;
1660
- height: 20px;
1661
- }
1662
-
1663
- /* Pawns comb tight; the other pieces show more of themselves, a pair of rooks or bishops two pieces still (Zoe, T-40) */
1664
- .taken .piece + .piece {
1665
- margin-left: -11px;
1666
- }
1667
-
1668
- .taken .pawns .piece + .piece {
1669
- margin-left: -15px;
1670
- }
1671
-
1672
- .balance {
1673
- flex: none;
1674
- margin-left: 2px;
1675
- color: var(--soft);
1676
- font-size: 13px;
1677
- font-weight: 600;
1678
- }
1679
-
1680
- /* The player's face, masked by a circle */
1681
- .avatar {
1682
- clip-path: circle(50%);
1683
- }
1684
-
1685
- .avatar .back {
1686
- fill: var(--say);
1687
- }
1688
-
1689
- .avatar .shirt {
1690
- fill: var(--accent);
1691
- }
1692
-
1693
- .avatar .skin {
1694
- fill: #f1c6a0;
1695
- }
1696
-
1697
- .avatar .hair {
1698
- fill: #4a3426;
1699
- }
1700
-
1701
- .avatar .eye {
1702
- fill: #2b2420;
1703
- }
1704
-
1705
- .avatar .smile {
1706
- fill: none;
1707
- stroke: #2b2420;
1708
- stroke-width: 1.6;
1709
- stroke-linecap: round;
1710
- }
1711
-
1712
- /* The Torretta, whose eyes blink now and then, and its moods (D-70): a new face that pops in, never fading out, a red light when worried, out when sad, a light that breathes when
1713
- thoughtful */
1714
- .torretta .antenna {
1715
- fill: none;
1716
- stroke: var(--torretta-shade);
1717
- stroke-width: 4;
1718
- stroke-linecap: round;
1719
- }
1720
-
1721
- .torretta .light {
1722
- fill: var(--torretta-light);
1723
- transition: fill 0.2s;
1724
- }
1725
-
1726
- .torretta.mood-worried .light {
1727
- fill: var(--torretta-alarm);
1728
- }
1729
-
1730
- .torretta.mood-thoughtful .light {
1731
- animation: ponder 2.4s ease-in-out infinite;
1732
- }
1733
-
1734
- .torretta.mood-sad .light {
1735
- fill: var(--torretta-shade);
1736
- }
1737
-
1738
- @keyframes ponder {
1739
- 50% {
1740
- fill: var(--torretta-ponder);
1741
- }
1742
- }
1743
-
1744
- .torretta .expression.changed {
1745
- transform-box: fill-box;
1746
- transform-origin: center;
1747
- animation: face-in 0.16s ease-out;
1748
- }
1749
-
1750
- @keyframes face-in {
1751
- from {
1752
- transform: scale(0.8);
1753
- }
1754
- }
1755
-
1756
- .torretta .shade {
1757
- fill: var(--torretta-shade);
1758
- }
1759
-
1760
- .torretta .body {
1761
- fill: var(--torretta-body);
1762
- }
1763
-
1764
- .torretta .screen {
1765
- fill: var(--torretta-screen);
1766
- }
1767
-
1768
- .torretta .eyes,
1769
- .torretta .mouth {
1770
- fill: var(--torretta-face);
1771
- }
1772
-
1773
- .torretta .expression .line,
1774
- .torretta .brows {
1775
- fill: none;
1776
- stroke: var(--torretta-face);
1777
- stroke-width: 3.4;
1778
- stroke-linecap: round;
1779
- stroke-linejoin: round;
1780
- }
1781
-
1782
- .torretta .eyes {
1783
- transform-box: fill-box;
1784
- transform-origin: center;
1785
- animation: blink 6s infinite;
1786
- }
1787
-
1788
- @keyframes blink {
1789
- 0%,
1790
- 95%,
1791
- 100% {
1792
- transform: scaleY(1);
1793
- }
1794
-
1795
- 97% {
1796
- transform: scaleY(0.1);
1797
- }
1798
- }
1799
-
1800
- @media (prefers-reduced-motion: reduce) {
1801
- .torretta .eyes,
1802
- .torretta .expression.changed,
1803
- .torretta.mood-thoughtful .light {
1804
- animation: none;
1805
- }
1806
-
1807
- .torretta .light {
1808
- transition: none;
1809
- }
1810
- }
1811
-
1812
- /* The bubbles: the AI's under its card, the tail under the Torretta's centre (14 px of padding, 48 px picture), and the player's above their box */
1813
- .says,
1814
- .sent {
1815
- list-style: none;
1816
- margin: 0;
1817
- padding: 0;
1818
- display: flex;
1819
- flex-direction: column;
1820
- gap: 6px;
1821
- }
1822
-
1823
- /* The bubbles never scroll: those that do not fit whole are hidden, and on the side away from the card they overflow toward */
1824
- .says {
1825
- overflow: hidden;
1826
- min-height: 0;
1827
- padding-top: 12px;
1828
- }
1829
-
1830
- .says:empty {
1831
- display: none;
1832
- }
1833
-
1834
- .say {
1835
- position: relative;
1836
- background: var(--say);
1837
- color: var(--say-ink);
1838
- border-radius: var(--bubble);
1839
- padding: 10px 13px;
1840
- font-size: 14.5px;
1841
- line-height: 1.45;
1842
- text-wrap: pretty;
1843
- overflow-wrap: anywhere;
1844
- }
1845
-
1846
- .say:first-child::before {
1847
- content: "";
1848
- position: absolute;
1849
- left: 29px;
1850
- top: -10px;
1851
- border: 10px solid transparent;
1852
- border-top: 0;
1853
- border-bottom-color: var(--say);
1854
- }
1855
-
1856
- .sent {
1857
- align-items: flex-end;
1858
- justify-content: flex-end;
1859
- margin-bottom: 8px;
1860
- overflow: hidden;
1861
- min-height: 0;
1862
- }
1863
-
1864
- .sent li {
1865
- display: flex;
1866
- flex-direction: column;
1867
- align-items: flex-end;
1868
- max-width: 88%;
1869
- }
1870
-
1871
- .said {
1872
- margin: 0;
1873
- background: var(--accent);
1874
- color: var(--on-accent);
1875
- border-radius: var(--bubble) var(--bubble) 4px var(--bubble);
1876
- padding: 8px 12px;
1877
- font-size: 14.5px;
1878
- line-height: 1.4;
1879
- text-wrap: pretty;
1880
- overflow-wrap: anywhere;
1881
- }
1882
-
1883
- .status {
1884
- display: inline-flex;
1885
- align-items: center;
1886
- gap: 3px;
1887
- margin-top: 3px;
1888
- font-size: 12px;
1889
- color: var(--soft);
1890
- }
1891
-
1892
- .status .icon {
1893
- width: 15px;
1894
- height: 15px;
1895
- stroke-width: 2;
1896
- }
1897
-
1898
- .status.read {
1899
- color: var(--accent);
1900
- font-weight: 600;
1901
- }
1902
-
1903
- /* The box the player writes in: a bubble whose tail points at their picture */
1904
- .compose {
1905
- position: relative;
1906
- background: var(--card);
1907
- border: 1px solid var(--line);
1908
- border-radius: var(--bubble);
1909
- padding: 8px 8px 8px 12px;
1910
- margin: 0 0 12px;
1911
- box-shadow: var(--shadow);
1912
- }
1913
-
1914
- .compose::after {
1915
- content: "";
1916
- position: absolute;
1917
- left: 31px;
1918
- bottom: -8px;
1919
- width: 14px;
1920
- height: 14px;
1921
- background: var(--card);
1922
- border-right: 1px solid var(--line);
1923
- border-bottom: 1px solid var(--line);
1924
- transform: rotate(45deg);
1925
- border-bottom-right-radius: 3px;
1926
- }
1927
-
1928
- .compose:focus-within,
1929
- .compose:focus-within::after {
1930
- border-color: var(--accent);
1931
- }
1932
-
1933
- .compose textarea {
1934
- display: block;
1935
- width: 100%;
1936
- resize: none;
1937
- border: 0;
1938
- background: none;
1939
- padding: 2px 0;
1940
- font-size: 14.5px;
1941
- line-height: 1.45;
1942
- min-height: 44px;
1943
- max-height: 96px;
1944
- field-sizing: content;
1945
- outline: none;
1946
- }
1947
-
1948
- .compose textarea::placeholder {
1949
- color: var(--soft);
1950
- }
1951
-
1952
- .foot {
1953
- display: flex;
1954
- align-items: center;
1955
- justify-content: space-between;
1956
- gap: 8px;
1957
- margin-top: 4px;
1958
- }
1959
-
1960
- .hint,
1961
- .count {
1962
- font-size: 12px;
1963
- color: var(--soft);
1964
- }
1965
-
1966
- .count {
1967
- font-variant-numeric: tabular-nums;
1968
- }
1969
-
1970
- .send {
1971
- display: inline-flex;
1972
- align-items: center;
1973
- gap: 5px;
1974
- border: 0;
1975
- border-radius: 8px;
1976
- padding: 6px 10px 6px 12px;
1977
- background: var(--accent);
1978
- color: var(--on-accent);
1979
- font-size: 13.5px;
1980
- font-weight: 600;
1981
- }
1982
-
1983
- .send .icon {
1984
- width: 15px;
1985
- height: 15px;
1986
- stroke-width: 2;
1987
- }
1988
-
1989
- .send:disabled {
1990
- background: var(--quote);
1991
- color: var(--soft);
1992
- cursor: default;
1993
- }
1994
-
1995
- .limit {
1996
- margin: 0 4px 6px 0;
1997
- padding: 7px 10px;
1998
- border-radius: 8px;
1999
- background: var(--warn-back);
2000
- color: var(--ink);
2001
- font-size: 13px;
2002
- line-height: 1.4;
2003
- }
2004
-
2005
- .limit:empty {
2006
- display: none;
2007
- }
2008
-
2009
- /* Turned round: the player on top, the AI below; the tails turn with them */
2010
- .flipped .talk,
2011
- .flipped .ai-block,
2012
- .flipped .you-block {
2013
- flex-direction: column-reverse;
2014
- }
2015
-
2016
- .flipped .says {
2017
- justify-content: flex-end;
2018
- padding: 0 0 12px;
2019
- }
2020
-
2021
- .flipped .say:first-child::before {
2022
- content: none;
2023
- }
2024
-
2025
- .flipped .say:last-child::after {
2026
- content: "";
2027
- position: absolute;
2028
- left: 29px;
2029
- bottom: -10px;
2030
- border: 10px solid transparent;
2031
- border-bottom: 0;
2032
- border-top-color: var(--say);
2033
- }
2034
-
2035
- .flipped .compose {
2036
- margin: 12px 0 0;
2037
- }
2038
-
2039
- .flipped .compose::after {
2040
- bottom: auto;
2041
- top: -8px;
2042
- transform: rotate(225deg);
2043
- }
2044
-
2045
- .flipped .sent {
2046
- justify-content: flex-start;
2047
- margin: 8px 0 0;
2048
- }
2049
-
2050
- /* The game's column, folded from the header */
2051
- .side {
2052
- grid-area: side;
2053
- display: flex;
2054
- flex-direction: column;
2055
- gap: var(--between);
2056
- contain: size;
2057
- min-height: 0;
2058
- }
2059
-
2060
- /* The game's card, as tall as a player's across the board: a little board where the player's card has their face, round people, a square game */
2061
- .game-card {
2062
- margin: 0;
2063
- min-height: 74px;
2064
- display: flex;
2065
- align-items: center;
2066
- gap: 12px;
2067
- font-size: 13px;
2068
- }
2069
-
2070
- .tile {
2071
- position: relative;
2072
- flex: none;
2073
- display: grid;
2074
- place-items: center;
2075
- width: 48px;
2076
- height: 48px;
2077
- border-radius: var(--radius);
2078
- /* A board of four squares in the skin's colours, the dark one at the bottom left as on a board */
2079
- background: conic-gradient(var(--dark-square) 0 25%, var(--light-square) 0 50%, var(--dark-square) 0 75%, var(--light-square) 0);
2080
- overflow: hidden;
2081
- }
2082
-
2083
- .tile .piece {
2084
- --piece-edge-width: 7px;
2085
- width: 40px;
2086
- height: 40px;
2087
- }
2088
-
2089
- /* The king to move, edged in the accent like the coin of whoever moves */
2090
- .tile.moving {
2091
- box-shadow: 0 0 0 2px var(--card), 0 0 0 4px var(--accent);
2092
- }
2093
-
2094
- /* At the end both kings: side by side in a draw, the loser laid at the winner's feet */
2095
- .tile.over {
2096
- display: flex;
2097
- justify-content: center;
2098
- align-items: flex-end;
2099
- padding-bottom: 4px;
2100
- }
2101
-
2102
- .tile.over .piece {
2103
- --piece-edge-width: 8px;
2104
- width: 30px;
2105
- height: 30px;
2106
- }
2107
-
2108
- .tile.draw .piece + .piece {
2109
- margin-left: -12px;
2110
- }
2111
-
2112
- .tile.win > span {
2113
- position: absolute;
2114
- display: grid;
2115
- }
2116
-
2117
- .tile.win .piece {
2118
- width: 100%;
2119
- height: 100%;
2120
- }
2121
-
2122
- .tile.win .up {
2123
- right: 5px;
2124
- bottom: 4px;
2125
- width: 28px;
2126
- height: 28px;
2127
- }
2128
-
2129
- /* Laid down, the king is as wide as it was tall: it drops 5px to rest where the other stands */
2130
- .tile.win .down {
2131
- left: 4px;
2132
- bottom: -1px;
2133
- width: 24px;
2134
- height: 24px;
2135
- rotate: -90deg;
2136
- }
2137
-
2138
- .game-card .what {
2139
- min-width: 0;
2140
- line-height: 1.25;
2141
- }
2142
-
2143
- .game-card p {
2144
- margin: 0;
2145
- }
2146
-
2147
- .game-card .head,
2148
- .game-card .when {
2149
- color: var(--soft);
2150
- }
2151
-
2152
- .game-card .big {
2153
- color: var(--ink);
2154
- font-size: 20px;
2155
- font-weight: 600;
2156
- font-variant-numeric: tabular-nums;
2157
- letter-spacing: -0.01em;
2158
- }
2159
-
2160
- .game-card .when {
2161
- margin-top: 2px;
2162
- }
2163
-
2164
- /* The game ended under the player's eyes: once the board has shown it, with the kings' badges, the card lights up in the accent and fades back */
2165
- .game-card.lit {
2166
- animation: lit 1200ms ease-out 1350ms;
2167
- }
2168
-
2169
- @keyframes lit {
2170
- 20% {
2171
- box-shadow: 0 0 0 2px var(--accent), 0 0 18px color-mix(in srgb, var(--accent) 55%, transparent);
2172
- }
2173
- }
2174
-
2175
- .opening {
2176
- display: grid;
2177
- gap: 2px;
2178
- font-size: 13px;
2179
- }
2180
-
2181
- .opening p {
2182
- margin: 0;
2183
- }
2184
-
2185
- .opening .family {
2186
- display: flex;
2187
- align-items: center;
2188
- gap: 7px;
2189
- }
2190
-
2191
- .opening .book {
2192
- display: grid;
2193
- align-self: center;
2194
- color: var(--accent);
2195
- }
2196
-
2197
- .opening .book .icon {
2198
- width: 21px;
2199
- height: 21px;
2200
- stroke-width: 2.3;
2201
- }
2202
-
2203
- .opening .book.out {
2204
- color: var(--ink);
2205
- }
2206
-
2207
- .opening .variation {
2208
- color: var(--ink);
2209
- }
2210
-
2211
- .opening .out {
2212
- color: var(--soft);
2213
- font-size: 12px;
2214
- }
2215
-
2216
- /* A game in analysis (D-69): the AI's word on the whole game above the moves, and its note on the move shown in the talk, under the Torretta */
2217
- .review {
2218
- display: grid;
2219
- gap: 4px;
2220
- font-size: 13.5px;
2221
- line-height: 1.45;
2222
- }
2223
-
2224
- .review.waiting {
2225
- display: flex;
2226
- align-items: center;
2227
- gap: 8px;
2228
- margin: 0;
2229
- color: var(--soft);
2230
- }
2231
-
2232
- .review ul {
2233
- margin: 0;
2234
- padding-left: 18px;
2235
- }
2236
-
2237
- /* In analysis nothing in the talk gives way: on a short screen the talk scrolls whole */
2238
- .talk.studied {
2239
- overflow-y: auto;
2240
- }
2241
-
2242
- .talk.studied > section,
2243
- .talk.studied > section > * {
2244
- flex: none;
2245
- }
2246
-
2247
- .spinner {
2248
- flex: none;
2249
- width: 14px;
2250
- height: 14px;
2251
- border: 2px solid color-mix(in srgb, var(--accent) 25%, transparent);
2252
- border-top-color: var(--accent);
2253
- border-radius: 50%;
2254
- animation: spin 900ms linear infinite;
2255
- }
2256
-
2257
- @keyframes spin {
2258
- to {
2259
- transform: rotate(360deg);
2260
- }
2261
- }
2262
-
2263
- @media (prefers-reduced-motion: reduce) {
2264
- .spinner {
2265
- animation-duration: 3s;
2266
- }
2267
- }
2268
-
2269
- /* The badges of a side's moves, in its card under the pieces taken */
2270
- .badge-counts {
2271
- display: flex;
2272
- flex-wrap: wrap;
2273
- gap: 4px 10px;
2274
- list-style: none;
2275
- margin: 6px 0 0;
2276
- padding: 0;
2277
- font-size: 13px;
2278
- }
2279
-
2280
- .badge-counts li {
2281
- display: inline-flex;
2282
- align-items: center;
2283
- gap: 4px;
2284
- }
2285
-
2286
- .review p,
2287
- .ai-note p {
2288
- margin: 0;
2289
- }
2290
-
2291
- .review .head {
2292
- display: flex;
2293
- align-items: center;
2294
- gap: 6px;
2295
- color: var(--soft);
2296
- font-size: 12px;
2297
- }
2298
-
2299
- .ai-note {
2300
- display: grid;
2301
- gap: 6px;
2302
- margin-top: 12px;
2303
- }
2304
-
2305
- .ai-note .who {
2306
- display: flex;
2307
- align-items: center;
2308
- gap: 8px;
2309
- color: var(--soft);
2310
- font-size: 13px;
2311
- }
2312
-
2313
- /* Who made the analysis, signed under the Torretta's name in the Torretta's height (D-81, Zoe's sketch A) */
2314
- .ai-note .signed {
2315
- display: flex;
2316
- flex-direction: column;
2317
- min-width: 0;
2318
- line-height: 1.25;
2319
- }
2320
-
2321
- .ai-note .signed small {
2322
- font-size: 12px;
2323
- overflow-wrap: anywhere;
2324
- }
2325
-
2326
- /* Only the note's last bubble has a tail, pointing down at the Torretta beside the AI's name, the board turned round or not */
2327
- .ai-note > .say::before,
2328
- .ai-note > .say::after {
2329
- content: none;
2330
- }
2331
-
2332
- .ai-note > .say:has(+ .who)::after {
2333
- content: "";
2334
- position: absolute;
2335
- left: 8px;
2336
- bottom: -9px;
2337
- border: 10px solid transparent;
2338
- border-bottom: 0;
2339
- border-top-color: var(--say);
2340
- }
2341
-
2342
- .ai-note > .say + .who {
2343
- margin-top: 4px;
2344
- }
2345
-
2346
- /* In analysis the board turned round changes which side's card is on top, never the order of the talk */
2347
- .flipped .talk.studied,
2348
- .flipped .talk.studied > section {
2349
- flex-direction: column;
2350
- }
2351
-
2352
- .move-note .head {
2353
- display: flex;
2354
- align-items: center;
2355
- gap: 6px;
2356
- }
2357
-
2358
- /* The note is the bubble's content: in the bubble's own ink, not the soft one of a side note (Zoe, T-40) */
2359
- /* The AI's judgment of the player's last move, with the helps on (D-78): a line that opens on its note */
2360
- .move-note.judged summary {
2361
- cursor: pointer;
2362
- list-style: none;
2363
- }
2364
-
2365
- .move-note.judged summary::-webkit-details-marker {
2366
- display: none;
2367
- }
2368
-
2369
- .move-note .note {
2370
- display: block;
2371
- margin-top: 4px;
2372
- color: var(--say-ink);
2373
- font-size: 14.5px;
2374
- }
2375
-
2376
- /* The words the AI put in bold, in the titles' colour; the squares and moves in its words in the accent too, to find on the board */
2377
- .say b {
2378
- color: var(--ink);
2379
- font-weight: 700;
2380
- }
2381
-
2382
- .say .on-board {
2383
- color: var(--accent);
2384
- }
2385
-
2386
- /* What the colours drawn with the note mean, the ones it uses */
2387
- .move-note .legend {
2388
- display: flex;
2389
- flex-wrap: wrap;
2390
- gap: 2px 12px;
2391
- margin-top: 6px;
2392
- color: var(--soft);
2393
- font-size: 12px;
2394
- }
2395
-
2396
- .move-note .legend > span {
2397
- display: inline-flex;
2398
- align-items: center;
2399
- gap: 5px;
2400
- }
2401
-
2402
- .move-note .legend i {
2403
- width: 14px;
2404
- height: 3px;
2405
- border-radius: 2px;
2406
- background: var(--ring);
2407
- }
2408
-
2409
- .legend .green {
2410
- --ring: #15a34a;
2411
- }
2412
-
2413
- .legend .red {
2414
- --ring: #dc2626;
2415
- }
2416
-
2417
- .legend .yellow {
2418
- --ring: #eab308;
2419
- }
2420
-
2421
- .legend .blue {
2422
- --ring: #2563eb;
2423
- }
2424
-
2425
- /* The move's number, which the list far below gives on a phone */
2426
- .move-note .move-number {
2427
- display: none;
2428
- margin-right: 2px;
2429
- color: var(--soft);
2430
- font-size: 12px;
2431
- font-weight: 400;
2432
- }
2433
-
2434
- .board-steps,
2435
- .board-map {
2436
- display: none;
2437
- }
2438
-
2439
- .app.folded .side {
2440
- visibility: hidden;
2441
- transition: visibility 0s 200ms;
2442
- }
2443
-
2444
- /* Positioned, so that the moves' hidden names scroll with the list instead of stretching the page */
2445
- .moves {
2446
- position: relative;
2447
- flex: 1;
2448
- min-height: 90px;
2449
- /* It scrolls with no scrollbar, kept on the move shown */
2450
- overflow: hidden auto;
2451
- scrollbar-width: none;
2452
- padding: 8px 10px;
2453
- font-size: 14px;
2454
- }
2455
-
2456
- .moves ol {
2457
- list-style: none;
2458
- margin: 0;
2459
- padding: 0;
2460
- }
2461
-
2462
- .moves li {
2463
- display: grid;
2464
- grid-template-columns: 30px 1fr 1fr;
2465
- padding: 3px 6px;
2466
- border-radius: 5px;
2467
- }
2468
-
2469
- .moves li:nth-child(even) {
2470
- background: var(--page);
2471
- }
2472
-
2473
- .moves .number {
2474
- color: var(--soft);
2475
- }
2476
-
2477
- /* A move is a button that shows it on the board (T-88) */
2478
- .moves .ply {
2479
- justify-self: start;
2480
- display: inline-flex;
2481
- align-items: center;
2482
- gap: 4px;
2483
- padding: 0 3px;
2484
- margin-left: -3px;
2485
- background: none;
2486
- border: 0;
2487
- border-radius: 3px;
2488
- color: inherit;
2489
- font: inherit;
2490
- cursor: pointer;
2491
- }
2492
-
2493
- .moves .ply:hover {
2494
- background: color-mix(in srgb, var(--accent) 14%, transparent);
2495
- }
2496
-
2497
- .moves .current {
2498
- font-weight: 700;
2499
- box-shadow: inset 0 -2px 0 var(--accent);
2500
- }
2501
-
2502
- /* The buttons that step through the moves, under them as on Lichess and chess.com */
2503
- .steps {
2504
- display: flex;
2505
- gap: 4px;
2506
- padding: 4px;
2507
- }
2508
-
2509
- .steps button {
2510
- flex: 1;
2511
- display: grid;
2512
- place-items: center;
2513
- padding: 6px 0;
2514
- background: none;
2515
- border: 1px solid transparent;
2516
- border-radius: 6px;
2517
- color: var(--ink);
2518
- cursor: pointer;
2519
- }
2520
-
2521
- .steps button:hover:not(:disabled) {
2522
- background: var(--page);
2523
- border-color: var(--line);
2524
- }
2525
-
2526
- .steps button:disabled {
2527
- color: var(--soft);
2528
- opacity: 0.5;
2529
- cursor: default;
2530
- }
2531
-
2532
- .steps .icon {
2533
- width: 20px;
2534
- height: 20px;
2535
- stroke-width: 2;
2536
- }
2537
-
2538
- /* A piece in a move: the set's small one (T-94), White's white and Black's black, edged so either shows on either theme */
2539
- .figurine {
2540
- display: inline-block;
2541
- width: 1.15em;
2542
- height: 1.15em;
2543
- margin-right: 0.05em;
2544
- vertical-align: -0.22em;
2545
- }
2546
-
2547
- /* A capture's x is grey, so the squares of a move read first */
2548
- .takes {
2549
- color: var(--soft);
2550
- font-weight: 400;
2551
- }
2552
-
2553
- .visually-hidden {
2554
- position: absolute;
2555
- width: 1px;
2556
- height: 1px;
2557
- overflow: hidden;
2558
- clip-path: inset(50%);
2559
- white-space: nowrap;
2560
- }
2561
-
2562
- .moves .result {
2563
- margin: 6px;
2564
- font-weight: 600;
2565
- }
2566
-
2567
- .empty {
2568
- margin: 0;
2569
- color: var(--soft);
2570
- }
2571
-
2572
- /* With no game, the game's column opens with this note, as tall as the game's card, so the column's tab sits in its middle */
2573
- .side > .card.empty {
2574
- min-height: 74px;
2575
- display: flex;
2576
- align-items: center;
2577
- }
2578
-
2579
- .problem {
2580
- max-width: 40em;
2581
- margin: 24px auto;
2582
- padding: 0 16px;
2583
- }
2584
-
2585
- /* The page without its server, after /clear in Claude's app (Zoe): a card in the middle of the window, over the page that waits under it, dimmed and still;
2586
- its light breathes while the page tries again */
2587
- .offline {
2588
- position: fixed;
2589
- top: 50%;
2590
- left: 50%;
2591
- z-index: 20;
2592
- width: min(400px, calc(100vw - 32px));
2593
- margin: 0;
2594
- padding: 20px 24px;
2595
- transform: translate(-50%, -50%);
2596
- border: 1px solid color-mix(in oklab, var(--accent) 40%, var(--line));
2597
- border-radius: var(--radius);
2598
- background: var(--card);
2599
- color: var(--ink);
2600
- /* The dialogs' backdrop, over the whole window */
2601
- box-shadow: 0 0 0 100vmax rgba(16, 22, 29, 0.5), 0 16px 40px rgb(0 0 0 / 22%);
2602
- font-size: 15px;
2603
- line-height: 1.5;
2604
- text-align: center;
2605
- text-wrap: pretty;
2606
- }
2607
-
2608
- .offline::before {
2609
- content: "";
2610
- display: block;
2611
- width: 10px;
2612
- height: 10px;
2613
- margin: 0 auto 12px;
2614
- border-radius: 50%;
2615
- background: var(--accent);
2616
- animation: reconnecting 1.6s ease-in-out infinite;
2617
- }
2618
-
2619
- @keyframes reconnecting {
2620
- 50% {
2621
- opacity: 0.25;
2622
- }
2623
- }
2624
-
2625
- /* Grey, darker and a little blurred, so it reads as stopped even when the board's theme is already grey */
2626
- .offline + .app {
2627
- filter: grayscale(1) brightness(0.85) blur(2px);
2628
- }
2629
-
2630
- /* No chat hears the player (Zoe): a note under the AI's card, by its stopped clock, on a page still in use. The AI's words below it lose their tail */
2631
- .asleep {
2632
- flex: none;
2633
- margin: var(--between) 0 0;
2634
- padding: 10px 12px;
2635
- border: 1px solid color-mix(in oklab, var(--hover-edge) 55%, var(--line));
2636
- border-radius: var(--radius);
2637
- background: var(--warn-back);
2638
- color: var(--ink);
2639
- font-size: 13.5px;
2640
- line-height: 1.45;
2641
- text-wrap: pretty;
2642
- }
2643
-
2644
- .flipped .asleep {
2645
- margin: 0 0 var(--between);
2646
- }
2647
-
2648
- .ai-block:has(> .asleep) .say::before,
2649
- .ai-block:has(> .asleep) .say::after {
2650
- content: none;
2651
- }
2652
-
2653
- /* With the talk folded, the same note and the button that starts the clocks over the board's edge on the AI's side, away from the squares of the player's
2654
- first move (Stefano); clicks go through the note to the squares, and both step aside for a lifted piece, a promotion and a refused move */
2655
- .over-board {
2656
- position: absolute;
2657
- top: 12px;
2658
- left: 50%;
2659
- z-index: 2;
2660
- display: flex;
2661
- flex-direction: column;
2662
- align-items: center;
2663
- gap: 8px;
2664
- width: min(460px, calc(100% - 24px));
2665
- transform: translateX(-50%);
2666
- pointer-events: none;
2667
- animation: appear 200ms;
2668
- }
2669
-
2670
- .flipped .over-board {
2671
- top: auto;
2672
- bottom: 12px;
2673
- flex-direction: column-reverse;
2674
- }
2675
-
2676
- .over-board > .asleep {
2677
- margin: 0;
2678
- box-shadow: 0 2px 6px rgb(0 0 0 / 14%), 0 10px 28px rgb(0 0 0 / 20%);
2679
- }
2680
-
2681
- .over-board > .start-clocks {
2682
- flex: none;
2683
- padding: 9px 22px;
2684
- box-shadow: 0 2px 6px rgb(0 0 0 / 14%), 0 8px 20px rgb(0 0 0 / 22%);
2685
- pointer-events: auto;
2686
- }
2687
-
2688
- :root.dragging .over-board,
2689
- .board-wrap:has(.promotion, .notice) > .over-board {
2690
- visibility: hidden;
2691
- }
2692
-
2693
- /* A phone shows the talk whatever its fold: the note and the button stay in the cards */
2694
- @media (max-width: 840px) {
2695
- .over-board {
2696
- display: none;
2697
- }
2698
- }
2699
-
2700
- @media (prefers-reduced-motion: reduce) {
2701
- .offline::before,
2702
- .over-board {
2703
- animation: none;
2704
- }
2705
- }
2706
-
2707
- /* Between games the board goes off (D-77): the squares sink toward the page and the pieces fade, the table set and nobody playing. A game the page saw end
2708
- keeps its final position less off, once its effects are over, with the kings' badges and the last move in full. A thin line keeps its edge, which the
2709
- light squares would lose in the page */
2710
- .board-wrap.off > .board {
2711
- box-shadow: 0 0 0 1px var(--line);
2712
- }
2713
-
2714
- .board-wrap.off .square.light {
2715
- background-color: color-mix(in oklab, var(--light-square) 40%, var(--page));
2716
- }
2717
-
2718
- .board-wrap.off .square.dark {
2719
- background-color: color-mix(in oklab, var(--dark-square) 40%, var(--page));
2720
- }
2721
-
2722
- /* The pieces fade toward the page and never turn see-through, so each side keeps one colour on every square; cburnett, which ignores the variables, loses
2723
- contrast instead, opaque as well */
2724
- .board-wrap.off .piece {
2725
- --kept: 45%;
2726
- }
2727
-
2728
- :root[data-set="cburnett"] .board-wrap.off .piece {
2729
- filter: grayscale(0.5) contrast(0.55);
2730
- }
2731
-
2732
- :root[data-set="cburnett"] .board-wrap.off > .ended .piece {
2733
- filter: grayscale(0.3) contrast(0.8);
2734
- }
2735
-
2736
- :root[data-set="cburnett"] .board-wrap.off > .ended .badge .piece {
2737
- filter: none;
2738
- }
2739
-
2740
- .board-wrap.off .coordinate {
2741
- opacity: 0.4;
2742
- }
2743
-
2744
- .board-wrap.off > .ended .square.light {
2745
- background-color: color-mix(in oklab, var(--light-square) 62%, var(--page));
2746
- }
2747
-
2748
- .board-wrap.off > .ended .square.dark {
2749
- background-color: color-mix(in oklab, var(--dark-square) 62%, var(--page));
2750
- }
2751
-
2752
- .board-wrap.off > .ended .piece {
2753
- --kept: 75%;
2754
- }
2755
-
2756
- .board-wrap.off > .ended .badge .piece {
2757
- --kept: 100%;
2758
- }
2759
-
2760
- /* It goes off gently, and comes back at once with the next game */
2761
- @media (prefers-reduced-motion: no-preference) {
2762
- .board-wrap.off .square {
2763
- transition: background-color 400ms ease;
2764
- }
2765
-
2766
- .board-wrap.off .piece,
2767
- .board-wrap.off .coordinate {
2768
- transition: opacity 400ms ease, --kept 400ms ease;
2769
- }
2770
- }
2771
-
2772
- /* The header's chip when no game goes on: neutral, not the accent, with a pause sign (D-77) */
2773
- .verdict.idle {
2774
- background: var(--card);
2775
- box-shadow: inset 0 0 0 1px var(--line);
2776
- color: var(--ink);
2777
- }
2778
-
2779
- .verdict.idle .icon {
2780
- color: var(--soft);
2781
- stroke-width: 2.4;
2782
- }
2783
-
2784
- /* Between games the chip is never cut: beside it the Torretta stands for the name at every width, and the flip keeps only its icon */
2785
- @media (min-width: 841px) {
2786
- .top:has(.verdict.idle, .verdict.over) .title {
2787
- display: none;
2788
- }
2789
-
2790
- .top:has(.verdict.idle, .verdict.over) .verdict {
2791
- margin-right: auto;
2792
- }
2793
- }
2794
-
2795
- .top:has(.verdict.idle, .verdict.over) .command:has(.icon.flip) span {
2796
- display: none;
2797
- }
2798
-
2799
- /* On a phone the player's card is under the board, below the fold: between games the header's new game stands out too, on the first screen */
2800
- @media (max-width: 840px) {
2801
- .top:has(.verdict.idle, .verdict.over) .command:has(.icon.new) {
2802
- background: var(--accent);
2803
- border-color: var(--accent);
2804
- color: var(--on-accent);
2805
- }
2806
- }
2807
-
2808
- /* The settings (D-56): a dialog over the page; each choice shows at once */
2809
- .settings {
2810
- width: min(440px, calc(100vw - 32px));
2811
- max-height: calc(100vh - 48px);
2812
- padding: 0 20px 20px;
2813
- border: 1px solid var(--line);
2814
- border-radius: var(--radius);
2815
- background: var(--card);
2816
- color: var(--ink);
2817
- box-shadow: var(--shadow);
2818
- }
2819
-
2820
- .settings::backdrop {
2821
- background: rgba(16, 22, 29, 0.4);
2822
- }
2823
-
2824
- .settings header {
2825
- position: sticky;
2826
- top: 0;
2827
- display: flex;
2828
- align-items: center;
2829
- justify-content: space-between;
2830
- padding: 16px 0 8px;
2831
- background: var(--card);
2832
- }
2833
-
2834
- .settings h2 {
2835
- margin: 0;
2836
- font-size: 17px;
2837
- font-weight: 600;
2838
- }
2839
-
2840
- .settings h3 {
2841
- margin: 18px 0 8px;
2842
- font-size: 12px;
2843
- font-weight: 600;
2844
- letter-spacing: 0.06em;
2845
- text-transform: uppercase;
2846
- color: var(--soft);
2847
- }
2848
-
2849
- .choices {
2850
- margin-bottom: 12px;
2851
- }
2852
-
2853
- .choices .label {
2854
- display: block;
2855
- margin-bottom: 6px;
2856
- font-size: 13px;
2857
- color: var(--soft);
2858
- }
2859
-
2860
- .options {
2861
- display: flex;
2862
- flex-wrap: wrap;
2863
- gap: 6px;
2864
- }
2865
-
2866
- .choice {
2867
- display: inline-flex;
2868
- align-items: center;
2869
- gap: 8px;
2870
- padding: 6px 10px;
2871
- border: 1px solid var(--line);
2872
- border-radius: 8px;
2873
- background: none;
2874
- font-size: 14px;
2875
- }
2876
-
2877
- .choice:hover {
2878
- border-color: var(--soft);
2879
- }
2880
-
2881
- .choice[aria-checked="true"] {
2882
- border-color: var(--accent);
2883
- box-shadow: inset 0 0 0 1px var(--accent);
2884
- }
2885
-
2886
- .sample {
2887
- display: inline-flex;
2888
- }
2889
-
2890
- .sample .piece {
2891
- width: 26px;
2892
- height: 26px;
2893
- }
2894
-
2895
- /* A swatch: the board's two squares and its highlight, the pieces' two colours, or the marks' one */
2896
- .swatch {
2897
- display: inline-flex;
2898
- border-radius: 4px;
2899
- overflow: hidden;
2900
- box-shadow: 0 0 0 1px var(--line);
2901
- }
2902
-
2903
- .swatch i {
2904
- width: 14px;
2905
- height: 20px;
2906
- }
2907
-
2908
- .swatch[data-board] i:first-child {
2909
- background: var(--light-square);
2910
- }
2911
-
2912
- .swatch[data-board] i:nth-child(2) {
2913
- background: var(--dark-square);
2914
- }
2915
-
2916
- .swatch[data-board] i:nth-child(3) {
2917
- background: var(--dark-square) linear-gradient(var(--last-move), var(--last-move));
2918
- }
2919
-
2920
- .swatch[data-pieces] i:first-child {
2921
- background: var(--white-piece);
2922
- }
2923
-
2924
- .swatch[data-pieces] i:last-child {
2925
- background: var(--black-piece);
2926
- }
2927
-
2928
- .swatch[data-marks] i {
2929
- background: var(--mark);
2930
- }
2931
-
2932
- .toggle {
2933
- display: flex;
2934
- align-items: center;
2935
- justify-content: space-between;
2936
- padding: 6px 0;
2937
- font-size: 14px;
2938
- }
2939
-
2940
- .toggle input {
2941
- width: 18px;
2942
- height: 18px;
2943
- accent-color: var(--accent);
2944
- }
2945
-
2946
- /* The profiles (D-23, D-45): the player's picture, which a click changes, their name, which opens the profiles, the wizard and the profiles' dialogs */
2947
- .avatar.photo {
2948
- clip-path: none;
2949
- border-radius: 50%;
2950
- object-fit: cover;
2951
- box-shadow: 0 0 0 1px var(--line);
2952
- }
2953
-
2954
- /* A drawn avatar, its colour in the picture: the page's colour while it loads */
2955
- .avatar.drawn {
2956
- background: var(--say);
2957
- }
2958
-
2959
- .me {
2960
- position: relative;
2961
- flex: none;
2962
- padding: 0;
2963
- border: 0;
2964
- border-radius: 50%;
2965
- background: none;
2966
- line-height: 0;
2967
- cursor: pointer;
2968
- }
2969
-
2970
- .me-cover {
2971
- position: absolute;
2972
- inset: 0;
2973
- display: grid;
2974
- place-items: center;
2975
- border-radius: 50%;
2976
- background: rgba(0, 0, 0, 0.45);
2977
- color: #fff;
2978
- opacity: 0;
2979
- transition: opacity 0.12s;
2980
- }
2981
-
2982
- .me-cover .icon {
2983
- width: 45%;
2984
- height: 45%;
2985
- }
2986
-
2987
- .me:hover .me-cover,
2988
- .me:focus-visible .me-cover {
2989
- opacity: 1;
2990
- }
2991
-
2992
- /* Where nothing hovers, a camera in the corner says the picture changes */
2993
- .me-badge {
2994
- position: absolute;
2995
- right: -2px;
2996
- bottom: -2px;
2997
- display: none;
2998
- place-items: center;
2999
- width: 18px;
3000
- height: 18px;
3001
- border-radius: 50%;
3002
- background: var(--accent);
3003
- color: var(--on-accent);
3004
- box-shadow: 0 0 0 2px var(--card);
3005
- }
3006
-
3007
- .me-badge .icon {
3008
- width: 12px;
3009
- height: 12px;
3010
- }
3011
-
3012
- @media (hover: none) {
3013
- .me-badge {
3014
- display: grid;
3015
- }
3016
- }
3017
-
3018
- .profile-name {
3019
- display: inline-flex;
3020
- align-items: center;
3021
- gap: 2px;
3022
- min-width: 0;
3023
- max-width: 100%;
3024
- padding: 0;
3025
- border: 0;
3026
- background: none;
3027
- color: inherit;
3028
- font: inherit;
3029
- text-align: left;
3030
- cursor: pointer;
3031
- }
3032
-
3033
- .profile-name span {
3034
- overflow: hidden;
3035
- white-space: nowrap;
3036
- text-overflow: ellipsis;
3037
- }
3038
-
3039
- .profile-name .icon {
3040
- flex: none;
3041
- width: 15px;
3042
- height: 15px;
3043
- color: var(--soft);
3044
- }
3045
-
3046
- .profile-name:hover,
3047
- .profile-name:hover .icon {
3048
- color: var(--accent);
3049
- }
3050
-
3051
- .wizard {
3052
- max-width: 480px;
3053
- margin: 32px auto;
3054
- padding: 28px;
3055
- border: 1px solid var(--line);
3056
- border-radius: var(--radius);
3057
- background: var(--card);
3058
- box-shadow: var(--shadow);
3059
- }
3060
-
3061
- .wizard h1 {
3062
- margin: 12px 0 4px;
3063
- font-size: 24px;
3064
- }
3065
-
3066
- .wizard .lead {
3067
- margin: 0 0 24px;
3068
- color: var(--soft);
3069
- }
3070
-
3071
- .wizard .lead span {
3072
- display: block;
3073
- margin-top: 4px;
3074
- }
3075
-
3076
- .profile-form fieldset {
3077
- min-width: 0;
3078
- margin: 0 0 20px;
3079
- padding: 0;
3080
- border: 0;
3081
- }
3082
-
3083
- .profile-form legend,
3084
- .profile-form .field > span {
3085
- display: block;
3086
- margin-bottom: 8px;
3087
- padding: 0;
3088
- font-size: 15px;
3089
- font-weight: 600;
3090
- }
3091
-
3092
- .profile-form legend small {
3093
- font-weight: 400;
3094
- color: var(--soft);
3095
- }
3096
-
3097
- .profile-form .field {
3098
- display: block;
3099
- margin-bottom: 20px;
3100
- }
3101
-
3102
- .profile-form input[type="text"],
3103
- .profile-form input[type="number"],
3104
- .profile-form select {
3105
- box-sizing: border-box;
3106
- width: 100%;
3107
- padding: 10px 12px;
3108
- border: 1px solid var(--line);
3109
- border-radius: 8px;
3110
- background: var(--page);
3111
- color: var(--ink);
3112
- font: inherit;
3113
- font-size: 16px;
3114
- }
3115
-
3116
- .study textarea {
3117
- box-sizing: border-box;
3118
- width: 100%;
3119
- padding: 10px 12px;
3120
- border: 1px solid var(--line);
3121
- border-radius: 8px;
3122
- background: var(--page);
3123
- color: var(--ink);
3124
- font: 13px/1.4 ui-monospace, monospace;
3125
- resize: vertical;
3126
- }
3127
-
3128
- .study .file input {
3129
- font: inherit;
3130
- font-size: 14px;
3131
- color: var(--soft);
3132
- }
3133
-
3134
- /* The file button as our secondary buttons, in both themes */
3135
- .study .file input::file-selector-button {
3136
- margin-right: 10px;
3137
- padding: 6px 12px;
3138
- border: 1px solid var(--line);
3139
- border-radius: 8px;
3140
- background: var(--card);
3141
- color: var(--ink);
3142
- font: inherit;
3143
- cursor: pointer;
3144
- }
3145
-
3146
- .study .note {
3147
- margin: 0 0 16px;
3148
- }
3149
-
3150
- /* In analysis, the game's own commands in the right column (T-106): save its PGN with the review, open the other analyses */
3151
- .analysis-actions {
3152
- display: flex;
3153
- gap: 8px;
3154
- padding: 8px;
3155
- }
3156
-
3157
- .analysis-actions button {
3158
- flex: 1;
3159
- display: inline-flex;
3160
- align-items: center;
3161
- justify-content: center;
3162
- gap: 6px;
3163
- padding: 7px 10px;
3164
- border: 1px solid var(--line);
3165
- border-radius: 8px;
3166
- background: transparent;
3167
- color: var(--ink);
3168
- font: inherit;
3169
- font-size: 13px;
3170
- cursor: pointer;
3171
- }
3172
-
3173
- .analysis-actions button:hover {
3174
- border-color: var(--accent);
3175
- }
3176
-
3177
- /* The analyses to open again (T-106): a line each, who played and how it ended, then when, the opening and how long, and whether the AI has reviewed it */
3178
- .study h3 {
3179
- margin: 0 0 8px;
3180
- font-size: 13px;
3181
- font-weight: 600;
3182
- color: var(--soft);
3183
- }
3184
-
3185
- .analyses ul {
3186
- display: grid;
3187
- gap: 6px;
3188
- max-height: 40vh;
3189
- overflow-y: auto;
3190
- margin: 0 0 18px;
3191
- padding: 0;
3192
- list-style: none;
3193
- }
3194
-
3195
- .analyses button {
3196
- display: grid;
3197
- grid-template-columns: 1fr auto;
3198
- gap: 2px 10px;
3199
- width: 100%;
3200
- padding: 8px 12px;
3201
- border: 1px solid var(--line);
3202
- border-radius: 8px;
3203
- background: var(--card);
3204
- color: var(--ink);
3205
- font: inherit;
3206
- font-size: 14px;
3207
- text-align: left;
3208
- cursor: pointer;
3209
- }
3210
-
3211
- .analyses button:hover {
3212
- border-color: var(--accent);
3213
- }
3214
-
3215
- .analyses b {
3216
- overflow: hidden;
3217
- white-space: nowrap;
3218
- text-overflow: ellipsis;
3219
- }
3220
-
3221
- .analyses .note {
3222
- margin: 0;
3223
- font-size: 12px;
3224
- }
3225
-
3226
- .analyses .state {
3227
- color: var(--soft);
3228
- font-size: 12px;
3229
- text-align: right;
3230
- }
3231
-
3232
- .analyses .state.reviewed {
3233
- color: var(--accent);
3234
- }
3235
-
3236
- .profile-form textarea:focus-visible,
3237
- .profile-form input:focus-visible,
3238
- .profile-form select:focus-visible {
3239
- outline: 2px solid var(--accent);
3240
- outline-offset: -1px;
3241
- }
3242
-
3243
- /* The drawn avatars: always two rows of five, smaller on a narrow screen (Zoe, T-102) */
3244
- .avatars {
3245
- display: grid;
3246
- grid-template-columns: repeat(5, minmax(0, 62px));
3247
- justify-content: space-between;
3248
- gap: 8px;
3249
- justify-items: center;
3250
- }
3251
-
3252
- .avatars .avatar-choice {
3253
- width: 100%;
3254
- box-sizing: border-box;
3255
- }
3256
-
3257
- .avatar-choice {
3258
- position: relative;
3259
- padding: 3px;
3260
- border: 2px solid transparent;
3261
- border-radius: 50%;
3262
- background: none;
3263
- line-height: 0;
3264
- cursor: pointer;
3265
- }
3266
-
3267
- .avatar-choice input {
3268
- position: absolute;
3269
- width: 1px;
3270
- height: 1px;
3271
- opacity: 0;
3272
- }
3273
-
3274
- .avatar-choice:has(input:checked),
3275
- .avatar-choice[aria-pressed="true"],
3276
- .avatar-choice.on {
3277
- border-color: var(--accent);
3278
- }
3279
-
3280
- .avatar-choice:has(input:focus-visible) {
3281
- outline: 2px solid var(--accent);
3282
- outline-offset: 2px;
3283
- }
3284
-
3285
- .avatar-choice .avatar {
3286
- display: block;
3287
- width: 100%;
3288
- height: auto;
3289
- }
3290
-
3291
- /* The player's own photo: a line of its own under the drawn avatars, at every width */
3292
- .avatar-choice.upload {
3293
- display: flex;
3294
- align-items: center;
3295
- gap: 10px;
3296
- width: fit-content;
3297
- margin-top: 10px;
3298
- padding-right: 14px;
3299
- border-radius: 30px;
3300
- color: var(--accent);
3301
- font-size: 14px;
3302
- line-height: 1.2;
3303
- }
3304
-
3305
- .avatar-choice.upload .avatar {
3306
- width: 36px;
3307
- height: 36px;
3308
- }
3309
-
3310
- .ring {
3311
- display: grid;
3312
- place-items: center;
3313
- width: 36px;
3314
- height: 36px;
3315
- border: 2px dashed var(--line);
3316
- border-radius: 50%;
3317
- box-sizing: border-box;
3318
- color: var(--soft);
3319
- }
3320
-
3321
- .ring .icon {
3322
- width: 18px;
3323
- height: 18px;
3324
- }
3325
-
3326
- /* How the player plays: two by two, each with its note under it */
3327
- .levels {
3328
- display: grid;
3329
- grid-template-columns: 1fr 1fr;
3330
- gap: 8px;
3331
- }
3332
-
3333
- .level {
3334
- position: relative;
3335
- cursor: pointer;
3336
- }
3337
-
3338
- .level input {
3339
- position: absolute;
3340
- opacity: 0;
3341
- }
3342
-
3343
- .level > span {
3344
- display: flex;
3345
- flex-direction: column;
3346
- gap: 2px;
3347
- height: 100%;
3348
- box-sizing: border-box;
3349
- padding: 9px 12px;
3350
- border: 1px solid var(--line);
3351
- border-radius: 8px;
3352
- background: var(--page);
3353
- }
3354
-
3355
- .level small {
3356
- color: var(--soft);
3357
- font-size: 13px;
3358
- }
3359
-
3360
- .level:has(input:checked) > span {
3361
- border-color: var(--accent);
3362
- box-shadow: inset 0 0 0 1px var(--accent);
3363
- }
3364
-
3365
- .level:has(input:focus-visible) > span {
3366
- outline: 2px solid var(--accent);
3367
- outline-offset: 2px;
3368
- }
3369
-
3370
- .rating {
3371
- display: grid;
3372
- grid-template-columns: 1fr 1fr;
3373
- gap: 8px;
3374
- }
3375
-
3376
- .profile-form .start {
3377
- width: 100%;
3378
- padding: 13px;
3379
- border: 0;
3380
- border-radius: 8px;
3381
- background: var(--accent);
3382
- color: var(--on-accent);
3383
- font: inherit;
3384
- font-size: 16px;
3385
- font-weight: 600;
3386
- cursor: pointer;
3387
- }
3388
-
3389
- .profile-form .start:disabled {
3390
- opacity: 0.6;
3391
- cursor: default;
3392
- }
3393
-
3394
- .profile-form .problem,
3395
- .profiles .problem {
3396
- margin: 0 0 12px;
3397
- padding: 0;
3398
- color: var(--low-time);
3399
- font-size: 14px;
3400
- }
3401
-
3402
- .profiles header {
3403
- justify-content: flex-start;
3404
- gap: 4px;
3405
- }
3406
-
3407
- .profiles header h2 {
3408
- flex: 1;
3409
- min-width: 0;
3410
- }
3411
-
3412
- .profiles .avatars {
3413
- margin-top: 8px;
3414
- }
3415
-
3416
- .profiles .avatar-choice.upload {
3417
- margin-bottom: 12px;
3418
- }
3419
-
3420
- .profile-list {
3421
- display: grid;
3422
- gap: 6px;
3423
- margin: 8px 0 12px;
3424
- }
3425
-
3426
- .profile-list .choice {
3427
- min-width: 0;
3428
- font-size: 15px;
3429
- text-align: left;
3430
- }
3431
-
3432
- /* The profile in use: a tick at the end of its line, not the ring of a field being typed in */
3433
- .profile-list .choice[aria-checked="true"] {
3434
- border-color: var(--line);
3435
- box-shadow: none;
3436
- }
3437
-
3438
- .profile-list .choice span {
3439
- flex: 1;
3440
- min-width: 0;
3441
- overflow: hidden;
3442
- white-space: nowrap;
3443
- text-overflow: ellipsis;
3444
- }
3445
-
3446
- .profile-list .in-use {
3447
- flex: none;
3448
- width: 18px;
3449
- height: 18px;
3450
- color: var(--accent);
3451
- }
3452
-
3453
- .profile-list .choice:disabled {
3454
- opacity: 0.6;
3455
- cursor: default;
3456
- }
3457
-
3458
- .profile-list .avatar {
3459
- flex: none;
3460
- width: 32px;
3461
- height: 32px;
3462
- }
3463
-
3464
- .profiles .note {
3465
- margin: 0 0 12px;
3466
- }
3467
-
3468
- .profiles .new-profile {
3469
- border-color: var(--line);
3470
- color: var(--ink);
3471
- }
3472
-
3473
- .profiles .new-profile:disabled {
3474
- color: var(--soft);
3475
- cursor: default;
3476
- }
3477
-
3478
- /* Where the games are (T-119), under the wizard's form and the players' menu, with the button that opens it */
3479
- .data-folder {
3480
- display: flex;
3481
- flex-wrap: wrap;
3482
- align-items: center;
3483
- gap: 8px 12px;
3484
- margin-top: 20px;
3485
- padding-top: 16px;
3486
- border-top: 1px solid var(--line);
3487
- }
3488
-
3489
- .data-folder .note {
3490
- flex: 1 1 220px;
3491
- margin: 0;
3492
- }
3493
-
3494
- .data-folder b {
3495
- color: var(--ink);
3496
- font-weight: 600;
3497
- overflow-wrap: anywhere;
3498
- }
3499
-
3500
- .data-folder .command {
3501
- border-color: var(--line);
3502
- color: var(--ink);
3503
- }
3504
-
3505
- .data-folder .command:disabled {
3506
- color: var(--soft);
3507
- cursor: default;
3508
- }
3509
-
3510
- /* The account's name suggested in the wizard (T-120): Chrome's arrow, quieter than the selects' chevron, is the only sign of it */
3511
- .profile-form input::-webkit-calendar-picker-indicator {
3512
- opacity: 0.45;
3513
- }
3514
-
3515
- .data-folder .problem {
3516
- flex-basis: 100%;
3517
- margin: 0;
3518
- }
3519
-
3520
- /* The new game (T-58): the colours and the clocks in a row, the levels two by two with what the AI sees under them */
3521
- .new-game .row {
3522
- display: grid;
3523
- grid-template-columns: repeat(auto-fit, minmax(52px, 1fr));
3524
- gap: 8px;
3525
- }
3526
-
3527
- .new-game .row .level > span {
3528
- align-items: center;
3529
- gap: 4px;
3530
- padding: 9px 4px;
3531
- }
3532
-
3533
- /* Each colour by its king, either by both, and each clock by its minutes as a slice of the hour */
3534
- .new-game .row .piece {
3535
- width: 30px;
3536
- height: 30px;
3537
- margin: -3px 0;
3538
- }
3539
-
3540
- .new-game .kings {
3541
- display: flex;
3542
- }
3543
-
3544
- .new-game .kings .piece + .piece {
3545
- margin-left: -8px;
3546
- }
3547
-
3548
- .new-game .clock-icon {
3549
- width: 24px;
3550
- height: 24px;
3551
- }
3552
-
3553
- .new-game .clock-icon .slice {
3554
- fill: currentColor;
3555
- stroke: none;
3556
- }
3557
-
3558
- .new-game .sees {
3559
- margin: 10px 0 0;
3560
- color: var(--soft);
3561
- font-size: 13px;
3562
- }
3563
-
3564
- .new-game .levels {
3565
- grid-auto-rows: 1fr;
3566
- }
3567
-
3568
- /* The AI's level on its card: a button that shows what it sees, under it where the browser anchors popovers, else in the middle */
3569
- .level-name {
3570
- margin: -4px -2px;
3571
- padding: 4px 2px;
3572
- border: 0;
3573
- border-radius: 4px;
3574
- background: none;
3575
- color: inherit;
3576
- font: inherit;
3577
- cursor: help;
3578
- text-decoration: underline dotted;
3579
- text-underline-offset: 3px;
3580
- anchor-name: --ai-level;
3581
- }
3582
-
3583
- .level-name:focus-visible {
3584
- outline: 2px solid var(--accent);
3585
- outline-offset: 2px;
3586
- }
3587
-
3588
- .level-tip {
3589
- max-width: min(280px, calc(100vw - 32px));
3590
- padding: 8px 10px;
3591
- border: 1px solid var(--line);
3592
- border-radius: 8px;
3593
- background: var(--card);
3594
- color: var(--ink);
3595
- font-size: 13px;
3596
- line-height: 1.35;
3597
- box-shadow: var(--shadow);
3598
- }
3599
-
3600
- @supports (position-area: bottom) {
3601
- .level-tip {
3602
- position-anchor: --ai-level;
3603
- position-area: bottom span-right;
3604
- position-try-fallbacks: flip-block, flip-inline;
3605
- inset: auto;
3606
- margin: 6px 16px 6px 0;
3607
- }
3608
- }
3609
-
3610
- @media (max-width: 520px) {
3611
- .wizard {
3612
- margin: 0;
3613
- padding: 20px 16px;
3614
- border: 0;
3615
- border-radius: 0;
3616
- box-shadow: none;
3617
- }
3618
- }
3619
-
3620
- /* Zoe's palettes (T-82): on the page's root and on each swatch of the settings. Board skins, each with its own highlights */
3621
- :root[data-board="azzurro"],
3622
- [data-board="azzurro"] {
3623
- --light-square: #eaf1f8;
3624
- --dark-square: #86abd0;
3625
- --last-move: rgba(255, 206, 70, 0.65);
3626
- --selected: rgba(255, 190, 50, 0.85);
3627
- --hover-edge: #f4c84c;
3628
- }
3629
-
3630
- :root[data-theme="dark"][data-board="azzurro"],
3631
- :root[data-theme="dark"] [data-board="azzurro"] {
3632
- --light-square: #a9bccd;
3633
- --dark-square: #61809e;
3634
- --last-move: rgba(255, 206, 70, 0.65);
3635
- --selected: rgba(255, 190, 50, 0.85);
3636
- --hover-edge: #f4c84c;
3637
- }
3638
-
3639
- :root[data-board="verde"],
3640
- [data-board="verde"] {
3641
- --light-square: #eeeed2;
3642
- --dark-square: #769656;
3643
- --last-move: rgba(255, 255, 51, 0.5);
3644
- --selected: rgba(255, 236, 40, 0.75);
3645
- --hover-edge: #f6f669;
3646
- }
3647
-
3648
- :root[data-theme="dark"][data-board="verde"],
3649
- :root[data-theme="dark"] [data-board="verde"] {
3650
- --light-square: #c3c7a8;
3651
- --dark-square: #5f7c45;
3652
- --last-move: rgba(255, 255, 51, 0.5);
3653
- --selected: rgba(255, 236, 40, 0.75);
3654
- --hover-edge: #f6f669;
3655
- }
3656
-
3657
- :root[data-board="noce"],
3658
- [data-board="noce"] {
3659
- --light-square: #e9d8bd;
3660
- --dark-square: #a6866a;
3661
- --last-move: rgba(200, 212, 40, 0.55);
3662
- --selected: rgba(185, 205, 20, 0.75);
3663
- --hover-edge: #cdd26a;
3664
- }
3665
-
3666
- :root[data-theme="dark"][data-board="noce"],
3667
- :root[data-theme="dark"] [data-board="noce"] {
3668
- --light-square: #c4b096;
3669
- --dark-square: #80654d;
3670
- --last-move: rgba(200, 212, 40, 0.55);
3671
- --selected: rgba(185, 205, 20, 0.75);
3672
- --hover-edge: #cdd26a;
3673
- }
3674
-
3675
- :root[data-board="ardesia"],
3676
- [data-board="ardesia"] {
3677
- --light-square: #dfe3e8;
3678
- --dark-square: #8b97a4;
3679
- --last-move: rgba(255, 206, 70, 0.6);
3680
- --selected: rgba(255, 190, 50, 0.8);
3681
- --hover-edge: #f4c84c;
3682
- }
3683
-
3684
- :root[data-theme="dark"][data-board="ardesia"],
3685
- :root[data-theme="dark"] [data-board="ardesia"] {
3686
- --light-square: #a7b0ba;
3687
- --dark-square: #65707c;
3688
- --last-move: rgba(255, 206, 70, 0.6);
3689
- --selected: rgba(255, 190, 50, 0.8);
3690
- --hover-edge: #f4c84c;
3691
- }
3692
-
3693
- :root[data-board="grigio"],
3694
- [data-board="grigio"] {
3695
- --light-square: #ededed;
3696
- --dark-square: #9a9a9a;
3697
- --last-move: rgba(255, 206, 70, 0.6);
3698
- --selected: rgba(255, 190, 50, 0.8);
3699
- --hover-edge: #f4c84c;
3700
- }
3701
-
3702
- :root[data-theme="dark"][data-board="grigio"],
3703
- :root[data-theme="dark"] [data-board="grigio"] {
3704
- --light-square: #b9b9b9;
3705
- --dark-square: #707070;
3706
- --last-move: rgba(255, 206, 70, 0.6);
3707
- --selected: rgba(255, 190, 50, 0.8);
3708
- --hover-edge: #f4c84c;
3709
- }
3710
-
3711
- :root[data-board="lavanda"],
3712
- [data-board="lavanda"] {
3713
- --light-square: #ece6f2;
3714
- --dark-square: #9a86b8;
3715
- --last-move: rgba(255, 214, 90, 0.6);
3716
- --selected: rgba(255, 200, 60, 0.8);
3717
- --hover-edge: #f4c84c;
3718
- }
3719
-
3720
- :root[data-theme="dark"][data-board="lavanda"],
3721
- :root[data-theme="dark"] [data-board="lavanda"] {
3722
- --light-square: #b8adc6;
3723
- --dark-square: #6f5e8c;
3724
- --last-move: rgba(255, 214, 90, 0.6);
3725
- --selected: rgba(255, 200, 60, 0.8);
3726
- --hover-edge: #f4c84c;
3727
- }
3728
-
3729
- :root[data-board="ciliegio"],
3730
- [data-board="ciliegio"] {
3731
- --light-square: #ecd3b6;
3732
- --dark-square: #9a5a3e;
3733
- --last-move: rgba(230, 220, 70, 0.55);
3734
- --selected: rgba(220, 210, 40, 0.75);
3735
- --hover-edge: #e6dc46;
3736
- }
3737
-
3738
- :root[data-theme="dark"][data-board="ciliegio"],
3739
- :root[data-theme="dark"] [data-board="ciliegio"] {
3740
- --light-square: #c6ab8f;
3741
- --dark-square: #73412c;
3742
- --last-move: rgba(230, 220, 70, 0.55);
3743
- --selected: rgba(220, 210, 40, 0.75);
3744
- --hover-edge: #e6dc46;
3745
- }
3746
-
3747
- :root[data-board="menta"],
3748
- [data-board="menta"] {
3749
- --light-square: #e9f3ec;
3750
- --dark-square: #7cb396;
3751
- --last-move: rgba(255, 218, 80, 0.6);
3752
- --selected: rgba(255, 204, 50, 0.8);
3753
- --hover-edge: #f4c84c;
3754
- }
3755
-
3756
- :root[data-theme="dark"][data-board="menta"],
3757
- :root[data-theme="dark"] [data-board="menta"] {
3758
- --light-square: #b3c6b9;
3759
- --dark-square: #58876d;
3760
- --last-move: rgba(255, 218, 80, 0.6);
3761
- --selected: rgba(255, 204, 50, 0.8);
3762
- --hover-edge: #f4c84c;
3763
- }
3764
-
3765
- :root[data-board="carta"],
3766
- [data-board="carta"] {
3767
- --light-square: #f3f1ea;
3768
- --dark-square: #b8b2a2;
3769
- --last-move: rgba(110, 165, 225, 0.5);
3770
- --selected: rgba(80, 145, 215, 0.7);
3771
- --hover-edge: #4a8ad0;
3772
- }
3773
-
3774
- :root[data-theme="dark"][data-board="carta"],
3775
- :root[data-theme="dark"] [data-board="carta"] {
3776
- --light-square: #c9c5b9;
3777
- --dark-square: #8a8577;
3778
- --last-move: rgba(110, 165, 225, 0.5);
3779
- --selected: rgba(80, 145, 215, 0.7);
3780
- --hover-edge: #4a8ad0;
3781
- }
3782
-
3783
- /* Piece colours for Nitida and Torretta */
3784
- :root[data-pieces="classico"],
3785
- [data-pieces="classico"] {
3786
- --white-piece: #fff;
3787
- --black-piece: #000;
3788
- }
3789
-
3790
- :root[data-pieces="avorio"],
3791
- [data-pieces="avorio"] {
3792
- --white-piece: #f4ead3;
3793
- --black-piece: #2a1c12;
3794
- }
3795
-
3796
- :root[data-pieces="notte"],
3797
- [data-pieces="notte"] {
3798
- --white-piece: #fff;
3799
- --black-piece: #1a3050;
3800
- }
3801
-
3802
- :root[data-pieces="bordeaux"],
3803
- [data-pieces="bordeaux"] {
3804
- --white-piece: #fff;
3805
- --black-piece: #5e161c;
3806
- }
3807
-
3808
- /* Marks with the right button */
3809
- :root[data-marks="arancione"],
3810
- [data-marks="arancione"] {
3811
- --mark: #f07c1e;
3812
- --mark-square: rgba(240, 124, 30, 0.65);
3813
- }
3814
-
3815
- :root[data-marks="rosso"],
3816
- [data-marks="rosso"] {
3817
- --mark: #d6342c;
3818
- --mark-square: rgba(214, 52, 44, 0.6);
3819
- }
3820
-
3821
- :root[data-marks="blu"],
3822
- [data-marks="blu"] {
3823
- --mark: #2335a8;
3824
- --mark-square: rgba(35, 53, 168, 0.62);
3825
- }
3826
-
3827
- :root[data-marks="verde"],
3828
- [data-marks="verde"] {
3829
- --mark: #0f6b30;
3830
- --mark-square: rgba(15, 107, 48, 0.7);
3831
- }
3832
-
3833
- /* Beside the board, a column's content keeps its width and its outer edge while the column folds: it slides under the board, the text never flows again */
3834
- @media (min-width: 841px) {
3835
- .talk > * {
3836
- width: var(--left);
3837
- }
3838
- }
3839
-
3840
- @media (min-width: 1100px) {
3841
- .side {
3842
- align-items: flex-end;
3843
- }
3844
-
3845
- .side > * {
3846
- width: var(--right);
3847
- }
3848
- }
3849
-
3850
- /* Where three columns would leave the board small, the game's column goes under the board, always open */
3851
- @media (min-width: 841px) and (max-width: 1099px) {
3852
- .app,
3853
- .app.folded {
3854
- --right-now: 0px;
3855
- grid-template-columns: var(--left-now) auto;
3856
- grid-template-rows: auto minmax(var(--least), auto) auto;
3857
- grid-template-areas: ". head" "talk board" ". side";
3858
- /* The page scrolls here: the board measures the page without its scroll bar */
3859
- container-type: inline-size;
3860
- }
3861
-
3862
- .board-wrap {
3863
- width: min(calc(100cqw - var(--left-now) - var(--between)), max(var(--least), calc(100vh - var(--bar) - 3 * var(--between))));
3864
- }
3865
-
3866
- .side,
3867
- .app.folded .side {
3868
- visibility: visible;
3869
- contain: none;
3870
- }
3871
-
3872
- .fold-tab.of-game {
3873
- display: none;
3874
- }
3875
-
3876
- .moves ol {
3877
- columns: 2;
3878
- column-gap: 12px;
3879
- }
3880
-
3881
- .moves li {
3882
- break-inside: avoid;
3883
- }
3884
- }
3885
-
3886
- @media (prefers-reduced-motion: reduce) {
3887
- .app,
3888
- .board-wrap,
3889
- .fold-tab,
3890
- .app.talk-rail .talk {
3891
- transition: none;
3892
- }
3893
-
3894
- .app.talk-rail .faces,
3895
- .verdict,
3896
- .game-card.lit {
3897
- animation: none;
3898
- }
3899
- }
3900
-
3901
- /* A phone, or a narrow window: one column. The AI above the board, the player's words and card below it, then the game */
3902
- @media (max-width: 840px) {
3903
- :root {
3904
- --gap: 12px;
3905
- }
3906
-
3907
- .command span {
3908
- display: none;
3909
- }
3910
-
3911
- /* The header has no room for the word on a game over: it takes a line of its own under the buttons */
3912
- .top {
3913
- height: auto;
3914
- min-height: var(--bar);
3915
- flex-wrap: wrap;
3916
- gap: var(--between) 8px;
3917
- }
3918
-
3919
- /* The name gives way to the buttons, which keep to the first line */
3920
- .title {
3921
- min-width: 0;
3922
- overflow: hidden;
3923
- white-space: nowrap;
3924
- text-overflow: ellipsis;
3925
- }
3926
-
3927
- .verdict {
3928
- order: 1;
3929
- flex-basis: 100%;
3930
- text-align: center;
3931
- justify-content: center;
3932
- }
3933
-
3934
- /* The AI's draw offer and its answer share the second line */
3935
- .answer {
3936
- order: 1;
3937
- }
3938
-
3939
- .top:has(.answer) .verdict {
3940
- flex: 1 0 60%;
3941
- }
3942
-
3943
- .app,
3944
- .app.folded,
3945
- .app.talk-rail,
3946
- .app.talk-folded {
3947
- grid-template-columns: 1fr;
3948
- grid-template-rows: none;
3949
- grid-template-areas: "head" "ai" "board" "you" "side";
3950
- }
3951
-
3952
- .app.flipped {
3953
- grid-template-areas: "head" "you" "board" "ai" "side";
3954
- }
3955
-
3956
- /* The helps' map right under the board, by the thumb, so the board stays in sight while it shows (D-78, Zoe) */
3957
- .app:has(.board-map) {
3958
- grid-template-areas: "head" "ai" "board" "map" "you" "side";
3959
- }
3960
-
3961
- .app.flipped:has(.board-map) {
3962
- grid-template-areas: "head" "you" "board" "map" "ai" "side";
3963
- }
3964
-
3965
- .board-map {
3966
- display: flex;
3967
- justify-content: flex-end;
3968
- grid-area: map;
3969
- }
3970
-
3971
- .helps-card .map-button {
3972
- display: none;
3973
- }
3974
-
3975
- .talk,
3976
- .app.talk-rail .talk,
3977
- .app.talk-folded .talk {
3978
- display: contents;
3979
- visibility: visible;
3980
- opacity: 1;
3981
- }
3982
-
3983
- .ai-block {
3984
- grid-area: ai;
3985
- }
3986
-
3987
- .you-block {
3988
- grid-area: you;
3989
- }
3990
-
3991
- .board-wrap {
3992
- width: 100%;
3993
- }
3994
-
3995
- .says,
3996
- .sent {
3997
- max-height: 30vh;
3998
- }
3999
-
4000
- .side,
4001
- .app.folded .side {
4002
- display: flex;
4003
- visibility: visible;
4004
- contain: none;
4005
- }
4006
-
4007
- .fold-tab,
4008
- .app.talk-rail .faces,
4009
- .app.talk-folded .faces {
4010
- display: none;
4011
- }
4012
-
4013
- .moves ol {
4014
- columns: 2;
4015
- column-gap: 12px;
4016
- }
4017
-
4018
- .moves li {
4019
- break-inside: avoid;
4020
- }
4021
-
4022
- /* A game in analysis, turned round or not: the card on top, the board, its steps under the thumb, the Torretta's note, the card below, the moves (Zoe, T-40) */
4023
- .app:has(.talk.studied),
4024
- .app.flipped:has(.talk.studied) {
4025
- grid-template-areas: "head" "ai" "board" "steps" "note" "you" "side";
4026
- }
4027
-
4028
- .talk.studied > .ai-block {
4029
- display: contents;
4030
- }
4031
-
4032
- .talk.studied > .ai-block > :not(.ai-note) {
4033
- grid-area: ai;
4034
- }
4035
-
4036
- .talk.studied .ai-note {
4037
- grid-area: note;
4038
- margin-top: 0;
4039
- }
4040
-
4041
- /* With no chat listening, its note comes before the Torretta's (Zoe) */
4042
- .app:has(.talk.studied > .ai-block > .asleep),
4043
- .app.flipped:has(.talk.studied > .ai-block > .asleep) {
4044
- grid-template-areas: "head" "ai" "board" "steps" "asleep" "note" "you" "side";
4045
- }
4046
-
4047
- .talk.studied > .ai-block > .asleep {
4048
- grid-area: asleep;
4049
- margin: 0;
4050
- }
4051
-
4052
- .board-steps {
4053
- display: block;
4054
- grid-area: steps;
4055
- }
4056
-
4057
- .app:has(.talk.studied) .side .steps {
4058
- display: none;
4059
- }
4060
-
4061
- .move-note .move-number {
4062
- display: inline;
4063
- }
4064
- }
4065
-
4066
- /* The helps (D-78, Zoe's sketch B): one ink for all they draw, never one of the AI's colours, a fill or a ring. The board says where, the card says what. */
4067
- :root {
4068
- --help-ink: #11161d;
4069
- --help-on: #fff;
4070
- --help-line: rgba(17, 22, 29, 0.78);
4071
- --help-halo: rgba(255, 255, 255, 0.85);
4072
- }
4073
-
4074
- /* A piece at risk: a corner folded in ink, bottom left, the square's free corner */
4075
- .help-notch {
4076
- position: absolute;
4077
- left: 0;
4078
- bottom: 0;
4079
- z-index: 2;
4080
- display: block;
4081
- width: clamp(14px, 6.5cqw, 44px);
4082
- height: clamp(14px, 6.5cqw, 44px);
4083
- pointer-events: none;
4084
- }
4085
-
4086
- .help-notch svg {
4087
- display: block;
4088
- width: 100%;
4089
- height: 100%;
4090
- }
4091
-
4092
- .help-notch path {
4093
- fill: var(--help-ink);
4094
- stroke: var(--help-halo);
4095
- stroke-width: 0.9;
4096
- stroke-linejoin: round;
4097
- }
4098
-
4099
- .help-notch circle {
4100
- fill: var(--help-on);
4101
- }
4102
-
4103
- /* A pin: a thin dashed ink line from the pinner to what stands behind, under the arrows; without a head, never an arrow */
4104
- .helps-layer {
4105
- position: absolute;
4106
- left: 0;
4107
- top: 0;
4108
- width: 100%;
4109
- aspect-ratio: 1;
4110
- z-index: 1;
4111
- pointer-events: none;
4112
- }
4113
-
4114
- .helps-layer line.halo {
4115
- stroke: rgba(255, 255, 255, 0.35);
4116
- stroke-width: 0.13;
4117
- }
4118
-
4119
- .helps-layer line:not(.halo) {
4120
- stroke: var(--help-line);
4121
- stroke-width: 0.065;
4122
- stroke-dasharray: 0.16 0.12;
4123
- stroke-linecap: round;
4124
- }
4125
-
4126
- /* The map (Zoe, after the round): every square on one neutral ground, then light where only White reaches, dark where only Black does, half and half
4127
- when both do; the two counts together in the middle, as a domino. The drawings and the pieces step back */
4128
- .board.mapping ~ .arrows,
4129
- .board.mapping .move-badge {
4130
- opacity: 0.12;
4131
- }
4132
-
4133
- .board.mapping .square.noted::after {
4134
- opacity: 0.15;
4135
- }
4136
-
4137
- .board.mapping .piece {
4138
- opacity: 0.45;
4139
- }
4140
-
4141
- .control-ground {
4142
- position: absolute;
4143
- inset: 0;
4144
- pointer-events: none;
4145
- background: #8d96a1;
4146
- }
4147
-
4148
- .control-ground.white {
4149
- background: #eef1f4;
4150
- }
4151
-
4152
- .control-ground.black {
4153
- background: #2b323c;
4154
- }
4155
-
4156
- .control-ground.both {
4157
- background: linear-gradient(135deg, #eef1f4 50%, #2b323c 50%);
4158
- }
4159
-
4160
- .control-count {
4161
- position: absolute;
4162
- left: 50%;
4163
- top: 50%;
4164
- z-index: 1;
4165
- display: flex;
4166
- translate: -50% -50%;
4167
- border-radius: 4px;
4168
- overflow: hidden;
4169
- box-shadow: 0 0 0 1px rgba(17, 22, 29, 0.55);
4170
- pointer-events: none;
4171
- font: 800 clamp(10px, 2.2cqw, 17px) / 1 "Segoe UI", system-ui, sans-serif;
4172
- }
4173
-
4174
- .control-count b {
4175
- min-width: 1.35em;
4176
- padding: 0.2em 0.25em;
4177
- text-align: center;
4178
- }
4179
-
4180
- .control-count .white {
4181
- background: #fff;
4182
- color: #11161d;
4183
- }
4184
-
4185
- .control-count .black {
4186
- background: #11161d;
4187
- color: #fff;
4188
- }
4189
-
4190
- /* The helps' card in the game's column */
4191
- .helps-card {
4192
- display: flex;
4193
- flex-direction: column;
4194
- gap: 8px;
4195
- font-size: 13px;
4196
- min-height: 0;
4197
- flex: 0 1 auto;
4198
- /* No scrollbar in the page (Stefano): the card fits its column's width, and a column too short for it scrolls it under the wheel or the finger */
4199
- overflow: hidden auto;
4200
- scrollbar-width: none;
4201
- }
4202
-
4203
- .helps-title {
4204
- margin: 0;
4205
- font-size: 13px;
4206
- font-weight: 700;
4207
- color: var(--ink);
4208
- }
4209
-
4210
- .help-rows {
4211
- list-style: none;
4212
- margin: 0;
4213
- padding: 0;
4214
- display: flex;
4215
- flex-direction: column;
4216
- gap: 2px;
4217
- color: var(--soft);
4218
- }
4219
-
4220
- .help-rows li {
4221
- position: relative;
4222
- padding: 3px 6px 3px 26px;
4223
- border-radius: 6px;
4224
- line-height: 1.35;
4225
- }
4226
-
4227
- .help-rows li.points:hover {
4228
- background: color-mix(in srgb, var(--accent) 16%, transparent);
4229
- color: var(--ink);
4230
- }
4231
-
4232
- .help-rows li.quiet {
4233
- font-size: 12px;
4234
- }
4235
-
4236
- .help-rows .square-name {
4237
- color: var(--ink);
4238
- }
4239
-
4240
- /* The checks and the loose pieces in figures, as the move list draws them; the loose ones White's first, then Black's. */
4241
- .help-rows .help-move {
4242
- margin-right: 0.5em;
4243
- color: var(--ink);
4244
- font-weight: 600;
4245
- white-space: nowrap;
4246
- }
4247
-
4248
- .help-rows .help-pieces + .help-pieces {
4249
- margin-left: 0.4em;
4250
- padding-left: 0.6em;
4251
- border-left: 1px solid var(--line);
4252
- }
4253
-
4254
- .help-rows .help-notch {
4255
- left: 6px;
4256
- top: 4px;
4257
- bottom: auto;
4258
- width: 14px;
4259
- height: 14px;
4260
- }
4261
-
4262
- .help-rows .help-notch path {
4263
- fill: var(--ink);
4264
- stroke: none;
4265
- }
4266
-
4267
- .help-rows .help-notch circle {
4268
- fill: var(--card);
4269
- }
4270
-
4271
- .help-rows .row-icon {
4272
- position: absolute;
4273
- left: 6px;
4274
- top: 3px;
4275
- width: 14px;
4276
- height: 16px;
4277
- display: grid;
4278
- place-items: center;
4279
- color: var(--ink);
4280
- font-weight: 800;
4281
- }
4282
-
4283
- .helps-card .tabs {
4284
- display: flex;
4285
- gap: 4px;
4286
- border-bottom: 1px solid var(--line);
4287
- }
4288
-
4289
- .helps-card .tabs [role="tab"] {
4290
- border: 0;
4291
- background: none;
4292
- color: var(--soft);
4293
- font: inherit;
4294
- font-weight: 600;
4295
- padding: 4px 8px 6px;
4296
- border-bottom: 2px solid transparent;
4297
- margin-bottom: -1px;
4298
- cursor: pointer;
4299
- }
4300
-
4301
- .helps-card .tabs [role="tab"][aria-selected="true"] {
4302
- color: var(--ink);
4303
- border-bottom-color: var(--accent);
4304
- }
4305
-
4306
- /* The map's button: in the card's tabs, or under the board on a phone */
4307
- .map-button {
4308
- display: flex;
4309
- align-items: center;
4310
- gap: 5px;
4311
- border: 1px solid var(--line);
4312
- border-radius: 6px;
4313
- padding: 2px 8px;
4314
- background: var(--card);
4315
- color: var(--soft);
4316
- font: inherit;
4317
- font-size: 13px;
4318
- font-weight: 600;
4319
- cursor: pointer;
4320
- touch-action: none;
4321
- user-select: none;
4322
- }
4323
-
4324
- .tabs .map-button {
4325
- margin: 0 0 4px auto;
4326
- }
4327
-
4328
- .board-map .map-button {
4329
- padding: 6px 12px;
4330
- }
4331
-
4332
- .map-button svg {
4333
- width: 13px;
4334
- height: 13px;
4335
- fill: currentColor;
4336
- }
4337
-
4338
- .map-button small {
4339
- font-weight: 400;
4340
- }
4341
-
4342
- .map-button[aria-pressed="true"] {
4343
- background: var(--accent);
4344
- color: var(--on-accent);
4345
- border-color: var(--accent);
4346
- }
4347
-
4348
- .profile-table {
4349
- width: 100%;
4350
- border-collapse: collapse;
4351
- font-size: 12.5px;
4352
- color: var(--soft);
4353
- }
4354
-
4355
- .profile-table th,
4356
- .profile-table td {
4357
- padding: 2px 4px;
4358
- text-align: left;
4359
- font-weight: 400;
4360
- }
4361
-
4362
- .profile-table thead th {
4363
- color: var(--ink);
4364
- font-weight: 700;
4365
- }
4366
-
4367
- .profile-table tbody tr + tr {
4368
- border-top: 1px solid var(--line);
4369
- }
4370
-
4371
- /* A term with its meaning under the pointer, and under its line at a click or a tap (Rosa, T-117). */
4372
- .profile-table .term {
4373
- padding: 0;
4374
- border: 0;
4375
- background: none;
4376
- color: inherit;
4377
- font: inherit;
4378
- text-align: left;
4379
- text-decoration: underline dotted color-mix(in srgb, var(--soft) 60%, transparent);
4380
- text-underline-offset: 3px;
4381
- cursor: help;
4382
- }
4383
-
4384
- .profile-table tbody tr.meaning {
4385
- border-top: 0;
4386
- }
4387
-
4388
- .profile-table tr.meaning td {
4389
- padding-bottom: 4px;
4390
- font-size: 12px;
4391
- font-style: italic;
4392
- }
4393
-
4394
- .profile-foot {
4395
- margin: 6px 0 0;
4396
- font-size: 12px;
4397
- color: var(--soft);
4398
- }
1
+ /* The page's style, a sheet for each of its parts, in the order of the cascade */
2
+ @import "theme.css";
3
+ @import "base.css";
4
+ @import "layout/layout.css";
5
+ @import "board/board.css";
6
+ @import "talk/talk.css";
7
+ @import "game/game.css";
8
+ @import "helps/helps.css";
9
+ @import "dialogs/dialogs.css";