/*
  Styles for the board page. Serves R-002 (five colors plus a "not set" look that differs from all of them),
  R-013 (weekend circles), R-018 (layout and circle sizes), R-026 (small controls below the board),
  R-028 (own-row highlight), R-031 (board messages), R-020 (the color picker), R-021 (the Undo button), R-029 (the lost-connection notice) and R-036 (the sync notice).
  The board has no color key (R-018); each circle's hover text gives its color's name and meaning.
*/

:root {
  --color-black: #1a1a1a;
  --color-blue: #1f5fbf;
  --color-green: #1e7b34;
  --color-yellow: #f2c200;
  --color-red: #c62828;
  --color-text: #1a1a1a;
  --color-muted-text: #666666;
  --color-not-set-border: #888888;
  --color-page: #f5f5f5;
  --color-surface: #ffffff;
  --color-line: #e3e3e3;
  --color-own-row: #f3f6fb;
  --color-error: #a00000;
  --color-note-background: #333333;
  --color-note-text: #ffffff;
  --color-dim: rgba(0, 0, 0, 0.3);
  --color-chosen-outline: #1a1a1a;
  --color-disc-edge: #b0b0b0;
  --color-focus: #1f5fbf;
  /* Day circles: 60 px on a 375 px phone (R-018 asks for at least 40; the user chose 60), larger on wider screens. */
  --circle-size: clamp(60px, 16vw, 85px);
  /* Weekend circles are smaller (R-013): 40% of a day circle (the user's choice). */
  --weekend-circle-size: calc(var(--circle-size) * 0.4);
}

* {
  box-sizing: border-box;
}

body {
  margin: 0;
  font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  background: var(--color-page);
  color: var(--color-text);
}

/* The board is the page and starts at the top of the screen (R-026). */
main {
  max-width: 40rem;
  margin: 0 auto;
  padding: 0 1rem;
}

.message {
  margin: 0;
  padding: 1rem 0;
}

.message.error {
  color: var(--color-error);
  font-weight: bold;
}

.board {
  width: 100%;
  border-collapse: collapse;
  background: var(--color-surface);
}

/* The header row stays visible while the board scrolls (R-018). */
.board thead th {
  position: sticky;
  top: 0;
  z-index: 1;
  background: var(--color-surface);
  border-bottom: 1px solid var(--color-line);
  padding: 0.5rem 0.25rem;
  font-weight: normal;
}

.board .technician-heading {
  text-align: left;
  padding-left: 0.5rem;
  color: var(--color-muted-text);
}

.day-heading,
.weekend-heading {
  text-align: center;
  line-height: 1.2;
}

/* Day name prominent, date below in smaller text ("Fri" over "10/23"). */
.day-name {
  display: block;
  font-weight: bold;
  font-size: 1.1rem;
}

.day-date {
  display: block;
  font-size: 0.8rem;
  color: var(--color-muted-text);
}

/* Team names are visible but less prominent than technician names (R-018). */
.team-heading th {
  text-align: left;
  padding: 0.75rem 0.5rem 0.15rem;
  font-size: 0.8rem;
  font-weight: normal;
  color: var(--color-muted-text);
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

.board .technician {
  position: relative; /* The Undo button is placed over the end of the name (R-021). */
  text-align: left;
  padding: 0.3rem 0.5rem;
  font-size: 1.1rem;
  font-weight: 600;
  overflow-wrap: anywhere;
}

.board td {
  padding: 0.3rem 0.25rem;
  text-align: center;
  vertical-align: middle;
}

/* The signed-in technician's own row: a very faint highlight (R-028). */
.own-row th,
.own-row td {
  background: var(--color-own-row);
}

.circle {
  display: inline-block;
  width: var(--circle-size);
  height: var(--circle-size);
  border-radius: 50%;
  vertical-align: middle;
}

.circle.black {
  background: var(--color-black);
}

.circle.blue {
  background: var(--color-blue);
}

.circle.green {
  background: var(--color-green);
}

.circle.yellow {
  background: var(--color-yellow);
}

.circle.red {
  background: var(--color-red);
}

/* "Not set": an empty circle with a dashed outline, unlike any color (R-002, R-018). */
.circle.not-set {
  background: transparent;
  border: 2px dashed var(--color-not-set-border);
}

/* Weekend: Saturday's color on the left half, Sunday's on the right; one solid circle when they match (R-013).
   board.js sets --saturday and --sunday on each circle. */
.circle.weekend {
  width: var(--weekend-circle-size);
  height: var(--weekend-circle-size);
  padding: 0;
  border: none;
  cursor: pointer;
  background: linear-gradient(to right, var(--saturday) 50%, var(--sunday) 50%);
}

/* App name, signed-in name and Sign out: small, below the board, reached by scrolling on a phone (R-026). */
.controls {
  max-width: 40rem;
  margin: 1.5rem auto 0;
  padding: 0.75rem 1rem 1.5rem;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem 1rem;
  font-size: 0.85rem;
  color: var(--color-muted-text);
}

/* Its own line above the name and Sign out, for admins only (R-036). Plain text, so it does not rely on color. */
.sync-notice {
  flex-basis: 100%;
  margin: 0;
}

.sync-notice[hidden] {
  display: none;
}

.controls #account {
  display: flex;
  align-items: center;
  gap: 0.75rem;
}

.controls #account[hidden],
.button[hidden] {
  display: none;
}

