:root {
  --cam-accent: #ff3bd4;
  --cam-glow: rgba(255, 59, 212, 0.45);
  --bg: #0d1117;
  --panel: #151b24;
  --panel-soft: #1a2330;
  --text: #d8f6ff;
  --muted: #7ea8bf;
  --line: #2d3a4e;
  --accent: #00d1ff;
  --accent-2: #00ffa2;
  --danger: #ff5f8f;
  --neon-violet: #b388ff;
  --shadow: 0 16px 32px rgba(0, 0, 0, 0.35);
}

* {
  box-sizing: border-box;
}

html,
body {
  margin: 0;
  height: 100%;
  overflow: hidden;
}

body {
  background:
    radial-gradient(900px 420px at 10% -10%, rgba(63, 184, 255, 0.14), transparent 60%),
    radial-gradient(700px 440px at 100% -8%, rgba(46, 207, 153, 0.12), transparent 64%),
    var(--bg);
  color: var(--text);
  font-family: "Manrope", "Avenir Next", "Segoe UI", sans-serif;
}

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* Read by screen readers only. */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  border: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
}

/* ---------- language switch, top right ---------- */

.langSel {
  position: fixed;
  top: 12px;
  right: 14px;
  z-index: 9999;
  display: flex;
  gap: 4px;
  padding: 4px;
  border-radius: 999px;
  background: rgba(7, 6, 10, 0.82);
  backdrop-filter: blur(10px);
  border: 1px solid rgba(255, 255, 255, 0.14);
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
}

.langSel button {
  cursor: pointer;
  border: none;
  background: transparent;
  color: rgba(255, 255, 255, 0.55);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.04em;
  padding: 5px 9px;
  border-radius: 999px;
}

.langSel button:hover {
  color: #fff;
}

.langSel button[aria-pressed="true"] {
  color: #07060a;
  background: #ffd24a;
}

/* ---------- page ---------- */

.app-shell {
  width: min(1600px, 100%);
  margin: 0 auto;
  height: 100dvh;
  padding: 6px;
  display: grid;
  grid-template-rows: minmax(0, 1fr);
}

.panel {
  display: none;
}

.panel.active {
  display: grid;
  min-height: 0;
  height: 100%;
}

#panel-game {
  --label-width: 44px;
  --dock-width: 104px;
  --dock-gap: 12px;
  --board-size: min(calc(100dvh - 140px), calc(100vw - 200px));
  --toolbar-height: 44px;
  --bar-height: 56px;
  grid-template-columns: 1fr;
  align-items: center;
  justify-items: center;
}

/* Wide screens: rotate and flip at the top left, above the pieces (two
   columns) on the left, the board in the middle; the area above the board;
   erase and the camera right under it, the camera's right edge on the
   board's, the credit between them (as in the other two labs). */
.game-layout {
  display: grid;
  grid-template-columns: var(--dock-width) var(--board-size) var(--label-width);
  grid-template-rows: var(--toolbar-height) var(--board-size) var(--bar-height);
  grid-template-areas:
    "acts toolbar ."
    "dock main label"
    ". bar .";
  column-gap: var(--dock-gap);
  row-gap: 8px;
  align-items: start;
  justify-content: center;
  align-content: center;
  min-height: 0;
  max-width: 100%;
  max-height: 100%;
}

.side-brand {
  grid-area: bar;
  align-self: center;
  justify-self: center;
  position: relative;
  z-index: 1;
  max-width: calc(100% - 2 * (76px + 16px));
}

/* Back to the hub and print the kit: in the top strip, left of the
   language switch. */
.lab-nav {
  position: fixed;
  top: 13px;
  right: 180px;
  z-index: 9999;
}

.game-toolbar {
  grid-area: toolbar;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: var(--toolbar-height);
}

/* The area wears the board's colour, the camera's. */
.measure {
  --area-accent: var(--cam-accent);
}

.game-main {
  grid-area: main;
  width: var(--board-size);
  height: var(--board-size);
  min-height: 0;
}

/* ---------- board and camera ---------- */

.board-stage {
  min-height: 0;
  display: grid;
  place-items: center;
  position: relative;
  overflow: hidden;
  width: var(--board-size);
  height: var(--board-size);
  border-radius: 12px;
  transition: box-shadow 0.2s ease;
}

/* While the camera films, the board wears the camera's colour. */
body[data-fc-camera]:not([data-fc-camera="stopped"]) .board-stage {
  box-shadow: 0 0 0 2px var(--cam-accent), 0 0 26px var(--cam-glow);
}

/* The camera view: laid by app.js exactly over the drawn 20 x 20 grid. */
.board-camera-frame {
  position: absolute;
  z-index: 4;
  touch-action: none;
}

.board-camera-host {
  position: relative;
  width: 100%;
  height: 100%;
}

#game-board {
  width: 100%;
  height: 100%;
  aspect-ratio: 1 / 1;
  margin: 0;
  border-radius: 12px;
  border: 1px solid var(--line);
  background: #0f141c;
  touch-action: none;
  cursor: crosshair;
}

/* ---------- pieces ---------- */

.dock-panel {
  display: contents;
}

.piece-dock {
  grid-area: dock;
  width: var(--dock-width);
  display: grid;
  grid-template-columns: repeat(2, 48px);
  gap: 8px;
  justify-content: center;
}

.piece-btn {
  display: grid;
  place-items: center;
  border: 1px solid var(--line);
  background: var(--panel-soft);
  color: var(--text);
  border-radius: 10px;
  padding: 0;
  cursor: pointer;
  width: 48px;
  height: 48px;
  -webkit-tap-highlight-color: transparent;
}

.piece-preview {
  width: 88%;
  height: 88%;
  display: block;
}

