/* ── Ap'lek operator dashboard ───────────────────────────────────────────────
   Hand-written, and deliberately so. This used to be Tailwind, which meant a
   build step and a compiler in the image to produce roughly this much CSS for
   three pages. There is no utility layer here: the pages use a couple of dozen
   class names that mean what they say.

   The TOKENS are not ours to invent. They come from the Trames MUI theme and
   are identical to the admin console's, because the same people use both in the
   same session — a "close enough" palette looks like a bug. If a token changes
   there, change it here.
   ──────────────────────────────────────────────────────────────────────────── */

/* `swap`: text is readable in the fallback while the font loads. The failure
   mode of `block` is a blank page on a bad connection. */
@font-face {
  font-family: 'MaisonNeue';
  src: url('/fonts/MaisonNeue-Book.woff2') format('woff2');
  font-weight: 400;
  font-display: swap;
}
@font-face {
  font-family: 'MaisonNeue';
  src: url('/fonts/MaisonNeue-Medium.woff2') format('woff2');
  font-weight: 500;
  font-display: swap;
}
@font-face {
  font-family: 'MaisonNeue';
  src: url('/fonts/MaisonNeue-Demi.woff2') format('woff2');
  font-weight: 600;
  font-display: swap;
}
@font-face {
  font-family: 'MaisonNeue';
  src: url('/fonts/MaisonNeue-Bold.woff2') format('woff2');
  font-weight: 700;
  font-display: swap;
}

:root {
  color-scheme: light;

  --primary: #2f58f7;
  --primary-text: #021d41;
  --secondary-text: #99adc0;
  --primary-bg: #ffffff;
  --secondary-bg: #f3f6f9;
  --placeholder: #8a99a7;
  --success: #3dcd58;
  --warning: #f5bb0a;
  --error: #f44336;

  --steel-gray: #8a99a7;
  --blue-gray: #808ea5;
  --powder-blue: #e2e8ef;
  --ghost-white: #f3f6f9;
  --frost-blue: #f0f3fe;
  --mint-green: #e2f8e6;
  --blush-pink: #ffe8e7;
  --cream: #ffefe4;
  --sapphire: #1e46c0;
  --deep-emerald: #026c45;
  --mustard: #c49708;
  --brick-red: #cc4f48;

  --shadow-primary: 0 2px 4px 0 rgba(101, 124, 162, 0.1);
  --scrollbar-track: rgba(211, 211, 211, 0.5);
  --scrollbar-thumb: #d3d3d3;
  --scrollbar-thumb-hover: #b6b5b5;

  --font-sans: 'MaisonNeue', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
    'Helvetica Neue', Arial, sans-serif;
}

/* darkTheme.colors, applied when the root carries data-theme="dark".
   The theme's `others` block is NOT used: those values are mechanical
   inversions that do not survive contact with a real UI (mintGreen → pink),
   so the supporting shades below are derived from the main dark colours with
   their semantic meaning kept intact. */
:root[data-theme='dark'] {
  color-scheme: dark;

  --primary: #4a90e2;
  --primary-text: #e3eaf5;
  --secondary-text: #a9b9d6;
  --primary-bg: #121f30;
  --secondary-bg: #182535;
  --placeholder: #c9d5e3;

  --steel-gray: #8fa3bc;
  --blue-gray: #a9b9d6;
  --powder-blue: #24354a;
  --ghost-white: #1b2938;
  --frost-blue: rgba(74, 144, 226, 0.16);
  --mint-green: rgba(61, 205, 88, 0.16);
  --blush-pink: rgba(244, 67, 54, 0.18);
  --cream: rgba(245, 187, 10, 0.16);
  --sapphire: #6ba7ea;
  --deep-emerald: #5bd973;
  --mustard: #f5bb0a;
  --brick-red: #ef7b74;

  --shadow-primary: 0 2px 4px 0 rgba(0, 0, 0, 0.35);
  --scrollbar-track: rgba(44, 59, 79, 0.5);
  --scrollbar-thumb: #2c3b4f;
  --scrollbar-thumb-hover: #33445c;
}

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

