/*
 * The student shell (SPEC §8.1). Brand tokens mirror src/react-app/index.css;
 * no external fonts or images (CLAUDE.md non-negotiable 6).
 *
 * Floors that are not negotiable: 16px text, 44px tap targets, visible focus,
 * and it must work on a 1366×768 Chromebook — the app gets everything below a
 * 44px top bar.
 */

:root {
  /* KiteQuad's colors (2026-10-24; src/react-app/index.css has the reasons). */
  --ink: #142B4F;
  --muted: #475467;
  --accent: #142B4F;
  --accent-strong: #142B4F;
  --accent-hover: #0E1B33;
  --accent-ink: #ffffff;
  --paper: #F4F7FB;
  --surface: #ffffff;
  --line: #d0d5dd;
  --danger: #b42318;
  --radius-card: 18px;
  --radius-input: 12px;
  --bar: 44px;
  --font: ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
  color-scheme: light;
}

*,
*::before,
*::after {
  box-sizing: border-box;
}

html,
body {
  height: 100%;
}

body {
  margin: 0;
  font-family: var(--font);
  font-size: 17px;
  line-height: 1.5;
  background: var(--paper);
  color: var(--ink);
  -webkit-font-smoothing: antialiased;
}

h1,
h2 {
  font-weight: 700;
  letter-spacing: -0.015em;
  line-height: 1.2;
}

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

h1:focus,
h2:focus {
  outline: none;
}

.root {
  min-height: 100vh;
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
}

/* ---------------------------------------------------------- screens */

.screen {
  flex: 1;
  display: grid;
  place-items: center;
  padding: 24px 16px;
}

.card {
  width: min(32rem, 100%);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-card);
  padding: 32px 28px;
  text-align: center;
}

.card h1 {
  font-size: 1.6rem;
  margin: 0 0 8px;
}

.card p {
  margin: 0;
  color: var(--muted);
}

.actions {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  justify-content: center;
  margin-top: 24px;
}

.spinner {
  width: 36px;
  height: 36px;
  margin: 0 auto 16px;
  border: 4px solid var(--line);
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: spin 0.8s linear infinite;
}

@keyframes spin {
  to {
    transform: rotate(360deg);
  }
}

@media (prefers-reduced-motion: reduce) {
  .spinner {
    animation: none;
  }
}

/* ---------------------------------------------------------- buttons */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  min-width: 44px;
  padding: 0 18px;
  font: inherit;
  font-size: 16px;
  font-weight: 600;
  border-radius: var(--radius-input);
  border: 2px solid var(--ink);
  background: var(--surface);
  color: var(--ink);
  text-decoration: none;
  cursor: pointer;
  touch-action: manipulation;
}

.btn:hover {
  background: var(--paper);
}

.btn-primary {
  background: var(--accent-strong);
  border-color: var(--accent-strong);
  color: var(--accent-ink);
}

.btn-primary:hover {
  background: var(--accent-hover);
}

.btn:disabled,
.btn[aria-disabled="true"] {
  opacity: 0.6;
  cursor: default;
}

/* ---------------------------------------------------------- app view */

.bar {
  flex: none;
  height: var(--bar);
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 0 4px 0 16px;
  background: var(--surface);
  border-bottom: 1px solid var(--line);
  overflow: hidden;
}

