/* ---------------------------------------------------------------------------
   kiosk.css — the sign-in station.

   The look is carried over from the team's previous attendance app: the team
   photo under a purple wash, white cards, and colour-coded title bars. Students
   already know this screen, so it stays familiar.

   Written for a touch screen in a workshop, seen from a few feet away. No
   framework and no build step. Custom properties hold the shared colours, and
   they are readable in the browser's inspector at runtime.
--------------------------------------------------------------------------- */

:root {
  --purple: #667eea;
  --purple-deep: #764ba2;
  --purple-wash: linear-gradient(135deg, var(--purple) 0%, var(--purple-deep) 100%);

  --ink: #333;
  --ink-quiet: #999;
  --line: #e0e0e0;
  --key-line: #ddd;
  --tint: #f8f9fa;

  --in: #4caf50;
  --out: #f44336;

  --card-radius: 12px;
  --card-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);
  --gap: 15px;
}

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

/* The `hidden` attribute must win over any author `display` rule -- see the
   same note in admin.css. .banner and .boards-strip are both toggled with it. */
[hidden] { display: none !important; }

html, body { height: 100%; }

body {
  font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
  color: var(--ink);
  background: #4b4f8f url("../assets/Background.jpg") center / cover no-repeat fixed;
  padding: 10px;
  /* The kiosk is a fixed screen: the page itself never scrolls, only the
     roster does. Otherwise a stray swipe scrolls the header away and the
     screen looks broken to the next person. */
  overflow: hidden;
}

/* The purple wash over the photo. On its own layer so the photo stays sharp
   underneath and the cards above it stay pure white. */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  background: linear-gradient(135deg, rgba(102, 126, 234, 0.85) 0%, rgba(118, 75, 162, 0.85) 100%);
  z-index: -1;
}

.container {
  max-width: 1080px;
  height: 100%;
  margin: 0 auto;
  padding: 10px;
  display: flex;
  flex-direction: column;
}

/* --- Header ------------------------------------------------------------- */

.header {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 20px;
  margin-bottom: var(--gap);
  padding: 15px;
  background: white;
  border-radius: var(--card-radius);
  box-shadow: var(--card-shadow);
}

.header__logo {
  height: 60px;
  width: auto;
}

/* A link is an inline box, and an image inside one sits on the text baseline
   with a few pixels of gap beneath it. Making the link a flex box removes the
   gap so the right-hand logo lines up exactly with the left-hand one. */
.header__admin-link { display: flex; }

.header__text { text-align: center; }

h1 {
  font-size: 1.8em;
  color: var(--ink);
}

.header__today {
  color: #666;
  font-size: 0.95em;
}

.instructions {
  flex: 0 0 auto;
  margin-bottom: var(--gap);
  text-align: center;
  color: white;
  font-size: 0.95em;
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
}

/* --- Banner ------------------------------------------------------------- */

.banner {
  flex: 0 0 auto;
  margin-bottom: var(--gap);
  padding: 12px;
  text-align: center;
  font-weight: bold;
  color: #721c24;
  background: #f8d7da;
  border: 2px solid #f5c6cb;
  border-radius: var(--card-radius);
  box-shadow: var(--card-shadow);
}

/* --- Scoreboards -------------------------------------------------------- */

/* `flex: 0 0 auto` keeps the boards out of the fight for vertical space --
   .stage is the flexible one, so the roster gives and takes as they change. */
.boards-strip {
  flex: 0 0 auto;
  margin-bottom: var(--gap);
}

.boards {
  display: grid;
  /* auto-fit, not a fixed three columns: one board should not sit in a narrow
     strip with dead space beside it. Three boards still land three across. */
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: var(--gap);
}

.board {
  display: flex;
  flex-direction: column;
  min-width: 0;
  background: white;
  border-radius: var(--card-radius);
  box-shadow: var(--card-shadow);
  overflow: hidden;
}

/* --accent is set inline by boards.js from the board's own colour. The
   darker end of the gradient is that same colour mixed with black, so any
   colour an admin picks gets the same sheen as the old fixed bars had. */