html,
body {
  margin: 0;
  min-height: 100vh;
  background: var(--secondary-bg);
  color: var(--primary-text);
  font-family: var(--font-sans);
  /* 15px, not 14. This is read at arm's length at the start of a shift, often
     on a laptop screen at whatever brightness the room allows — and it carries
     about a dozen facts in total, so there is no shortage of space to spend. */
  font-size: 15px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

a {
  color: inherit;
  text-decoration: none;
}

*::-webkit-scrollbar {
  width: 0.6rem;
  height: 5px;
}
*::-webkit-scrollbar-track {
  box-shadow: inset 0 0 6px var(--scrollbar-track);
  border-radius: 2.5px;
}
*::-webkit-scrollbar-thumb {
  border-radius: 2.5px;
  background: var(--scrollbar-thumb);
}
*::-webkit-scrollbar-thumb:hover {
  background: var(--scrollbar-thumb-hover);
}

/* ── Layout ───────────────────────────────────────────────────────────────── */

.page {
  max-width: 44rem;
  margin: 0 auto;
  padding: 32px 24px 64px;
}
.page--narrow {
  max-width: 44rem;
}

.header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 28px;
}
.header h1 {
  margin: 0;
  font-size: 22px;
  font-weight: 600;
}
.header .sub {
  margin: 3px 0 0;
  font-size: 13px;
  color: var(--steel-gray);
}
.header .actions {
  display: flex;
  align-items: center;
  gap: 8px;
}

.mono {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}
.muted {
  color: var(--steel-gray);
}
.nums {
  font-variant-numeric: tabular-nums;
}
.right {
  text-align: right;
}
.hidden {
  display: none !important;
}

/* ── Buttons ──────────────────────────────────────────────────────────────── */

.btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 9px 15px;
  border-radius: 6px;
  border: 1px solid var(--powder-blue);
  background: var(--primary-bg);
  color: var(--primary-text);
  font-family: inherit;
  font-size: 13px;
  cursor: pointer;
  transition: border-color 0.12s, color 0.12s, filter 0.12s;
}
.btn:hover {
  border-color: var(--primary);
  color: var(--primary);
}
.btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}
.btn--primary {
  background: var(--primary);
  border-color: var(--primary);
  color: #fff;
}
.btn--primary:hover {
  filter: brightness(0.95);
  color: #fff;
}
.btn--danger {
  background: var(--error);
  border-color: var(--error);
  color: #fff;
  font-weight: 500;
}
.btn--danger:hover {
  filter: brightness(0.95);
  color: #fff;
}
.btn--block {
  width: 100%;
  justify-content: center;
  padding: 10px 12px;
  font-size: 13px;
}

/* ── Cards ────────────────────────────────────────────────────────────────── */

.card {
  background: var(--primary-bg);
  border: 1px solid var(--powder-blue);
  border-radius: 8px;
  box-shadow: var(--shadow-primary);
  margin-bottom: 20px;
  overflow: hidden;
}
.card {
  margin-bottom: 24px;
}
.card__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 12px 22px 12px 16px;
  border-bottom: 1px solid var(--powder-blue);
}
.card__header h2 {
  margin: 0;
  font-size: 15px;
  font-weight: 600;
}
.card__header .note {
  font-size: 13px;
  color: var(--steel-gray);
}
.card__body {
  padding: 20px 22px;
  font-size: 14px;
}

/* ── Stats ────────────────────────────────────────────────────────────────── */