.bar-title {
  flex: 1;
  min-width: 0;
  margin: 0;
  font-size: 16px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.badge {
  flex: none;
  font-size: 16px;
  color: var(--muted);
  padding: 0 8px;
  white-space: nowrap;
}

.who {
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 0 8px;
  max-width: 14rem;
  font-size: 16px;
}

.nick {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* An emoji animal on the student's colour (src/shared/avatars.mjs). */
.avatar {
  flex: none;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  display: inline-grid;
  place-items: center;
  font-size: 18px;
  line-height: 1;
  color: #ffffff;
  background: var(--muted);
}

.avatar-large {
  width: 48px;
  height: 48px;
  font-size: 28px;
}

.bar .btn {
  flex: none;
  height: var(--bar);
  border: 0;
  border-radius: 0;
  padding: 0 14px;
  background: transparent;
}

.bar .btn:hover {
  background: var(--paper);
}

.bar .btn:focus-visible {
  outline-offset: -3px;
}

.bar-home {
  gap: 6px;
  padding: 0 12px;
  margin-right: 4px;
}

/* The app gets every pixel under the bar. Absolute, because a percentage
   height on a flex item's child doesn't resolve and an iframe falls back to 150px. */
.stage {
  flex: 1;
  position: relative;
  min-height: 0;
}

.app-frame {
  position: absolute;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
  border: 0;
  background: var(--surface);
}

/* On a phone the app matters more than the badge and the name. */
@media (max-width: 640px) {
  .badge,
  .bar-class {
    display: none;
  }
  .nick,
  .bar-home-label {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }
}

/* Sign-out wipe frames: loaded, never seen. */
.wipe {
  position: absolute;
  width: 0;
  height: 0;
  overflow: hidden;
}

.wipe iframe {
  width: 0;
  height: 0;
  border: 0;
}

/* ---------------------------------------------------------- report dialog */

.dialog {
  width: min(28rem, calc(100vw - 32px));
  padding: 28px 24px 24px;
  border: 1px solid var(--line);
  border-radius: var(--radius-card);
  background: var(--surface);
  color: var(--ink);
}

.dialog::backdrop {
  background: rgba(27, 31, 36, 0.55);
}

.dialog h2 {
  font-size: 1.35rem;
  margin: 0 0 12px;
}

.dialog p {
  margin: 0 0 8px;
}

.dialog fieldset {
  border: 0;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 8px;
}

.dialog legend {
  font-weight: 600;
  margin-bottom: 8px;
  padding: 0;
}

.choice {
  display: flex;
  align-items: center;
  gap: 12px;
  min-height: 44px;
  padding: 0 14px;
  border: 1px solid var(--line);
  border-radius: var(--radius-input);
  cursor: pointer;
  font-size: 16px;
}

.choice:has(input:checked) {
  border-color: var(--accent-strong);
  box-shadow: inset 0 0 0 1px var(--accent-strong);
}

.choice input {
  width: 20px;
  height: 20px;
  margin: 0;
  accent-color: var(--accent-strong);
}

.status {
  min-height: 1.5em;
  margin: 12px 0 0;
  color: var(--muted);
}

.dialog .actions {
  justify-content: flex-end;
  margin-top: 16px;
}

/* ------------------------------------------------------------ shared bits */

/* `hidden` must win over a class's display (a hidden .btn is still a flex box otherwise). */
[hidden] {
  display: none !important;
}

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.error,
.card .error {
  min-height: 1.5em;
  margin: 12px 0 0;
  color: var(--danger);
  font-weight: 600;
}

.card .error:empty {
  margin-top: 0;
}

.help {
  margin-top: 20px;
  text-align: left;
}

.help summary {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: 0 4px;
  font-weight: 600;
  color: var(--accent-strong);
  cursor: pointer;
}

.card .help p {
  margin: 4px 0 0;
}

.btn-big {
  width: 100%;
  min-height: 64px;
  font-size: 1.25rem;
  gap: 12px;
}

.btn-icon {
  font-size: 1.6rem;
  line-height: 1;
}

/* ------------------------------------------------------------ sign-in */

.signin-card {
  text-align: left;
}

.signin-card h1 {
  text-align: center;
  margin-bottom: 20px;
}

.or {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 20px 0;
  color: var(--muted);
}

.or::before,
.or::after {
  content: "";
  flex: 1;
  border-top: 1px solid var(--line);
}

.code-label {
  display: block;
  font-size: 1.15rem;
  font-weight: 700;
}

.card .hint {
  margin: 2px 0 10px;
}

.code-row {
  display: flex;
  gap: 10px;
}

.code-input {
  flex: 1;
  min-width: 0;
  min-height: 56px;
  padding: 0 14px;
  font: inherit;
  font-family: ui-monospace, "SF Mono", "Cascadia Mono", Menlo, monospace;
  font-size: 1.6rem;
  font-weight: 700;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--ink);
  background: var(--surface);
  border: 2px solid var(--ink);
  border-radius: var(--radius-input);
}

.code-input:focus-visible {
  outline-offset: 1px;
}

.code-row .btn {
  min-height: 56px;
  font-size: 1.1rem;
}

/* The roster gets room: ≥ 4 names a row on a 1366×768 Chromebook and on an iPad. */
.screen-wide {
  place-items: start center;
}

.signin-wide {
  width: min(72rem, 100%);
}

.card .class-name {
  font-size: 1.1rem;
}

.roster {
  list-style: none;
  margin: 20px 0 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(9rem, 1fr));
  gap: 12px;
}

