/* =====================================================================
   MGEN x EPD Field Operations & Reporting Platform
   Mobile-first stylesheet.

   Written for a crew member holding a phone in one hand at a refuse
   collection point, not for a designer at a 27" monitor:

   - every control is at least 44px tall (Apple's minimum touch target)
   - nothing is revealed only on :hover, because a touchscreen has no hover
   - wide tables collapse into stacked cards below 720px
   - base font size is 16px so iOS Safari does not zoom on focus
   ===================================================================== */

:root {
  --c-bg: #f4f6f8;
  --c-surface: #ffffff;
  --c-border: #d8dee5;
  --c-text: #1c2733;
  --c-muted: #5b6b7c;
  --c-primary: #1f6feb;
  --c-primary-dark: #1a5ac4;
  --c-success: #1a7f4b;
  --c-warning: #a86400;
  --c-danger: #b3261e;
  --c-danger-bg: #fdecea;
  --c-warning-bg: #fff5e0;
  --c-success-bg: #e7f5ec;
  --c-info-bg: #e8f0fe;

  --radius: 8px;
  --gap: 1rem;
  --touch: 44px;
}

*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  font-size: 16px;
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--c-bg);
  color: var(--c-text);
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Noto Sans TC",
    "Microsoft JhengHei", Roboto, "Helvetica Neue", Arial, sans-serif;
  line-height: 1.5;
}

/* ---------------------------------------------------------------- layout */
.wrap {
  max-width: 1100px;
  margin: 0 auto;
  padding: var(--gap);
}

/* A working screen, not a reading one (U-25, David: 「個畫面可唔可以用盡少少」).
   A fortnight of columns does not fit in a reading column, and every pixel of
   margin was a day the administrator had to scroll to.

   But not to the glass: 「好似都攞得太盡, 驚唔同 Size mon 都有變數, 左右留小小
   空間」 (2026-09-17). The first version used the full width with a 12px pad, and
   on his monitor the 「下一段」 button sat on the edge of the window. The gutter
   now grows with the window — 12px on a laptop, ~28px at 1900 — and the page
   stops at 1900px and centres, so a very wide monitor does not stretch fifty
   name rows across a metre of desk. */
.wrap.wide {
  max-width: 1900px;
  padding: 0.6rem clamp(0.75rem, 1.6vw, 2rem) 1rem;
}

.site-header {
  background: var(--c-surface);
  border-bottom: 1px solid var(--c-border);
  position: sticky;
  top: 0;
  z-index: 10;
}

.site-header .bar {
  max-width: 1100px;
  margin: 0 auto;
  padding: 0.5rem var(--gap);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  flex-wrap: wrap;
}

.brand {
  font-weight: 700;
  font-size: 1rem;
  color: var(--c-text);
  text-decoration: none;
}

.brand small {
  display: block;
  font-weight: 400;
  font-size: 0.75rem;
  color: var(--c-muted);
}

/* Navigation scrolls sideways on a phone instead of wrapping into a wall. */
.nav {
  display: flex;
  gap: 0.25rem;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  width: 100%;
  padding-bottom: 0.25rem;
}

.nav a {
  flex: 0 0 auto;
  min-height: var(--touch);
  display: inline-flex;
  align-items: center;
  padding: 0 0.9rem;
  border-radius: var(--radius);
  color: var(--c-muted);
  text-decoration: none;
  font-size: 0.95rem;
  white-space: nowrap;
}

.nav a.active,
.nav a[aria-current="page"] {
  background: var(--c-info-bg);
  color: var(--c-primary-dark);
  font-weight: 600;
}