.stats {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 12px;
  margin-bottom: 20px;
}
@media (min-width: 720px) {
  .stats {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }
}
.stat {
  background: var(--primary-bg);
  border: 1px solid var(--powder-blue);
  border-radius: 8px;
  padding: 12px 14px;
  box-shadow: var(--shadow-primary);
}
.stat__label {
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.6px;
  text-transform: uppercase;
  color: var(--steel-gray);
}
.stat__value {
  margin-top: 4px;
  font-size: 22px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.stat__value--good {
  color: var(--deep-emerald);
}
.stat__value--warn {
  color: var(--mustard);
}
.stat__hint {
  margin-top: 2px;
  font-size: 11px;
  color: var(--steel-gray);
}

/* ── Tables ───────────────────────────────────────────────────────────────── */

.table-wrap {
  overflow-x: auto;
}
.table-wrap--tall {
  max-height: 22rem;
  overflow-y: auto;
}
table {
  width: 100%;
  border-collapse: collapse;
  font-size: 14px;
}
thead th {
  position: sticky;
  top: 0;
  background: var(--ghost-white);
  padding: 11px 14px;
  text-align: left;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.6px;
  text-transform: uppercase;
  color: var(--steel-gray);
  white-space: nowrap;
}
tbody td {
  padding: 13px 14px;
  border-top: 1px solid var(--powder-blue);
  vertical-align: middle;
}
tbody tr.is-today {
  background: var(--frost-blue);
}
th:first-child,
td:first-child {
  padding-left: 22px;
}
th:last-child,
td:last-child {
  padding-right: 22px;
}

/* ── Badges ───────────────────────────────────────────────────────────────── */

.badge {
  display: inline-block;
  padding: 2px 7px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 500;
  white-space: nowrap;
}
.badge--neutral {
  background: var(--ghost-white);
  color: var(--steel-gray);
}
.badge--info {
  background: var(--frost-blue);
  color: var(--primary);
}
.badge--success {
  background: var(--mint-green);
  color: var(--deep-emerald);
}
.badge--warning {
  background: var(--cream);
  color: var(--mustard);
}
.badge--danger {
  background: var(--blush-pink);
  color: var(--brick-red);
}
.badge--outline {
  border: 1px solid var(--powder-blue);
  color: var(--steel-gray);
}

/* ── Empty states ─────────────────────────────────────────────────────────── */

.empty {
  padding: 44px 24px;
  text-align: center;
}
.empty h3 {
  margin: 0;
  font-size: 15px;
  font-weight: 600;
}
.empty p {
  margin: 8px auto 0;
  max-width: 30rem;
  font-size: 13px;
  line-height: 1.6;
  color: var(--steel-gray);
}

/* ── Sign-in ──────────────────────────────────────────────────────────────── */

.signin {
  display: flex;
  min-height: 100vh;
  align-items: center;
  justify-content: center;
  padding: 24px;
}
.signin__box {
  width: 100%;
  max-width: 22rem;
}
.signin__title {
  margin: 0;
  text-align: center;
  font-size: 24px;
  font-weight: 600;
}
.signin__sub {
  margin: 6px 0 28px;
  text-align: center;
  font-size: 14px;
  color: var(--steel-gray);
}
.field {
  display: block;
  margin-bottom: 16px;
}
.field__label {
  display: block;
  margin-bottom: 6px;
  font-size: 12px;
  font-weight: 500;
  color: var(--steel-gray);
}
.field input {
  width: 100%;
  height: 44px;
  padding: 0 12px;
  border: 1px solid var(--powder-blue);
  border-radius: 6px;
  background: var(--primary-bg);
  color: var(--primary-text);
  font-family: inherit;
  font-size: 13px;
}
.field input::placeholder {
  color: var(--placeholder);
}
.field input:focus {
  outline: none;
  border-color: var(--primary);
  box-shadow: 0 0 0 3px rgba(47, 88, 247, 0.15);
}

/* One message at a time, in the one place the eye already is: under the form.
   It must not be a toast — the reason a sign-in failed is the whole content of
   the screen at that moment, and a timer would take it away mid-read. */
.notice {
  margin-top: 12px;
  padding: 9px 12px;
  border-radius: 6px;
  border-left: 3px solid var(--error);
  background: var(--blush-pink);
  color: var(--brick-red);
  font-size: 12px;
  line-height: 1.5;
}
.notice--info {
  border-left-color: var(--primary);
  background: var(--frost-blue);
  color: var(--primary);
}

/* ── Downloads ──────────────────────────────────────────────────────────── */

.build {
  padding: 22px 24px;
}
.build__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
}
.build__platform {
  margin: 0;
  font-size: 18px;
  font-weight: 600;
}
.build__meta {
  margin-top: 3px;
  font-size: 13px;
  color: var(--steel-gray);
}
.build__version {
  font-variant-numeric: tabular-nums;
  font-weight: 500;
  color: var(--primary-text);
}
.build__notes-label {
  margin-top: 18px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.7px;
  text-transform: uppercase;
  color: var(--steel-gray);
}
.build__notes {
  margin-top: 6px;
  font-size: 14px;
  line-height: 1.6;
  color: var(--secondary-text);
  /* The changelog is written as lines in the console, so it is shown as
     lines. */
  white-space: pre-wrap;
}

/* ── Loading ──────────────────────────────────────────────────────────────── */

/* The pages fetch their data, so there is a moment with nothing in them. A
   line of text rather than a spinner: it says what is happening, and it does
   not animate in a window somebody leaves open all shift. */
.loading {
  padding: 48px 20px;
  text-align: center;
  font-size: 12px;
  color: var(--steel-gray);
}

/* ── Classes that would otherwise be inline styles ────────────────────────────
   The pages are served with `style-src 'self'` and no `'unsafe-inline'`, which
   blocks `style="..."` attributes in markup outright — silently, with the page
   rendering unstyled in exactly one place and no error anywhere. So anything
   that looks like a one-off lives here instead.

   (`element.style.x = y` from a script is CSSOM, not an inline attribute, and
   is not affected. It is still avoided below, so the styling is in one file.) */

.card--form {
  padding: 24px;
  margin-bottom: 0;
}

.back-link {
  font-size: 12px;
  color: var(--steel-gray);
}
.back-link:hover {
  color: var(--primary-text);
}

.page-title {
  margin: 12px 0 0;
  font-size: 18px;
  font-weight: 600;
}
.page-intro {
  margin: 4px 0 0;
  font-size: 13px;
  line-height: 1.55;
  color: var(--secondary-text);
}
.page-header {
  margin-bottom: 24px;
}