.roster li {
  display: flex;
}

/* Avatar above the name: the name gets the tile's whole width. */
.tile {
  width: 100%;
  min-height: 96px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 12px 8px;
  font: inherit;
  font-size: 1.05rem;
  font-weight: 600;
  line-height: 1.25;
  text-align: center;
  color: var(--ink);
  background: var(--surface);
  border: 2px solid var(--line);
  border-radius: var(--radius-input);
  cursor: pointer;
  touch-action: manipulation;
}

.tile:hover {
  border-color: var(--accent-strong);
  background: var(--paper);
}

.tile-name {
  min-width: 0;
  overflow-wrap: anywhere;
}

.card .empty {
  margin-top: 20px;
}

/* PIN and pictures */

.pad-card {
  width: min(26rem, 100%);
  padding: 24px 24px 20px;
}

.pad-card-pictures {
  width: min(30rem, 100%);
}

.pad-who {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
}

.pad-who h1 {
  margin: 0;
  overflow-wrap: anywhere;
}

.card .pad-label {
  margin: 8px 0 16px;
  font-size: 1.1rem;
  color: var(--ink);
}

.dots {
  display: flex;
  justify-content: center;
  gap: 18px;
  margin-bottom: 18px;
}

.dot {
  width: 22px;
  height: 22px;
  border-radius: 50%;
  border: 3px solid var(--ink);
}

.dot.on {
  background: var(--ink);
}

.keys {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 10px;
}

.key {
  min-height: 64px;
  font: inherit;
  font-size: 1.6rem;
  font-weight: 700;
  color: var(--ink);
  background: var(--paper);
  border: 2px solid var(--line);
  border-radius: var(--radius-input);
  cursor: pointer;
  touch-action: manipulation;
}

.key-edit {
  font-size: 1.05rem;
}

.key:hover:not([aria-disabled="true"]) {
  border-color: var(--ink);
}

/* Held (checking, waiting, locked, class paused): aria-disabled rather than disabled, so the
   key a student just pressed keeps focus instead of dropping it to <body>. */
.key[aria-disabled="true"],
.pic[aria-disabled="true"] {
  opacity: 0.6;
  cursor: default;
}

.slots {
  display: flex;
  justify-content: center;
  gap: 16px;
  margin-bottom: 14px;
}

.slot {
  position: relative;
  width: 76px;
  height: 76px;
  display: grid;
  place-items: center;
  border: 3px dashed var(--line);
  border-radius: var(--radius-input);
  font-size: 2.6rem;
  line-height: 1;
}

.slot.filled {
  border-style: solid;
  border-color: var(--accent-strong);
}

.slot-n {
  position: absolute;
  top: 2px;
  left: 6px;
  font-size: 16px;
  font-weight: 700;
  color: var(--muted);
}

.pics {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 10px;
}

.pic {
  min-height: 96px;
  display: grid;
  place-items: center;
  gap: 2px;
  padding: 8px 4px;
  font: inherit;
  font-size: 16px;
  font-weight: 600;
  color: var(--ink);
  background: var(--paper);
  border: 2px solid var(--line);
  border-radius: var(--radius-input);
  cursor: pointer;
  touch-action: manipulation;
}

.pic:hover:not([aria-disabled="true"]) {
  border-color: var(--ink);
}

.pic-emoji {
  font-size: 2.6rem;
  line-height: 1.1;
}

.picpad .actions {
  margin-top: 14px;
}

.shake {
  animation: shake 0.35s ease-in-out;
}

@keyframes shake {
  25% {
    transform: translateX(-8px);
  }
  75% {
    transform: translateX(8px);
  }
}