.user-chip {
  font-size: 0.85rem;
  color: var(--c-muted);
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

/* ---------------------------------------------------------------- cards */
.card {
  background: var(--c-surface);
  border: 1px solid var(--c-border);
  border-radius: var(--radius);
  padding: var(--gap);
  margin-bottom: var(--gap);
}

.card > h2,
.card > h3 {
  margin-top: 0;
}

.grid {
  display: grid;
  gap: var(--gap);
  grid-template-columns: 1fr;
}

@media (min-width: 720px) {
  .grid.cols-2 {
    grid-template-columns: 1fr 1fr;
  }
  .grid.cols-3 {
    grid-template-columns: repeat(3, 1fr);
  }
}

.stats {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 0.75rem;
}

@media (min-width: 560px) {
  .stats {
    grid-template-columns: repeat(4, 1fr);
  }
}

.stat {
  background: var(--c-surface);
  border: 1px solid var(--c-border);
  border-radius: var(--radius);
  padding: 0.75rem;
  text-align: center;
}

.stat .n {
  display: block;
  font-size: 1.6rem;
  font-weight: 700;
  line-height: 1.1;
}

.stat .l {
  font-size: 0.78rem;
  color: var(--c-muted);
}

/* --------------------------------------------------------------- tables */
.table-wrap {
  overflow-x: auto;
}

table.data {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.95rem;
}

table.data th,
table.data td {
  text-align: left;
  padding: 0.6rem 0.5rem;
  border-bottom: 1px solid var(--c-border);
  vertical-align: top;
}

table.data th {
  font-size: 0.8rem;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--c-muted);
}

/* Below 720px each row becomes its own card, labelled from data-label.
   A horizontally scrolling table is unusable one-handed. */
@media (max-width: 719px) {
  table.data thead {
    display: none;
  }
  table.data,
  table.data tbody,
  table.data tr,
  table.data td {
    display: block;
    width: 100%;
  }
  table.data tr {
    border: 1px solid var(--c-border);
    border-radius: var(--radius);
    margin-bottom: 0.75rem;
    padding: 0.25rem 0.5rem;
    background: var(--c-surface);
  }
  table.data td {
    border-bottom: none;
    padding: 0.35rem 0;
    display: flex;
    justify-content: space-between;
    gap: 1rem;
  }
  table.data td::before {
    content: attr(data-label);
    font-size: 0.78rem;
    text-transform: uppercase;
    color: var(--c-muted);
    flex: 0 0 40%;
  }
}

/* ---------------------------------------------------------------- forms */
.field {
  margin-bottom: var(--gap);
}

.field label {
  display: block;
  font-weight: 600;
  font-size: 0.9rem;
  margin-bottom: 0.3rem;
}

.input,
input[type="text"],
input[type="password"],
input[type="email"],
input[type="number"],
input[type="date"],
input[type="time"],
select,
textarea {
  width: 100%;
  min-height: var(--touch);
  padding: 0.6rem 0.7rem;
  font-size: 1rem; /* 16px prevents iOS zoom-on-focus */
  font-family: inherit;
  color: var(--c-text);
  background: var(--c-surface);
  border: 1px solid var(--c-border);
  border-radius: var(--radius);
}

textarea {
  min-height: 5rem;
}

.helptext {
  display: block;
  font-size: 0.82rem;
  color: var(--c-muted);
  margin-top: 0.25rem;
}

.errorlist {
  list-style: none;
  margin: 0.35rem 0 0;
  padding: 0.5rem 0.7rem;
  background: var(--c-danger-bg);
  color: var(--c-danger);
  border-radius: var(--radius);
  font-size: 0.88rem;
}

ul.checkboxes {
  list-style: none;
  margin: 0;
  padding: 0;
}

ul.checkboxes li label {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  min-height: var(--touch);
  font-weight: 400;
}

input[type="checkbox"],
input[type="radio"] {
  width: 1.25rem;
  height: 1.25rem;
}

/* -------------------------------------------------------------- buttons */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.4rem;
  min-height: var(--touch);
  padding: 0 1.1rem;
  border: 1px solid transparent;
  border-radius: var(--radius);
  background: var(--c-primary);
  color: #fff;
  font-size: 1rem;
  font-weight: 600;
  text-decoration: none;
  cursor: pointer;
}

.btn:active {
  background: var(--c-primary-dark);
}

.btn.secondary {
  background: var(--c-surface);
  color: var(--c-text);
  border-color: var(--c-border);
}

.btn.danger {
  background: var(--c-danger);
}

.btn.block {
  width: 100%;
}

.btn-row {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-top: var(--gap);
}

/* --------------------------------------------------------------- badges */
.badge {
  display: inline-block;
  padding: 0.15rem 0.55rem;
  border-radius: 999px;
  font-size: 0.75rem;
  font-weight: 600;
  white-space: nowrap;
  background: var(--c-info-bg);
  color: var(--c-primary-dark);
}