/* The one number on the Today card that is read at a glance. */
.hours-large {
  font-size: 15px;
}

/* "today" / "next" beside a day, marking the row that answers the question. */
.tag {
  font-size: 11px;
  color: var(--primary);
}

/* Away time is amber wherever it appears, so it reads the same on this page as
   it does in the console. */
.away {
  color: var(--mustard);
}

.badge + .badge {
  margin-left: 6px;
}

/* ── Today ────────────────────────────────────────────────────────────────────
   The whole reason most people open this page, so it is the largest thing on
   it. A number read from across a desk, not a row in a table. */

.today {
  background: var(--primary-bg);
  border: 1px solid var(--powder-blue);
  border-left: 3px solid var(--primary);
  border-radius: 10px;
  padding: 22px 24px;
  margin-bottom: 24px;
  box-shadow: var(--shadow-primary);
}
.today--off {
  border-left-color: var(--powder-blue);
}
.today__label {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.7px;
  text-transform: uppercase;
  color: var(--steel-gray);
}
.today__time {
  margin-top: 6px;
  font-size: 30px;
  font-weight: 600;
  letter-spacing: -0.4px;
  font-variant-numeric: tabular-nums;
}
.today--off .today__time {
  font-size: 22px;
  color: var(--steel-gray);
}
.today__meta {
  margin-top: 4px;
  font-size: 14px;
  color: var(--secondary-text);
}

/* ── The month ───────────────────────────────────────────────────────────── */

.shifts {
  list-style: none;
  margin: 0;
  padding: 0;
}
.shift {
  display: grid;
  /* Fixed tracks, not `auto`. With auto the widest cell in each column set
     the width, so a row reading "13:15 – 21:30  Evening" and one reading
     "Off" produced different column edges and nothing lined up down the
     page. Every row now has all four cells, some of them empty. */
  grid-template-columns: 1fr 9.5rem 5.5rem 3.5rem;
  align-items: center;
  gap: 12px;
  padding: 14px 22px;
  border-top: 1px solid var(--powder-blue);
}
.shift:first-child {
  border-top: none;
}
/* Past days stay in the list — a month with the first half missing does not
   read as a month — but they recede. */
.shift--past {
  opacity: 0.45;
}
.shift--today {
  background: var(--frost-blue);
}
.shift__when {
  display: flex;
  flex-direction: column;
}
.shift__day {
  font-weight: 500;
}
.shift__date {
  font-size: 13px;
  color: var(--steel-gray);
}
.shift__time {
  font-variant-numeric: tabular-nums;
  font-size: 16px;
  font-weight: 500;
  white-space: nowrap;
  text-align: right;
}
.shift__name {
  font-size: 13px;
  color: var(--steel-gray);
  text-align: right;
}
/* Holds the column open on rows that are not today, so the times above and
   below a highlighted row do not step sideways. */
.tag-slot {
  display: block;
}
.tag {
  justify-self: end;
  padding: 2px 8px;
  border-radius: 999px;
  background: var(--primary);
  color: #fff;
  font-size: 11px;
  font-weight: 500;
  white-space: nowrap;
}

@media (max-width: 560px) {
  .shift {
    grid-template-columns: 1fr auto 3.5rem;
    row-gap: 2px;
  }
  /* The shift name tucks under the time rather than claiming a column of its
     own, which at this width would leave nothing for the day. */
  .shift__name {
    grid-column: 2;
    text-align: right;
  }
}

/* ── The week toggle ─────────────────────────────────────────────────────── */

.toggle-bar {
  display: flex;
  gap: 4px;
}
.toggle {
  padding: 5px 12px;
  border-radius: 7px;
  border: 1px solid transparent;
  background: transparent;
  color: var(--steel-gray);
  font-family: inherit;
  font-size: 14px;
  font-weight: 500;
  cursor: pointer;
}
.toggle:hover {
  color: var(--primary-text);
}
.toggle--on {
  background: var(--frost-blue);
  border-color: transparent;
  color: var(--primary);
}

/* A day off is a row like any other, just quieter — it is there so nobody has
   to count dates to work out whether Saturday is missing or free. */
.shift--off .shift__day {
  font-weight: 400;
  color: var(--steel-gray);
}
.shift__time--off {
  color: var(--steel-gray);
  font-weight: 400;
}

/* The list dims while the other week is on its way. Not a spinner: the swap is
   one small request and a spinner would flash rather than inform. */
.card.is-loading {
  opacity: 0.55;
  transition: opacity 0.12s ease;
}
.toggle:disabled {
  cursor: default;
}