.button {
  display: inline-block;
  padding: 0.25rem 0.75rem;
  border: 1px solid var(--color-not-set-border);
  border-radius: 0.3rem;
  color: var(--color-text);
  background: var(--color-surface);
  text-decoration: none;
}

/* Short notes, such as the weekend tap note (R-013), shown for about 3 seconds at the bottom of the screen. */
.note {
  position: fixed;
  left: 50%;
  bottom: 1.5rem;
  transform: translateX(-50%);
  max-width: calc(100% - 2rem);
  margin: 0;
  padding: 0.6rem 1rem;
  border-radius: 0.4rem;
  background: var(--color-note-background);
  color: var(--color-note-text);
  font-size: 0.95rem;
  z-index: 2;
}

/* A circle the viewer may change is a button that looks exactly like one they may not (R-020). */
button.circle {
  padding: 0;
  border: none;
  cursor: pointer;
}

/* Keyboard focus shows a ring; a mouse or finger tap does not. */
button.circle:focus-visible,
.undo-button:focus-visible {
  outline: 3px solid var(--color-focus);
  outline-offset: 2px;
}

/* The picker (R-020). The rest of the screen dims slightly while the picker stays bright. */
.picker-backdrop {
  position: fixed;
  inset: 0;
  z-index: 3;
  background: transparent;
  transition: background 250ms;
}

.picker-backdrop.open {
  background: var(--color-dim);
}

/* A zero-size point at the picker's center. picker.js sets its position, --from-x and --from-y (where the
   tapped circle is), the disc's size and closed scale, and each choice's --x and --y. */
.picker {
  position: fixed;
  width: 0;
  height: 0;
}

/* The white disc behind the choices hides the board (R-020). Closed, it is the tapped circle's size and
   place; open, it surrounds the whole picker. */
.picker-disc {
  position: absolute;
  left: calc(var(--disc-size) / -2);
  top: calc(var(--disc-size) / -2);
  width: var(--disc-size);
  height: var(--disc-size);
  border-radius: 50%;
  background: var(--color-surface);
  border: 1px solid var(--color-disc-edge);
  transform: translate(var(--from-x), var(--from-y)) scale(var(--disc-closed-scale));
  transition: transform 250ms;
}

.picker.open .picker-disc {
  transform: translate(0, 0) scale(1);
}

/* Every choice starts stacked on the tapped circle, behind the current one, and moves out to its place when open.
   The color choices are the tapped circle's size (--choice-size, R-020). */
.picker-choice {
  position: absolute;
  left: calc(var(--choice-size) / -2);
  top: calc(var(--choice-size) / -2);
  width: var(--choice-size);
  height: var(--choice-size);
  z-index: 1;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.5);
  outline: 3px solid transparent;
  outline-offset: 3px;
  transform: translate(var(--from-x), var(--from-y));
  transition: transform 250ms, outline-color 250ms;
}

.picker.open .picker-choice {
  transform: translate(var(--x), var(--y));
}

/* "Not set" stays an empty dashed circle, on white like the disc. It is smaller in the open picker (R-020), but
   closed it matches the tapped circle, so no white ring shows at the start or end of the animation. */
.picker-choice.not-set {
  background: var(--color-surface);
  width: var(--not-set-size);
  height: var(--not-set-size);
  left: calc(var(--not-set-size) / -2);
  top: calc(var(--not-set-size) / -2);
  transform: translate(var(--from-x), var(--from-y)) scale(var(--not-set-closed-scale));
}

.picker.open .picker-choice.not-set {
  transform: translate(0, 0) scale(1);
}

/* The current (or just picked) choice is outlined and drawn on top. */
.picker-choice.chosen {
  z-index: 2;
  outline-color: var(--color-chosen-outline);
}

.picker.fade-outline .picker-choice.chosen {
  outline-color: transparent;
}

.picker-choice:focus-visible {
  box-shadow: 0 0 0 3px var(--color-focus);
}

/* Undo: at the left of the row's color columns, over the end of the name, fading after 5 seconds (R-021). */
.undo-button {
  position: absolute;
  right: 0.25rem;
  top: 50%;
  transform: translateY(-50%);
  padding: 0.35rem 0.75rem;
  border: 1px solid var(--color-not-set-border);
  border-radius: 0.3rem;
  background: var(--color-surface);
  color: var(--color-text);
  font: inherit;
  font-size: 0.95rem;
  font-weight: normal;
  cursor: pointer;
  opacity: 1;
  transition: opacity 250ms;
}

.undo-button.fading {
  opacity: 0;
}

/* Lost connection (R-029): the whole screen dims slightly, the last board stays visible, and this layer, above
   everything else, catches every tap. */
.reconnecting {
  position: fixed;
  inset: 0;
  z-index: 4;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1rem;
  background: var(--color-dim);
}

.reconnecting[hidden] {
  display: none;
}

.reconnecting-notice {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.25rem;
  margin: 0;
  padding: 0.75rem 1.25rem;
  border-radius: 0.4rem;
  background: var(--color-note-background);
  color: var(--color-note-text);
  text-align: center;
}

.reconnecting-notice [hidden] {
  display: none;
}

/* On a device set to reduce motion, the picker and Undo appear and disappear without animation (R-020). */
@media (prefers-reduced-motion: reduce) {
  .picker-backdrop,
  .picker-disc,
  .picker-choice,
  .undo-button {
    transition: none;
  }
}