.piece-btn.selected {
  border-color: color-mix(in srgb, var(--accent) 70%, white);
  background: color-mix(in srgb, var(--accent) 24%, var(--panel-soft));
}

.piece-btn.placed {
  opacity: 0.5;
}

.piece-actions {
  grid-area: acts;
  align-self: center;
  justify-self: start;
  display: flex;
  gap: 8px;
}

/* ---------- the board group ---------- */

.game-bar {
  --accent: var(--cam-accent);
  --accent-soft: rgba(255, 59, 212, 0.14);
  --accent-glow: var(--cam-glow);
  grid-area: bar;
  align-self: center;
  width: 100%;
}

/* ---------- narrow or portrait screens: area on top, then rotate and flip
   (back to the hub and print at the other end of their row), the board, the
   pieces in two rows, erase and the camera right under the pieces, then the
   credit; this group is centred in the room under the area, its rows 10 px
   apart, as in the other two labs ---------- */

@media (max-width: 1180px) {
  #panel-game {
    --board-size: max(96px, min(calc(100vw - 20px), calc(100dvh - 404px)));
    align-items: center;
  }

  .app-shell {
    padding: 6px 10px max(8px, env(safe-area-inset-bottom));
  }

  .game-layout {
    width: var(--board-size);
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: auto minmax(0, 1fr) auto auto auto auto auto minmax(0, 1fr);
    grid-template-areas:
      "toolbar"
      "."
      "acts"
      "main"
      "dock"
      "bar"
      "label"
      ".";
    row-gap: 10px;
    column-gap: 0;
    align-content: stretch;
    height: 100%;
  }

  .side-brand {
    grid-area: label;
    max-width: 100%;
  }

  .lab-nav {
    position: static;
  }

  .game-toolbar {
    justify-content: center;
  }

  .piece-dock {
    width: 100%;
    min-width: 0;
    grid-template-columns: repeat(6, minmax(0, 1fr));
    /* two rows of chips are kept from the start: filling the tray moves nothing */
    min-height: calc(2 * min(58px, (var(--board-size) - 40px) / 6) + 8px);
  }

  .piece-btn {
    width: 100%;
    height: auto;
    max-width: 58px;
    aspect-ratio: 1 / 1;
    justify-self: center;
  }

  .piece-actions {
    justify-self: stretch;
  }
}

/* Phones: the area pill shares the top strip with the language switch. */
@media (max-width: 640px) {
  .langSel {
    position: absolute;
  }

  .game-toolbar {
    justify-content: flex-start;
    padding-right: 172px;
  }
}

/* The narrowest phones: the board is narrower than the screen, so the top
   strip takes the screen's width and the area keeps clear of the switch. */
@media (max-width: 359px) {
  .game-toolbar {
    width: calc(100vw - 20px);
    margin-left: calc((var(--board-size) - 100vw + 20px) / 2);
  }
}

/* ---------- phones held sideways: a strip on top (rotate and flip on the
   left, the area in the middle, back to the hub, print and the language
   switch on the right), the board on the left under it, and on its right
   the pieces, then erase and the camera, then the credit. app.js sizes the
   board (--board-size) and the chips (--side-chip, --side-cols), and moves
   the area off the middle (--side-shift) only when it lacks room there. The
   query must match SIDEWAYS_LAYOUT_QUERY in app.js. ---------- */

@media (orientation: landscape) and (max-height: 500px) {
  #panel-game {
    --board-size: min(calc(100dvh - 74px), 52vw);
    --side-chip: 44px;
    --side-cols: 6;
    --side-shift: 0px;
    align-items: stretch;
    justify-items: stretch;
  }

  .app-shell {
    padding: 0;
  }

  .game-layout {
    position: relative;
    width: 100%;
    height: 100%;
    max-width: none;
    max-height: none;
    grid-template-columns: 10px var(--board-size) 16px minmax(0, 1fr) 10px;
    /* the spare height goes between the pieces and erase / the camera, so
       the credit ends 10 px above the bottom edge */
    grid-template-rows: 56px 8px auto minmax(8px, 1fr) auto 16px auto 10px;
    grid-template-areas:
      "toolbar toolbar toolbar toolbar toolbar"
      ". . . . ."
      ". main . dock ."
      ". main . . ."
      ". main . bar ."
      ". main . . ."
      ". main . label ."
      ". . . . .";
    row-gap: 0;
    column-gap: 0;
    align-content: stretch;
    justify-content: stretch;
  }

  .game-toolbar {
    width: 100%;
    height: 56px;
    margin-left: 0;
    padding: 0 max(0px, calc(-2 * var(--side-shift))) 0 max(0px, calc(2 * var(--side-shift)));
    justify-content: center;
    align-items: center;
    pointer-events: none;
  }

  .game-toolbar .measure {
    align-self: center;
    pointer-events: auto;
  }

  .piece-actions {
    grid-area: auto;
    position: absolute;
    left: 10px;
    top: 6px;
    z-index: 2;
  }

  .lab-nav {
    position: fixed;
    top: 6px;
    right: 180px;
  }

  .langSel {
    top: 5px;
  }

  .game-main {
    align-self: start;
    justify-self: start;
  }

  .piece-dock {
    width: auto;
    min-height: 0;
    justify-self: start;
    align-self: start;
    grid-template-columns: repeat(var(--side-cols), var(--side-chip));
    justify-content: start;
  }

  .piece-btn {
    width: var(--side-chip);
    height: var(--side-chip);
    max-width: none;
    justify-self: start;
  }

  .game-bar {
    width: 100%;
  }

  .side-brand {
    grid-area: label;
    justify-self: center;
    align-self: start;
    max-width: 100%;
    white-space: normal;
    text-align: center;
    text-wrap: balance;
  }
}