@media (prefers-reduced-motion: reduce) {
  .shake {
    animation: none;
  }
}

/* Camera */

.scan-card {
  width: min(36rem, 100%);
}

.viewfinder-box {
  position: relative;
  margin: 16px auto 0;
  width: min(100%, 28rem);
  aspect-ratio: 4 / 3;
  background: var(--accent-hover);
  border-radius: var(--radius-input);
  overflow: hidden;
}

.viewfinder {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* A camera facing the student shows a mirror image, as a mirror would (camera.ts). */
.viewfinder.mirrored {
  transform: scaleX(-1);
}

.aim {
  position: absolute;
  inset: 18%;
  border: 4px solid #ffffff;
  border-radius: 12px;
  box-shadow: 0 0 0 9999px rgba(27, 31, 36, 0.25);
}

.scan-card .status {
  min-height: 1.5em;
  margin-top: 12px;
  color: var(--ink);
}

/* ---------------------------------------------------------------- home */

.home-bar {
  padding: 0 4px 0 8px;
}

.bar-class {
  flex: 1;
  min-width: 0;
  padding: 0 8px;
  color: var(--muted);
  font-size: 16px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.home {
  flex: 1;
  width: min(72rem, 100%);
  margin: 0 auto;
  padding: 28px 16px 40px;
}

.home-head {
  display: flex;
  align-items: center;
  gap: 16px;
}

.home-head h1 {
  font-size: 1.8rem;
  margin: 0;
}

.home-head p {
  margin: 4px 0 0;
  color: var(--muted);
  overflow-wrap: anywhere;
}

.tiles {
  list-style: none;
  margin: 24px 0 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(14rem, 1fr));
  gap: 14px;
}

.app-tile {
  min-height: 88px;
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 14px 16px;
  color: var(--ink);
  text-decoration: none;
  font-size: 1.1rem;
  font-weight: 700;
  background: var(--surface);
  border: 2px solid var(--line);
  border-radius: var(--radius-card);
}

.app-tile:hover {
  border-color: var(--accent-strong);
}

.tile-mark {
  flex: none;
  width: 52px;
  height: 52px;
  display: grid;
  place-items: center;
  border-radius: 14px;
  color: #ffffff;
  font-size: 1.5rem;
  font-weight: 800;
}

.tile-title {
  min-width: 0;
  overflow-wrap: anywhere;
}

.home-empty {
  margin-top: 24px;
  padding: 24px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-card);
  color: var(--muted);
}

/* A Chromebook's 1366×768 screen leaves about 640px for the page once the
   browser's bars and the shelf are taken; an iPad on its side in Safari about
   the same. The picture pad (nine 96px pictures, the slots, Start over, the
   answer and "Not you? Go back") is taller than that, so on short screens it
   tightens up — pictures stay well over the 44px tap floor — and the answer
   and the way back stay on screen (tests/e2e/60-student.mjs measures it). */
@media (max-height: 760px) {
  .screen {
    padding-top: 12px;
    padding-bottom: 12px;
  }
  .pad-card-pictures {
    padding: 16px 24px;
  }
  .pad-card-pictures .pad-label {
    margin: 4px 0 8px;
  }
  .pad-card-pictures .slots {
    gap: 12px;
    margin-bottom: 8px;
  }
  .pad-card-pictures .slot {
    width: 60px;
    height: 60px;
    font-size: 2.1rem;
  }
  .pad-card-pictures .pics {
    gap: 8px;
  }
  .pad-card-pictures .pic {
    min-height: 76px;
    padding: 4px;
  }
  .pad-card-pictures .pic-emoji {
    font-size: 2.1rem;
  }
  .pad-card-pictures .picpad .actions {
    margin-top: 8px;
  }
  .pad-card-pictures .error {
    margin-top: 8px;
  }
  .pad-card-pictures > .actions {
    margin-top: 12px;
  }
  .pad-card-pictures .help {
    margin-top: 8px;
  }
}

/* An iPad on its side and a Chromebook both fit; a phone stacks. */
@media (max-width: 480px) {
  .code-row {
    flex-direction: column;
  }
  .pad-card,
  .pad-card-pictures {
    padding: 20px 14px 16px;
  }
}