.badge.SCHEDULED { background: var(--c-info-bg); color: var(--c-primary-dark); }
.badge.RESCHEDULED { background: var(--c-warning-bg); color: var(--c-warning); }
.badge.CANCELLED { background: var(--c-danger-bg); color: var(--c-danger); }
.badge.COMPLETED { background: var(--c-success-bg); color: var(--c-success); }
.badge.PENDING { background: var(--c-warning-bg); color: var(--c-warning); }
.badge.ACTIVE { background: var(--c-success-bg); color: var(--c-success); }
.badge.INACTIVE { background: #eceff2; color: var(--c-muted); }
.badge.SUSPENDED { background: var(--c-danger-bg); color: var(--c-danger); }
.badge.internal { background: #efe6ff; color: #5b2ea6; }

/* Shift application window (WP01). Prefixed so the values cannot collide with
   the schedule statuses above. */
.badge.APP_NOT_OPEN { background: #eceff2; color: var(--c-muted); }
.badge.APP_OPEN { background: var(--c-success-bg); color: var(--c-success); }
.badge.APP_CLOSED { background: var(--c-warning-bg); color: var(--c-warning); }
/* Individual application status. */
.badge.SUBMITTED { background: var(--c-success-bg); color: var(--c-success); }
.badge.WITHDRAWN { background: #eceff2; color: var(--c-muted); }

/* A POST button that sits inline next to other controls. */
.inline-form {
  display: inline-block;
  margin: 0.15rem 0;
}

.btn.small {
  min-height: 36px;
  padding: 0 0.7rem;
  font-size: 0.9rem;
}

/* A prominent notice — used for "the pool is not the roster". */
.notice {
  border: 1px solid var(--c-warning);
  background: var(--c-warning-bg);
  color: var(--c-warning);
  border-radius: var(--radius);
  padding: 0.6rem 0.8rem;
  margin-bottom: var(--gap);
  font-weight: 600;
}

/* Crew shift cards: one card per shift, no horizontal table on a phone. */
.shift-cards {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 0.75rem;
}

.shift-card {
  border: 1px solid var(--c-border);
  border-radius: var(--radius);
  padding: 0.75rem;
  background: var(--c-surface);
}

.shift-card .shift-card-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 0.5rem;
  flex-wrap: wrap;
}

.shift-card .shift-card-date {
  font-weight: 700;
}

.shift-card dl {
  margin: 0.4rem 0 0;
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 0.2rem 0.75rem;
  font-size: 0.95rem;
}

.shift-card dt {
  color: var(--c-muted);
  font-size: 0.8rem;
}

.shift-card dd {
  margin: 0;
}

.shift-card .btn-row {
  margin-top: 0.6rem;
}

/* ------------------------------------------------------------- messages */
.messages {
  list-style: none;
  margin: 0 0 var(--gap);
  padding: 0;
}

.messages li {
  padding: 0.7rem 0.9rem;
  border-radius: var(--radius);
  margin-bottom: 0.5rem;
  font-size: 0.95rem;
}

.messages li.success { background: var(--c-success-bg); color: var(--c-success); }
.messages li.error { background: var(--c-danger-bg); color: var(--c-danger); }
.messages li.warning { background: var(--c-warning-bg); color: var(--c-warning); }
.messages li.info { background: var(--c-info-bg); color: var(--c-primary-dark); }

/* ---------------------------------------------------------------- misc */
.muted { color: var(--c-muted); }
.small { font-size: 0.85rem; }
.mono { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; }
.nowrap { white-space: nowrap; }

.page-title {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-bottom: var(--gap);
}

.page-title h1 {
  font-size: 1.35rem;
  margin: 0;
}

.filters {
  display: grid;
  gap: 0.5rem;
  grid-template-columns: 1fr;
  margin-bottom: var(--gap);
}

@media (min-width: 640px) {
  .filters {
    grid-template-columns: 2fr 1fr 1fr auto;
    align-items: end;
  }
}

.empty {
  padding: 1.5rem;
  text-align: center;
  color: var(--c-muted);
}

.placeholder {
  border: 1px dashed var(--c-border);
  border-radius: var(--radius);
  padding: 1rem;
  color: var(--c-muted);
  background: var(--c-surface);
}

.internal-block {
  border-left: 3px solid #5b2ea6;
  background: #faf7ff;
  padding: 0.6rem 0.8rem;
  border-radius: 0 var(--radius) var(--radius) 0;
  margin-top: 0.5rem;
}

.timeline {
  list-style: none;
  margin: 0;
  padding: 0;
}

.timeline li {
  border-left: 2px solid var(--c-border);
  padding: 0 0 1rem 0.9rem;
  margin-left: 0.3rem;
  position: relative;
}

.timeline li::before {
  content: "";
  position: absolute;
  left: -0.34rem;
  top: 0.4rem;
  width: 0.6rem;
  height: 0.6rem;
  border-radius: 50%;
  background: var(--c-primary);
}

.site-footer {
  padding: var(--gap);
  text-align: center;
  color: var(--c-muted);
  font-size: 0.8rem;
}

/* Roster block inside the activity workspace (S2-005 / S2-015). One row per
   person, wrapping on a phone rather than scrolling sideways. */
.roster-block {
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px solid var(--c-border);
}

.roster-block h3 {
  margin: 12px 0 6px;
  font-size: 0.95rem;
}

.assignment-row {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  align-items: center;
  padding: 6px 0;
  border-bottom: 1px dashed var(--c-border);
}

.assignment-row .input {
  width: auto;
  min-width: 140px;
  flex: 1 1 140px;
}

/* Paste-from-Excel grid (S5-001). Dense on purpose: the operator is checking a
   block of rows against a spreadsheet, so compact rows beat comfortable ones. */
table.data.grid td {
  padding: 4px 6px;
  vertical-align: middle;
}

table.data.grid .grid-number {
  color: var(--c-muted);
  font-size: 0.85rem;
  text-align: right;
}

.grid-input {
  width: 100%;
  min-width: 6rem;
  padding: 5px 7px;
  font-size: 0.9rem;
}

.grid-status .badge {
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.grid-footer {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  align-items: center;
  justify-content: space-between;
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px solid var(--c-border);
}

kbd {
  padding: 1px 5px;
  border: 1px solid var(--c-border);
  border-bottom-width: 2px;
  border-radius: 4px;
  background: #f6f8fa;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.85em;
}

/* The estate cell is a picker, so it needs room for a full name plus the
   browser's dropdown arrow. */
table.data.grid td .grid-input[list] {
  min-width: 13rem;
}

table.data.grid td .row-select,
table.data.grid th #select-all-rows {
  width: 16px;
  height: 16px;
}

/* U-08 (David, 2026-09-14 UAT): the header and the body were misaligned
   because the table carries the class "grid", which the layout utility above
   turns into display:grid — so <thead> and <tbody> became two independent grid
   items, each sizing its own columns. The table is forced back to being a
   table, a <colgroup> fixes the column plan, the header does not wrap, and
   every status cell always carries a badge (「未填」 for an empty row).
   Narrower screens scroll the .table-wrap container, never the page. */
table.data.grid {
  display: table;
  gap: 0;
  table-layout: fixed;
  width: 100%;
  min-width: 1000px;
}
table.data.grid th,
table.data.preview-grid th {
  white-space: nowrap;
  text-transform: none;
  padding: 0.5rem 0.4rem;
}
table.data.grid .th-exception .small { display: block; text-transform: none; letter-spacing: 0; }
table.data.grid col.col-select { width: 2.25rem; }
table.data.grid col.col-num    { width: 2.5rem; }
table.data.grid col.col-estate { width: 13rem; }
table.data.grid col.col-date   { width: 7.25rem; }
table.data.grid col.col-head   { width: 4.75rem; }
table.data.grid col.col-ref    { width: 6.5rem; }
table.data.grid col.col-notes  { width: auto; }   /* takes whatever is left */
table.data.grid col.col-status { width: 6.5rem; }
table.data.grid col.col-remove { width: 2.5rem; }
table.data.grid td .grid-input,
table.data.grid td .grid-input[list] {
  min-width: 0;             /* the column, not the input, sets the width now */
  width: 100%;
  box-sizing: border-box;
}
table.data.grid td.grid-status { overflow: hidden; }
.badge.EMPTY { background: #f1f3f5; color: var(--c-muted); }
.badge.CONFLICT { background: #fff1e0; color: #9a4b00; }
.visually-hidden {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap;
}
table.data tr.row-problem td { background: #fff7f7; }
table.data tr.row-problem td:first-child { border-left: 3px solid var(--c-danger); }
.text-danger { color: var(--c-danger); }

/* .xlsx preview (S5-001 §8): twelve read-only columns sized by the browser's
   automatic layout; dates and short Chinese labels never wrap, and a row's
   problems/reminders sit in a full-width detail row directly under it. */
table.data.preview-grid { table-layout: auto; width: 100%; min-width: 1000px; }
table.data.preview-grid td { vertical-align: top; }
table.data.preview-grid td.mono,
table.data.preview-grid td.nowrap { white-space: nowrap; }
table.data.preview-grid tr:has(+ tr.row-detail) td { border-bottom: 0; }
table.data.preview-grid tr.row-detail td.td-issues { padding-top: 0; padding-left: 2.75rem; }

@media (max-width: 719px) {
  /* Phones: the grid keeps its table shape inside the scrolling container
     (a card-per-row grid cannot be pasted into); the preview turns into
     cards like every other data table. */
  table.data.grid { display: table; }
  table.data.grid thead { display: table-header-group; }
  table.data.grid tbody { display: table-row-group; }
  table.data.grid tr { display: table-row; border: 0; margin: 0; padding: 0; background: transparent; }
  table.data.grid td { display: table-cell; width: auto; border-bottom: 1px solid var(--c-border); padding: 4px 6px; }
  table.data.grid td::before { content: none; }
  table.data.preview-grid { min-width: 0; }
  table.data.preview-grid colgroup { display: none; }
  table.data.preview-grid td.mono,
  table.data.preview-grid td.nowrap { white-space: normal; }
  /* the detail card hangs off the bottom of its row's card */
  table.data.preview-grid tr:has(+ tr.row-detail) { margin-bottom: 0; border-bottom: 0; border-radius: var(--radius) var(--radius) 0 0; }
  table.data.preview-grid tr.row-detail { border-top: 0; border-radius: 0 0 var(--radius) var(--radius); }
  table.data.preview-grid tr.row-detail td.td-issues { padding: 0.35rem 0.25rem 0.5rem; display: block; }
  table.data.preview-grid tr.row-detail td.td-issues::before { display: block; margin-bottom: 0.2rem; }
}

/* Month calendar with quick create (U-10, DOC-032 §9). Seven columns on a
   desk; on a phone the weeks stack and only days with something in them (or
   today) take up room, so a month is a short scroll rather than 42 tiny
   squares. Every entry is estate + green dot + 「已報更／所需」 and nothing
   else — the dot means "a promotion day exists here" (D-U10-02). */
.cal-toolbar { display: flex; align-items: center; justify-content: space-between; gap: 0.5rem; }
.cal-month { margin: 0; font-size: 1.15rem; }
.cal-help { margin: 0.5rem 0 0.75rem; }
table.cal { width: 100%; border-collapse: collapse; table-layout: fixed; }
table.cal th { font-size: 0.8rem; color: var(--c-muted); padding: 0.35rem 0; text-align: center; font-weight: 600; }
table.cal td.cal-day {
  vertical-align: top; border: 1px solid var(--c-border); padding: 0.25rem 0.3rem;
  min-height: 5.5rem; height: 5.5rem; background: var(--c-surface); cursor: pointer;
}
table.cal td.cal-other { background: var(--c-bg); cursor: default; }
table.cal td.cal-today { box-shadow: inset 0 0 0 2px var(--c-primary); }
.cal-head { display: flex; justify-content: space-between; align-items: center; }
.cal-num { font-size: 0.85rem; font-weight: 600; color: var(--c-text); }
.cal-add {
  display: inline-flex; align-items: center; justify-content: center;
  width: 1.6rem; height: 1.6rem; border-radius: 50%; text-decoration: none;
  color: var(--c-primary-dark); background: var(--c-info-bg); font-weight: 700; line-height: 1;
}
.cal-entries { list-style: none; margin: 0.2rem 0 0; padding: 0; }
.cal-entry a {
  display: flex; align-items: center; gap: 0.3rem; text-decoration: none; color: var(--c-text);
  font-size: 0.82rem; line-height: 1.3; padding: 0.1rem 0; white-space: nowrap; overflow: hidden;
}
.cal-estate { overflow: hidden; text-overflow: ellipsis; min-width: 0; }
.cal-dot {
  display: inline-block; width: 0.55rem; height: 0.55rem; border-radius: 50%;
  background: var(--c-success); flex: 0 0 auto;
}
.cal-fraction { font-variant-numeric: tabular-nums; font-weight: 600; margin-left: auto; color: var(--c-success); }
.cal-dialog { border: 1px solid var(--c-border); border-radius: var(--radius); padding: var(--gap); max-width: 26rem; width: calc(100% - 2rem); }
.cal-dialog::backdrop { background: rgba(28, 39, 51, 0.45); }
.cal-dialog[open]:not(:modal) { position: fixed; left: 50%; top: 10%; transform: translateX(-50%); z-index: 20; box-shadow: 0 10px 30px rgba(0,0,0,0.2); }
.cal-dialog-head { display: flex; justify-content: space-between; align-items: center; gap: 0.5rem; }
.cal-dialog-head h2 { margin: 0; font-size: 1.1rem; }
.cal-headcounts { display: grid; grid-template-columns: repeat(3, 1fr); gap: 0.5rem; }
.cal-headcounts .field { margin-bottom: 0.5rem; }
.cal-headcounts .field label { font-size: 0.85rem; }

@media (max-width: 719px) {
  table.cal thead { display: none; }
  table.cal, table.cal tbody, table.cal tr { display: block; width: 100%; }
  table.cal td.cal-day { display: block; width: 100%; height: auto; min-height: 0; border-radius: var(--radius); margin-bottom: 0.4rem; padding: 0.4rem 0.6rem; }
  table.cal td.cal-other { display: none; }
  table.cal td.cal-day .cal-num::after { content: " 日"; font-weight: 400; color: var(--c-muted); }
  .cal-entry a { font-size: 0.95rem; white-space: normal; }
  .cal-headcounts { grid-template-columns: 1fr; }
}

/* --- Pagination ----------------------------------------------------------
   The page strip under a long list (templates/_pagination.html). Wraps on a
   phone rather than pushing the table sideways, and the current page is a
   filled button so the eye finds it without reading the numbers. */
.pager {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
  align-items: center;
  margin-top: 0.9rem;
}
.pager .btn.small { min-width: 2.2rem; text-align: center; }
.pager-current { pointer-events: none; }
.pager .disabled { opacity: 0.45; pointer-events: none; }
.pager-gap { padding: 0 0.15rem; color: var(--c-muted); }
.pager-summary { margin-top: 0.5rem; }

/* The round day-picker, grouped one promotion at a time (U-18). David,
   2026-09-15: 「報更個位置，可能一條邨連續出三日，可能會容易啲睇」. The head row
   carries the estate; the three days under it are indented so a group reads as
   one block on a phone as well as a desktop. */
table.shift-picker tbody.shift-group + tbody.shift-group { border-top: 2px solid var(--c-border); }
table.shift-picker .shift-group-head td { background: var(--c-bg); }
table.shift-picker .shift-group-head label { cursor: pointer; }
table.shift-picker .shift-group-head strong { margin-right: 0.4rem; }
table.shift-picker tbody.shift-group tr:not(.shift-group-head) td:nth-child(2) { padding-left: 1.2rem; }

/* ===================================================================
   The staffing matrix (U-23). David, 2026-09-15: 「好似 Excel 個 Matrix
   佢 tick tick tick 咁 / 全部 show 晒出嚟」. A fortnight is fifteen columns
   and fifty rows, so the name column and the two header rows stay put
   while the grid scrolls under them — a name that scrolls away turns the
   grid into a puzzle.

   U-25 (2026-09-17, 「個畫面可唔可以用盡少少」) took the chrome off the top of
   the page and tightened the cells: the prose and the legend are behind a
   「點用？」 fold, the filters sit on the title line, and the grid gets the rest
   of the window. Nothing was deleted — it is one click away — but the grid now
   starts near the top of the screen instead of halfway down it.
   =================================================================== */
.mx-bar { margin-bottom: 0.5rem; row-gap: 0.35rem; }
.mx-bar h1 { font-size: 1.15rem; }
.mx-period { font-size: 0.85rem; font-weight: 400; color: var(--c-muted); }
.mx-filters {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: flex-end;
  gap: 0.35rem;
  font-size: 0.85rem;
  /* Without these the row refuses to wrap and walks off the right edge of a
     narrower monitor instead — which is how 「下一段」 ended up half off David's
     screen. min-width:0 lets a flex item shrink below its content width. */
  flex: 1 1 22rem;
  min-width: 0;
}
.mx-filters .input { width: auto; padding: 0.2rem 0.35rem; font-size: 0.85rem; }
.mx-filters .btn { padding: 0.25rem 0.6rem; font-size: 0.85rem; }
.mx-allpeople { display: inline-flex; align-items: center; gap: 0.25rem; white-space: nowrap; }

/* The explanation is not gone, it is folded. Everything an administrator needs
   on day one is one click away; on day twenty they never open it again. */
.hint {
  border: 1px solid var(--c-border);
  border-radius: var(--radius);
  background: var(--c-surface);
  padding: 0.35rem 0.6rem;
  margin-bottom: 0.5rem;
}
.hint > summary { cursor: pointer; font-size: 0.85rem; color: var(--c-muted); }
.hint[open] > summary { margin-bottom: 0.4rem; }
.hint p:last-child { margin-bottom: 0; }

.mx-actions { margin-top: 0.5rem; align-items: center; }

.matrix-wrap {
  overflow: auto;
  max-height: 82vh;
  border: 1px solid var(--c-border);
  border-radius: var(--radius);
}
table.matrix { border-collapse: separate; border-spacing: 0; font-size: 0.8rem; }
table.matrix th,
table.matrix td {
  border-right: 1px solid var(--c-border);
  border-bottom: 1px solid var(--c-border);
  padding: 0.12rem 0.25rem;
  text-align: center;
  white-space: nowrap;
  background: var(--c-surface);
}
table.matrix thead th { position: sticky; top: 0; z-index: 3; background: var(--c-bg); }
table.matrix thead tr:nth-child(2) th { top: 1.7rem; }
table.matrix .mx-name {
  position: sticky;
  left: 0;
  z-index: 2;
  text-align: left;
  background: var(--c-bg);
  min-width: 6.5rem;
  font-weight: 600;
}
table.matrix thead .mx-name,
table.matrix thead .mx-total { z-index: 4; }
table.matrix .mx-group { background: var(--c-info-bg); font-weight: 600; }
table.matrix tfoot th,
table.matrix tfoot td { position: sticky; bottom: 0; background: var(--c-bg); z-index: 2; }
table.matrix tfoot .mx-name { z-index: 3; }

/* A cell is read by colour first and by its mark second: the grid is
   scanned, not read. */
.mx-cell { min-width: 2.7rem; }
.mx-assigned { background: var(--c-success-bg); }
.mx-leader   { background: var(--c-info-bg); font-weight: 600; }
.mx-can      { background: #fbfbe8; }
.mx-cannot   { background: var(--c-danger-bg); color: var(--c-danger); }
.mx-blank    { color: var(--c-muted); }
.mx-short    { background: var(--c-warning-bg); }

/* The whole cell is the target, not just the box: this screen is used with
   a mouse, fast, for an hour at a time. */
/* Every cell is a visible control, because twice it was not one: the tick was
   an invisible checkbox behind the cell's text, and the administrator could
   not tell what was clickable — 「派更個位咩都按唔到」, then 「不如好似 Leader
   咁俾人揀喇, 會簡單好多」 (David, 2026-09-16). A bordered dropdown, the same
   shape as the leader picker beside it, says both things at once: this is a
   control, and this is what it is currently set to. */
.mx-pick {
  display: block;
  width: 100%;
  min-width: 3.2rem;
  font-size: 0.75rem;
  padding: 0.05rem 0.15rem;
  border: 1px solid var(--c-border);
  border-radius: 4px;
  background: var(--c-surface);
  cursor: pointer;
  /* The 44px touch floor every other control keeps is what made this grid
     twice as tall as it needed to be: fifty rows of it is a second screenful
     of nothing. This one screen is the exception the comment above already
     names — it is worked with a mouse, for an hour at a time — so the boxes
     drop to a mouse-sized 28px. */
  min-height: 1.75rem;
}
.mx-assigned .mx-pick, .mx-leader-cell .mx-pick { font-weight: 600; }
.mx-answer { display: block; font-size: 0.64rem; line-height: 1.2; opacity: 0.7; }
.mx-flat { display: block; opacity: 0.7; }
.mx-leader-select, select.mx-leader { min-width: 5rem; min-height: 1.75rem; font-size: 0.75rem; padding: 0.05rem; }
.mx-key { display: inline-block; padding: 0 0.35rem; border-radius: 4px; }
/* Full is full (U-24, David: 「超過咗個村嘅需要人數係要制止行政主任」). The box
   stops accepting a tick where the decision is made, and the day's count says
   why; the server refuses the same thing for a browser with no JavaScript. */
.mx-over { background: var(--c-danger-bg); color: var(--c-danger); font-weight: 600; }
.mx-locked .mx-pick { cursor: not-allowed; opacity: 0.45; }

/* ------------------------------------------- the round answer grid (U-26)

   One column per day, one row per colleague, so it is wide by nature and
   scrolls sideways inside .table-wrap rather than stretching the page.

   These rules used to sit in round.css, which base.html does not load, so the
   grid rendered as bare unruled text: no borders, no green, no red, while the
   sentence above it told the reader to look for exactly those colours (David,
   2026-09-17: 「答覆沒有了顏色」、「要加個表格, 否則好難睇到」). They live
   here now because this grid is an administrator screen and app.css is the
   stylesheet the administrator screens load. */
table.round-matrix {
  border-collapse: collapse;
  white-space: nowrap;
  font-size: 0.9rem;
}

table.round-matrix th,
table.round-matrix td {
  border: 1px solid var(--c-border);
  padding: 0.35rem 0.55rem;
  text-align: center;
  vertical-align: middle;
}

/* The colleague column stays put while the days scroll past it; without this
   a scroll to late October leaves a grid of 可/否 belonging to nobody. */
table.round-matrix th.person,
table.round-matrix td.person {
  text-align: left;
  white-space: normal;
  position: sticky;
  left: 0;
  z-index: 1;
  background: var(--c-surface);
}

/* Three lines per heading — date, estate, district — instead of one run-on
   label (David, 2026-09-17). Centred and non-wrapping keeps the columns
   narrow; the district is the quietest of the three because it is there to
   disambiguate the estate, not to be scanned. */
table.round-matrix th .mx-day-estate { display: block; font-size: 0.8rem; }
table.round-matrix th .mx-day-district {
  display: block;
  font-size: 0.72rem;
  font-weight: 400;
  color: var(--c-muted);
}

.round-cell-yes { background: var(--c-success-bg); color: var(--c-success); font-weight: 600; }
.round-cell-no { background: var(--c-danger-bg); color: var(--c-danger); }
.round-cell-blank { background: var(--c-bg); color: var(--c-muted); }

/* SSB-R1 UI: deliberately scoped to the answer overview, not the whole app. */
.round-admin { color: #18333d; }
.round-admin > .page-title { color: #173f4b; letter-spacing: -.02em; }
.round-admin .card { border-radius: 12px; border-color: #d6e2e5; box-shadow: 0 3px 14px #173d4808; }
.round-admin .btn { border-radius: 9px; }
.round-admin .btn:not(.secondary) { background: #146b79; }
.round-admin .btn:focus-visible { outline: 3px solid #208397; outline-offset: 3px; }
.round-admin .table-wrap { border: 1px solid #d6e2e5; border-radius: 12px; }
.round-admin table.round-matrix { width: 100%; font-variant-numeric: tabular-nums; }
.round-admin table.round-matrix th,
.round-admin table.round-matrix td { padding: .75rem .85rem; border-color: #d6e2e5; }
.round-admin table.round-matrix thead th { background: #eaf2f4; color: #183d48; }
.round-admin table.round-matrix th .mx-day-estate { margin-top: .25rem; font-size: .9rem; }
.round-admin table.round-matrix th .mx-day-district { color: #536b73; font-size: .85rem; font-weight: 400; }
.round-admin .round-cell-yes { background: #e8f5ed; color: #216443; font-weight: 700; }
.round-admin .round-cell-no { background: #fff0ec; color: #984032; font-weight: 700; }
.round-admin .round-cell-blank { background: #f6f8f9; color: #62777e; }
.round-admin .card > .mono { overflow-wrap: anywhere; }
@media print { .round-admin .card { box-shadow: none; } }