.board__title {
  padding: 10px;
  text-align: center;
  font-size: 0.95em;
  font-weight: bold;
  color: white;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.25);
  background: linear-gradient(
    135deg,
    var(--accent, var(--purple)) 0%,
    color-mix(in srgb, var(--accent, var(--purple)) 75%, black) 100%
  );
}

/* The list caps its own height and scrolls, so a board with many places
   never pushes the roster off the screen. */
.board__list,
.board__empty {
  flex: 1;
  min-height: 100px;
  max-height: min(250px, 25vh);
  overflow-y: auto;
  padding: 8px;
  background: var(--tint);
  list-style: none;
}

.board__empty {
  padding: 20px 10px;
  text-align: center;
  color: var(--ink-quiet);
  font-size: 0.85em;
  font-style: italic;
}

.board__row {
  display: flex;
  align-items: center;
  margin-bottom: 4px;
  padding: 6px 8px;
  background: white;
  border: 1px solid #eee;
  border-radius: 4px;
  font-size: 0.85em;
}

.board__row:last-child { margin-bottom: 0; }

.board__rank {
  min-width: 24px;
  text-align: center;
  font-weight: bold;
  color: var(--purple);
  font-variant-numeric: tabular-nums;
}

.board__row[data-rank="1"] .board__rank { color: #ffd700; }
.board__row[data-rank="2"] .board__rank { color: #c0c0c0; }
.board__row[data-rank="3"] .board__rank { color: #cd7f32; }

/* A long name is truncated rather than wrapped, so rows stay one height and
   the boards line up across the strip. */
.board__name {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

.board__value {
  display: flex;
  align-items: center;
  gap: 5px;
  margin-left: 8px;
  font-weight: bold;
  color: var(--in);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

/* --- Rank insignia ------------------------------------------------------ */

/* Sized by where it sits; these are the defaults for a line of board text. */
.insignia {
  width: 22px;
  height: 22px;
  flex-shrink: 0;
  object-fit: contain;
}

/* --- Stage -------------------------------------------------------------- */

/* Whatever screen is current -- roster, number pad, or confirmation. It takes
   the height left over, and scrolls only if its screen is taller than that. */
.stage {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  overflow-y: auto;
}

.empty {
  padding: 48px 0;
  text-align: center;
  color: white;
  font-size: 1.1em;
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
}

/* --- Kiosk setup -------------------------------------------------------- */

.setup { display: flex; justify-content: center; padding: 24px 0; }

.setup__form {
  width: 100%;
  max-width: 440px;
  padding: 30px;
  background: white;
  border-radius: var(--card-radius);
  box-shadow: var(--card-shadow);
}

.setup__form h2 { margin-bottom: 6px; }
.setup__hint { margin-bottom: 20px; color: var(--ink-quiet); }
.setup__error { min-height: 1.4em; margin: 6px 0 12px; color: #721c24; }
.setup__form .button { width: 100%; }

.field { display: flex; flex-direction: column; gap: 5px; margin-bottom: 14px; }
.field__label { color: var(--ink-quiet); }

.field__input {
  min-height: 52px;
  padding: 0 14px;
  font: inherit;
  font-size: 1.1em;
  color: var(--ink);
  border: 2px solid var(--line);
  border-radius: 10px;
}

.field__input:focus { outline: 3px solid var(--purple); outline-offset: 2px; }

/* --- Roster ------------------------------------------------------------- */

/* The card fills the stage and only its grid scrolls, so the header with the
   signed-in count stays in view. */
.student-roster {
  flex: 1;
  min-height: 200px;
  display: flex;
  flex-direction: column;
  background: white;
  border-radius: var(--card-radius);
  box-shadow: var(--card-shadow);
  overflow: hidden;
}

.roster-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 12px 15px;
  background: var(--purple-wash);
}

.roster-title {
  font-size: 1.1em;
  color: white;
}

.roster-count {
  font-size: 0.95em;
  font-weight: 600;
  color: rgba(255, 255, 255, 0.9);
}

.roster-grid {
  flex: 1;
  overflow-y: auto;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  align-content: start;
}

/* Insignia and name on the left, the tick or cross pushed to the right edge
   by the name taking all the space between them. */
.roster-item {
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 14px;
  font: inherit;
  font-size: 0.95em;
  font-weight: 500;
  text-align: left;
  color: var(--ink);
  background: white;
  border: none;
  border-bottom: 1px solid var(--line);
  border-right: 1px solid var(--line);
  cursor: pointer;
  transition: background-color 0.15s ease;
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
}

/* The third column is the right edge of the card. */
.roster-item:nth-child(3n) { border-right: none; }

.roster-item:hover { background-color: #f5f5f5; }
.roster-item:active { background-color: #ebebeb; }

.roster-item:focus-visible {
  outline: 3px solid var(--purple);
  outline-offset: -3px;
}

/* A fixed-width slot even when empty, so names line up down the column. */
.roster-insignia {
  flex-shrink: 0;
  width: 34px;
  height: 34px;
}

.roster-insignia .insignia {
  width: 100%;
  height: 100%;
}

.roster-icon {
  flex-shrink: 0;
  width: 28px;
  height: 28px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.4em;
  font-weight: bold;
  border-radius: 50%;
}

.roster-item.signed-in .roster-icon {
  color: var(--in);
  background-color: rgba(76, 175, 80, 0.12);
}

.roster-item.signed-out .roster-icon {
  color: var(--out);
  background-color: rgba(244, 67, 54, 0.12);
}

.roster-name {
  flex: 1;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

.empty-list {
  grid-column: 1 / -1;
  padding: 20px 10px;
  text-align: center;
  color: var(--ink-quiet);
  font-size: 0.85em;
  font-style: italic;
}

/* --- Number pad --------------------------------------------------------- */

.numberpad {
  width: 100%;
  max-width: 500px;
  margin: 0 auto;
  padding: 25px;
  text-align: center;
  background: white;
  border-radius: var(--card-radius);
  box-shadow: var(--card-shadow);
}

.numberpad__who {
  font-size: 1.3em;
  color: var(--ink);
}

.numberpad__prompt {
  margin-bottom: 15px;
  color: #666;
}

/* This student's place on each board, in one purple bar.
   `min-height` on the rank and value holds the bar at its final height while
   the ranks are still loading, so the keypad below never shifts. */
.standings {
  display: flex;
  justify-content: space-around;
  gap: 10px;
  margin-bottom: 20px;
  padding: 12px;
  background: var(--purple-wash);
  border-radius: 8px;
}

.standings__item {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  color: white;
}

.standings__label {
  max-width: 100%;
  margin-bottom: 4px;
  font-size: 0.75em;
  text-transform: uppercase;
  opacity: 0.9;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

.standings__rank {
  min-height: 1.3em;
  font-size: 1.4em;
  font-weight: bold;
  line-height: 1.1;
  font-variant-numeric: tabular-nums;
}

.standings__value {
  min-height: 1.3em;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 4px;
  font-size: 0.85em;
  opacity: 0.9;
  font-variant-numeric: tabular-nums;
}

.numberpad__entry {
  display: flex;
  gap: 10px;
  margin-bottom: 10px;
}

.numberpad__display {
  flex: 1;
  min-height: 60px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.5em;
  letter-spacing: 3px;
  background: white;
  border: 2px solid var(--key-line);
  border-radius: 8px;
}

.numberpad__clear {
  padding: 15px 25px;
  font: inherit;
  font-weight: bold;
  color: white;
  background: var(--out);
  border: none;
  border-radius: 8px;
  cursor: pointer;
  transition: background 0.2s ease;
  touch-action: manipulation;
}

.numberpad__clear:hover { background: #da190b; }

/* Holds its space when empty so the keypad does not jump when an error
   appears; the pink box only shows once there is something to say. */
.numberpad__error {
  min-height: 1.5em;
  margin-bottom: 10px;
  padding: 6px;
  font-weight: bold;
  color: #721c24;
  background: #f8d7da;
  border: 2px solid #f5c6cb;
  border-radius: 8px;
}

.numberpad__error:empty {
  background: none;
  border-color: transparent;
}

.numberpad__keys {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 12px;
  margin-bottom: 20px;
}

.key {
  aspect-ratio: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  font: inherit;
  font-size: 1.8em;
  font-weight: bold;
  color: var(--ink);
  background: white;
  border: 2px solid var(--key-line);
  border-radius: 10px;
  box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
  cursor: pointer;
  transition: all 0.2s ease;
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
}

.key:hover {
  color: white;
  background: var(--purple);
  border-color: var(--purple);
  transform: translateY(-2px);
  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
}

.key:active { transform: translateY(0); }

.key:focus-visible {
  outline: 3px solid var(--purple);
  outline-offset: 2px;
}

.key--back {
  color: white;
  background: #ff9800;
  border-color: #ff9800;
}

.key--back:hover {
  background: #f57c00;
  border-color: #f57c00;
}

.key--empty {
  background: transparent;
  border: none;
  box-shadow: none;
  pointer-events: none;
}

.numberpad__actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 12px;
}

/* --- Buttons ------------------------------------------------------------ */

.button {
  min-width: 140px;
  padding: 15px 35px;
  font: inherit;
  font-size: 1.1em;
  font-weight: bold;
  color: white;
  border: none;
  border-radius: 10px;
  box-shadow: 0 3px 10px rgba(0, 0, 0, 0.2);
  cursor: pointer;
  transition: all 0.2s ease;
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
}

.button:hover {
  transform: translateY(-2px);
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
}

.button:active { transform: translateY(0); }

.button:disabled {
  opacity: 0.6;
  cursor: progress;
}

.button:focus-visible {
  outline: 3px solid var(--purple);
  outline-offset: 2px;
}

.button--sign-in { background: linear-gradient(135deg, #4caf50 0%, #45a049 100%); }
.button--sign-out { background: linear-gradient(135deg, #f44336 0%, #da190b 100%); }
.button--quiet { background: linear-gradient(135deg, #9e9e9e 0%, #757575 100%); }

/* --- Confirmation ------------------------------------------------------- */

.confirmation {
  width: 100%;
  max-width: 560px;
  margin: 24px auto;
  padding: 40px 32px;
  text-align: center;
  background: white;
  border-top: 8px solid var(--line);
  border-radius: var(--card-radius);
  box-shadow: var(--card-shadow);
}

.confirmation__mark {
  margin-bottom: 12px;
  font-size: 4em;
  line-height: 1;
}

.confirmation--in { border-top-color: var(--in); }
.confirmation--in .confirmation__mark { color: var(--in); }

.confirmation--out { border-top-color: var(--out); }
.confirmation--out .confirmation__mark { color: var(--out); }

.confirmation--problem { border-top-color: #721c24; }
.confirmation--problem .confirmation__mark { color: #721c24; }

.confirmation__headline {
  margin-bottom: 6px;
  font-size: 2em;
}

.confirmation__who {
  margin-bottom: 18px;
  font-size: 1.4em;
  color: #666;
}

.confirmation__reminder {
  margin-bottom: 22px;
  padding: 10px;
  font-weight: bold;
  color: #155724;
  background: #d4edda;
  border: 2px solid #c3e6cb;
  border-radius: 8px;
}

/* --- Rank-up celebration ------------------------------------------------ */

/* Over everything; a tap anywhere on it dismisses it. */
.celebration {
  position: fixed;
  inset: 0;
  z-index: 100;
  cursor: pointer;
  background: radial-gradient(circle at center, rgba(30, 15, 60, 0.15) 0%, rgba(30, 15, 60, 0.55) 100%);
  animation: celebration-dim 0.4s ease-out;
}

/* Must match LEAVE_MS in celebration.js. Taps pass through while it fades,
   so the one that dismissed it is the only one it swallows. */
.celebration--leaving {
  opacity: 0;
  transition: opacity 0.5s ease-in;
  pointer-events: none;
}

.celebration__fireworks {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}

/* The banner. A gradient border is a gradient background on the card with a
   white padding-box laid over it -- CSS borders cannot be gradients. */
.celebration__toast {
  position: absolute;
  top: 50%;
  left: 50%;
  width: min(760px, calc(100vw - 32px));
  border: 4px solid transparent;
  border-radius: 18px;
  background:
    linear-gradient(white, white) padding-box,
    linear-gradient(135deg, #ffd700, var(--purple), var(--purple-deep), #ffd700) border-box;
  box-shadow:
    0 0 0 6px rgba(255, 215, 0, 0.25),
    0 0 60px rgba(255, 215, 0, 0.55),
    0 20px 50px rgba(0, 0, 0, 0.45);
  overflow: hidden;
  transform: translate(-50%, -50%);
  animation: celebration-zoom 0.9s cubic-bezier(0.2, 0.9, 0.3, 1.2) both;
}

.celebration__banner {
  padding: 8px;
  text-align: center;
  font-size: 1.05em;
  font-weight: bold;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: white;
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.35);
  background: var(--purple-wash);
}

.celebration__body {
  display: flex;
  align-items: center;
  gap: 24px;
  padding: 22px 28px;
}

/* The insignia in a glowing gold ring, the way a game frames an icon. */
.celebration__badge {
  flex-shrink: 0;
  width: 128px;
  height: 128px;
  padding: 10px;
  border-radius: 50%;
  background: radial-gradient(circle, #fffbe6 0%, #ffe9a8 60%, #f5c542 100%);
  box-shadow: 0 0 0 4px #ffd700, 0 0 28px rgba(255, 215, 0, 0.8);
  animation: celebration-glow 1.6s ease-in-out 0.9s infinite alternate;
}

.celebration__badge .insignia {
  width: 100%;
  height: 100%;
}

.celebration__words {
  flex: 1;
  min-width: 0;
  text-align: center;
}

.celebration__name {
  font-size: 1.5em;
  font-weight: bold;
  color: var(--ink);
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

.celebration__rank {
  font-size: 2.3em;
  font-weight: 800;
  line-height: 1.15;
  background: linear-gradient(135deg, #f5a300 0%, #ffd700 45%, var(--purple-deep) 100%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.celebration__level {
  margin-top: 2px;
  font-size: 0.9em;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: #888;
}

.celebration__date {
  flex-shrink: 0;
  max-width: 120px;
  padding: 12px 14px;
  text-align: center;
  font-size: 0.95em;
  font-weight: bold;
  line-height: 1.3;
  color: white;
  background: var(--purple-wash);
  border-radius: 10px;
  box-shadow: 0 3px 10px rgba(0, 0, 0, 0.2);
}

/* From a speck to slightly too big, then settling: the overshoot is what makes
   it feel like it arrived rather than appeared. */
@keyframes celebration-zoom {
  0%   { transform: translate(-50%, -50%) scale(0.02); opacity: 0; }
  15%  { opacity: 1; }
  70%  { transform: translate(-50%, -50%) scale(1.08); }
  85%  { transform: translate(-50%, -50%) scale(0.97); }
  100% { transform: translate(-50%, -50%) scale(1); }
}

@keyframes celebration-glow {
  from { box-shadow: 0 0 0 4px #ffd700, 0 0 18px rgba(255, 215, 0, 0.6); }
  to   { box-shadow: 0 0 0 4px #ffd700, 0 0 40px rgba(255, 215, 0, 1); }
}

@keyframes celebration-dim {
  from { opacity: 0; }
}

/* --- Small screens ------------------------------------------------------ */

@media (max-width: 768px) {
  .roster-grid { grid-template-columns: 1fr; }
  .roster-item:nth-child(3n) { border-right: 1px solid var(--line); }
  .header__logo { height: 40px; }
  h1 { font-size: 1.3em; }
  .celebration__body { flex-direction: column; gap: 12px; }
  .celebration__date { max-width: none; }
}

/* A finger cannot hover; without this a tapped key stays lifted. */
@media (hover: none) {
  .key:hover,
  .button:hover {
    transform: none;
  }
}

/* Respect a reader who has asked for less motion. */
@media (prefers-reduced-motion: reduce) {
  .key, .button, .roster-item { transition: none; }
  .key:hover, .button:hover { transform: none; }
  .celebration__toast { animation: celebration-dim 0.4s ease-out both; }
  .celebration__badge { animation: none; }
}
