/*
 * Screen styles for the roster. Everything measurable comes from the Broadsheet
 * tokens in styles.css; this file only arranges them into the eight screens.
 * Written 390px-first, centred with a max-width once there is room.
 */

* { box-sizing: border-box; }

body {
  margin: 0;
  font-size: 15px;
  line-height: 1.55;
  -webkit-text-size-adjust: 100%;
}

/* Home-screen launch: no browser chrome, so the app owns the edges. */
html.is-standalone body {
  overscroll-behavior: none;
  user-select: none;
  -webkit-user-select: none;
  -webkit-touch-callout: none;
}

html.is-standalone input,
html.is-standalone textarea,
html.is-standalone [contenteditable] {
  user-select: text;
  -webkit-user-select: text;
}

html.is-standalone .install-hint {
  display: none !important;
}

/* Consent copy lives in a modal once script is running. Without JS it stays
   inline above the name list, because the overlay cannot be dismissed. */
html.has-js .welcome-inline { display: none; }
html:not(.has-js) .welcome-modal { display: none; }

.welcome-modal {
  position: fixed;
  inset: 0;
  z-index: 30;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px var(--space-4);
  background: color-mix(in srgb, var(--color-neutral-900) 50%, transparent);
}

.welcome-modal-card {
  display: flex;
  flex-direction: column;
  width: min(100%, 400px);
  max-height: min(86vh, 640px);
  background: var(--color-surface);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  overflow: hidden;
}

.welcome-modal-body {
  overflow-y: auto;
  padding: 24px var(--space-4) 8px;
}

.welcome-modal-body h2 {
  font-size: 23px;
  margin: 0 0 12px;
  letter-spacing: -0.02em;
  line-height: 1.15;
}

.welcome-modal-body p {
  font-size: 15px;
  margin: 0 0 12px;
  color: var(--color-neutral-800);
  line-height: 1.45;
}

.welcome-modal-body p:last-child { margin-bottom: 8px; }

.welcome-modal-actions {
  flex: none;
  padding: 12px var(--space-4) 16px;
  border-top: 1px solid var(--color-divider);
  background: var(--color-surface);
}

.welcome-modal-actions .btn-block {
  margin-top: 0;
  min-height: 48px;
}

/* The browser's own [hidden] rule loses to any class that sets display, which
   every control here does. Without this, "hidden until the script reveals it"
   would show the control to people with no JavaScript at all. */
[hidden] { display: none !important; }

.phone {
  max-width: 560px;
  margin: 0 auto;
  min-height: 100vh;
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  padding-bottom: env(safe-area-inset-bottom);
}

/* Room for the fixed tab bar, which is no longer in the flow. Screens without
   one — the setup pages — keep their own footing. */
.phone:has(.tabbar) {
  padding-bottom: calc(92px + env(safe-area-inset-bottom));
}

.app-header {
  position: sticky;
  top: 0;
  z-index: 15;
  background: var(--color-bg);
  padding-top: env(safe-area-inset-top);
  padding-bottom: 10px;
  border-bottom: 1px solid var(--color-divider);
}

.statusbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  padding: 8px var(--space-4) 0;
  font-size: 11px;
  color: var(--color-neutral-700);
}

/* The roster's name is the heading of every screen. The auto margin gathers
   whatever else the bar carries over on the right. */
.statusbar-name {
  display: flex;
  align-items: center;
  margin-right: auto;
  gap: 8px;
  font-size: 16px;
  line-height: 1.15;
  letter-spacing: -0.01em;
  color: var(--color-text);
}

.statusbar-icon {
  width: 35px;
  height: 35px;
  padding: 6.56px;
  box-sizing: border-box;
  border-radius: 50%;
  object-fit: contain;
  background: #fff;
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--color-text) 10%, transparent);
}

.view-switch {
  display: flex;
  padding: 10px var(--space-4) 0;
}

.view-switch .seg {
  display: flex;
  width: 100%;
  border: 0;
  border-radius: 999px;
  background: var(--color-neutral-300);
  padding: 3px;
  overflow: hidden;
}

.view-switch .seg-opt {
  flex: 1;
  justify-content: center;
  min-height: 34px;
  padding: 6px 10px;
  border-radius: 999px;
  font-size: 13px;
}

.view-switch .seg-opt + .seg-opt { border-left: 0; }

.view-switch .seg-opt.is-active {
  background: var(--color-bg);
  color: var(--color-text);
}

.view-switch .seg-opt:not(.is-active) {
  background: transparent;
  color: var(--color-neutral-700);
}

.view-switch .seg-opt:not(.is-active):hover {
  background: color-mix(in srgb, var(--color-text) 8%, transparent);
}

/* People / Tasks, same pill as Week / Month / Quarter. */
.admin-tabs {
  display: flex;
  flex: none;
  border-radius: 999px;
  background: var(--color-neutral-300);
  padding: 3px;
  overflow: hidden;
}

.admin-tabs .seg-opt {
  justify-content: center;
  min-width: 72px;
  min-height: 34px;
  padding: 6px 12px;
  border-radius: 999px;
  font-size: 13px;
}

.admin-tabs .seg-opt + .seg-opt { border-left: 0; }

.admin-tabs .seg-opt.is-active {
  background: var(--color-bg);
  color: var(--color-text);
}

.admin-tabs .seg-opt:not(.is-active) {
  background: transparent;
  color: var(--color-neutral-700);
}

/* On the light ground the thumb is the page showing through the track. On the
   dark one that reads as a hole, so the track sinks and the thumb lifts. */
body.theme-dark .view-switch .seg,
body.theme-dark .admin-tabs {
  background: var(--color-neutral-100);
}

body.theme-dark .view-switch .seg-opt.is-active,
body.theme-dark .admin-tabs .seg-opt.is-active {
  background: var(--color-neutral-400);
}

.admin-tabs .seg-opt:not(.is-active):hover {
  background: color-mix(in srgb, var(--color-text) 8%, transparent);
}

/* The way in to editing. Accent means this phone is already unlocked. */
.statusbar-admin {
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: 44px;
  min-height: 34px;
  margin-right: -10px;
  color: var(--color-neutral-700);
}

.statusbar-admin.is-unlocked { color: var(--color-accent); }

.statusbar-actions {
  display: flex;
  align-items: center;
  gap: 2px;
  margin-right: -10px;
}

.statusbar-actions .statusbar-admin { margin-right: 0; }

.statusbar-logout { margin: 0; }

button.statusbar-admin {
  font: inherit;
  background: none;
  border: 0;
  cursor: pointer;
  padding: 0;
}

.page {
  flex: 1;
  padding: 0 var(--space-4);
}

body.month-view .phone {
  height: 100dvh;
  max-height: 100dvh;
  overflow: hidden;
}

body.month-view .page {
  min-height: 0;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
}

/* — datelines and headings — */

.kicker {
  font-size: 10px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--color-accent);
}

.kicker-2 { color: var(--color-accent-2-700); }

.dateline-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-3);
  padding: 10px var(--space-4) 12px;
  /* The dateline can be long ("… · PUBLISHED"); let the control drop to its
     own line rather than pushing the page wider than the phone. */
  flex-wrap: wrap;
}

.dateline-row > :first-child {
  flex: 1 1 auto;
  min-width: 0;
}

.admin-generate {
  padding: 0 var(--space-4) 2px;
}

.admin-generate .btn-block {
  margin-top: 0;
}

.admin-setup {
  padding: 0 var(--space-4) 8px;
}

.admin-setup > summary {
  list-style: none;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  min-height: 44px;
  padding: 8px 0;
  font-family: var(--font-heading);
  font-weight: var(--font-heading-weight);
  font-size: 19px;
  letter-spacing: -0.015em;
  line-height: 1.12;
  color: var(--color-text);
  border-bottom: 2px solid var(--color-text);
}

.admin-setup > summary::-webkit-details-marker,
.admin-setup > summary::marker { display: none; content: none; }

.admin-setup > summary::after {
  content: '';
  width: 8px;
  height: 8px;
  flex: none;
  margin-top: -4px;
  border-right: 2px solid var(--color-text);
  border-bottom: 2px solid var(--color-text);
  transform: rotate(45deg);
  transition: transform 0.15s ease, margin-top 0.15s ease;
}

.admin-setup[open] > summary::after {
  margin-top: 4px;
  transform: rotate(225deg);
}

.admin-setup-form {
  padding-top: 12px;
}

.admin-setup-form .hint { margin-bottom: 0; }

.kicker { overflow-wrap: anywhere; }

.page-title {
  font-size: 29px;
  margin: 2px 0 0;
  letter-spacing: -0.02em;
  line-height: 1.1;
}

.page-title-sm { font-size: 27px; }

.lede {
  font-size: 13px;
  margin: 6px 0 0;
  color: var(--color-neutral-800);
}

/* — week navigation — */

.week-rail {
  display: flex;
  gap: 8px;
  align-items: center;
  padding: 6px var(--space-4) 2px;
}

/* Borderless: the arrows read as quiet navigation next to the label, and the
   hover and press tints still show where the tap target is. */
.week-rail .btn {
  padding: 5px 10px;
  font-size: 24px;
  min-width: 44px;
  min-height: 44px;
  line-height: 1;
  border-color: transparent;
}

/* With the heading above it gone, this label is the title of the screen, so it
   takes the heading face rather than sitting quietly between the arrows. */
.week-rail-label {
  font-family: var(--font-heading);
  font-weight: var(--font-heading-weight);
  font-size: 19px;
  color: var(--color-text);
  flex: 1;
  text-align: center;
}

.seg-full {
  display: flex;
  margin: 11px var(--space-4) 12px;
  font-size: 12px;
}

.seg-full .seg-opt {
  flex: 1;
  justify-content: center;
  min-height: 44px;
}

/* The design draws the segmented controls as radios; as navigation between
   server-rendered screens they are links, so the selected state is a class
   rather than :has(input:checked). */
a.seg-opt { text-decoration: none; color: inherit; }
.seg-opt.is-active { background: var(--color-accent); color: var(--color-bg); }
.seg-opt:not(.is-active):hover { background: color-mix(in srgb, var(--color-text) 7%, transparent); }

/* — group headings — */

.group-head {
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--color-accent);
  border-bottom: 2px solid var(--color-text);
  padding-bottom: 4px;
}

.group-head + .slot { border-top: 0; }

.group-head-bschool {
  color: var(--color-accent-2-700);
  margin-top: var(--space-4);
}

/* Same thick rule as AV's "Main hall" heading. On a phone it is only the
   line; on desktop the invisible label keeps the first tasks level. */
.group-head-align {
  display: block;
  font-size: 0;
  letter-spacing: 0;
  padding-bottom: 0;
  color: transparent;
  user-select: none;
}

/* — the day's two departments —
 *
 * Both are always in the page, stacked on a phone. Past 900px they sit side
 * by side. The day itself is chosen with the Sat/Tue tabs, at every width. */

.day-column + .day-column { margin-top: 22px; }

.day-column-head {
  display: block;
  font-family: var(--font-heading);
  font-size: 19px;
  font-weight: 600;
  margin: 0 0 10px;
}

/* — the task rows that make up a meeting — */

.slot {
  display: flex;
  gap: 11px;
  padding: 10px 0;
  border-top: 1px solid var(--color-divider);
  min-height: 44px;
  width: 100%;
  text-align: left;
  background: none;
  border-left: 0;
  border-right: 0;
  border-bottom: 0;
  font: inherit;
  color: inherit;
}

.slot:last-of-type { border-bottom: 1px solid var(--color-divider); }

button.slot { cursor: pointer; }
button.slot:hover { background: color-mix(in srgb, var(--color-text) 4%, transparent); }

.slot-icon {
  flex: none;
  color: var(--color-neutral-700);
  align-self: center;
  line-height: 1;
}

a.slot-icon {
  position: relative;
  color: var(--color-neutral-700);
  text-decoration: none;
}

a.slot-icon:hover,
a.slot-icon:focus-visible {
  color: var(--color-accent-2-700);
}

/* Widen the tap target without growing the glyph in the row. */
a.slot-icon::after {
  content: "";
  position: absolute;
  inset: -12px -10px;
}

.spine {
  width: 3px;
  height: 40px;
  flex: none;
  align-self: flex-start;
  border-radius: 2px;
  background: var(--color-neutral-400);
}

.slot-body { flex: 1; min-width: 0; }

.slot-label {
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-neutral-700);
}

.slot-person {
  display: flex;
  align-items: center;
  gap: 9px;
  margin-top: 5px;
  width: 100%;
}

.slot-person + .slot-person { margin-top: 0; }

.slot-confirmed {
  margin-left: auto;
  flex: none;
  display: flex;
  align-items: center;
  color: var(--color-neutral-400);
  line-height: 0;
}

.slot-name { font-size: 18px; }

.slot-open .slot-name {
  color: var(--color-accent-2-700);
  font-style: italic;
}

.slot-refill {
  font-size: 12px;
  color: var(--color-accent-2-700);
  margin-top: 3px;
}

/* — person chips — */

.chip {
  width: var(--chip-size, 26px);
  height: var(--chip-size, 26px);
  flex: none;
  border-radius: 50%;
  background: var(--chip-color, var(--color-neutral-500));
  color: var(--chip-ink, var(--color-bg));
  display: grid;
  place-items: center;
  font-size: var(--chip-initials, calc(var(--chip-size, 26px) * 0.42));
  line-height: 1;
  letter-spacing: 0.01em;
}

.chip-open {
  background: transparent;
  border: 1px dashed var(--color-accent-2-600);
  color: var(--color-accent-2-700);
}

.chip.chip-muted {
  background: transparent;
  border: 1.5px solid var(--color-neutral-500);
  color: var(--color-neutral-700);
}

.chip-open.chip-muted {
  background: transparent;
  border: 1px dashed var(--color-neutral-500);
  color: var(--color-neutral-600);
}

.chip-rows {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-top: 10px;
}

.chip-dept {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
}

.chip-dept-label {
  flex: none;
  width: 6.5em;
  font-size: 11px;
  color: var(--color-neutral-700);
  line-height: 1.2;
}

.chip-row {
  display: flex;
  gap: 0;
  flex-wrap: wrap;
  flex: 1;
  min-width: 0;
}

/* — footnotes — */

.hint {
  font-size: 12px;
  color: var(--color-neutral-700);
  margin: 14px 0 16px;
}

.hint-warn { color: var(--color-accent-2-700); }

.flash {
  font-size: 13px;
  margin: 0 0 var(--space-3);
  padding: 9px 11px;
  border-radius: var(--radius-md);
}

.flash-accent { background: var(--color-accent-100); color: var(--color-accent-800); }
.flash-warn { background: var(--color-accent-2-100); color: var(--color-accent-2-800); }

/* Compact cyan pill on Me — text-sized, not a full-width bar. */
.me-away {
  display: flex;
  justify-content: center;
  margin: 14px 0 4px;
}

.me-away .btn-pill {
  min-height: 44px;
  padding-inline: 22px;
  font-weight: 600;
}

/* Shown only in the browser. Once EZRA is on the Home Screen, standalone
   mode hides the address bar and this tip goes with it. */
.install-hint {
  display: flex;
  flex-direction: column;
  gap: 12px;
  margin: 16px 0;
  padding: 14px 14px 12px;
  border: 1px solid var(--color-divider);
  border-radius: var(--radius-md);
  background: var(--color-raised);
}

.install-hint-copy strong {
  display: block;
  margin-bottom: 4px;
  font-size: 15px;
}

.install-hint-copy p {
  margin: 0;
  color: var(--color-neutral-700);
  font-size: 13px;
  line-height: 1.45;
}

.install-hint-copy em {
  font-style: normal;
  font-weight: 600;
  color: var(--color-ink);
}

.install-hint-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.chat-typing {
  margin: 0 0 6px;
  padding: 0 4px;
  color: var(--color-neutral-700);
  font-size: 12.5px;
  line-height: 1.3;
  min-height: 1.3em;
  animation: chat-typing-pulse 1.4s ease-in-out infinite;
}

.chat-typing[hidden] {
  display: none;
}

@keyframes chat-typing-pulse {
  0%, 100% { opacity: 0.55; }
  50% { opacity: 1; }
}

/* — bottom tab bar — */

/* A floating island, pinned to the viewport. Always four-tab wide: Docs,
   Roster, Me, Chat. Sits below the picker's backdrop (z-index 20) so a bottom
   sheet still covers it. The full rounding is a deliberate departure from the
   design's 1–4px radii. */
.tabbar {
  /* Bright pink from the EZRA mark — all floating nav icons. */
  --tab-ink: #ff458e;
  --tab-w: 76px;
  --tab-gap: 2px;
  --tab-pad: 5px;
  --tab-slots: 4;
  --tabbar-span: calc(
    (var(--tab-slots) * var(--tab-w))
    + ((var(--tab-slots) - 1) * var(--tab-gap))
    + (2 * var(--tab-pad))
    + 2px
  );
  position: fixed;
  bottom: calc(14px + env(safe-area-inset-bottom));
  left: calc(50% - (var(--tabbar-span) / 2));
  width: var(--tabbar-span);
  z-index: 10;
  display: grid;
  grid-template-columns: repeat(4, var(--tab-w));
  gap: var(--tab-gap);
  padding: var(--tab-pad);
  border-radius: 999px;
  background: var(--color-raised);
  border: 1px solid var(--color-divider);
  box-shadow: var(--shadow-md);
}

.tab-docs { grid-column: 1; }
.tab-roster { grid-column: 2; }
.tab-me { grid-column: 3; }
.tab-chat { grid-column: 4; }

.tab {
  grid-row: 1;
  flex: none;
  width: var(--tab-w);
  min-width: var(--tab-w);
  box-sizing: border-box;
  font-size: 12px;
  color: var(--tab-ink);
  text-decoration: none;
  padding: 8px 0;
  min-height: 50px;
  border-radius: 999px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
}

.tab.is-active {
  color: var(--tab-ink);
  background: color-mix(in srgb, var(--tab-ink) 12%, transparent);
}

body.theme-dark .tabbar {
  --tab-ink: #ff8ab8;
}

/* Actions rather than destinations, but they sit in the island so they wear the
   same shape as their neighbours. */
button.tab {
  font-family: inherit;
  background: none;
  border: 0;
  cursor: pointer;
}

/* The three sets draw at different weights; nudge them to look even. */
.tab-icon { display: block; }

.tabbar .tab-icon {
  width: 33px;
  height: 33px;
}
.tab-label {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* — chat —
 *
 * The one screen that is not a Broadsheet page. It replaces the group chat the
 * volunteers already use, so it is drawn like one: wallpaper, tinted bubbles,
 * the time tucked inside them, and a pill composer. Both grounds are set as
 * chat-local tokens on the body, which is also what paints the strip below the
 * log so the wallpaper reaches the bottom of the screen. */

body.chat-screen {
  /* Same ground as the rest of the app in light mode, so chat does not feel
     like a separate beige room. */
  --chat-wallpaper: var(--color-bg);
  /* Cyan from the EZRA mark — soft wash under the composer. */
  --chat-fade: #00a0d0;
  --chat-doodle: color-mix(in srgb, #000 4%, transparent);
  --chat-in: #ffffff;
  --chat-out: #ffffff;
  --chat-ink: #111b21;
  --chat-muted: #667781;
  --chat-bar: #f0f2f5;
  --chat-pill: #ffffff;
  --chat-system: color-mix(in srgb, #fff 88%, transparent);
  --chat-quote: color-mix(in srgb, #000 5%, transparent);
  --chat-accent: #00a884;
  /* The warm orange of the feather tip on the EZRA mark — send is the one
     control that should carry the brand rather than WhatsApp green. */
  --chat-send: #fc7e54;
  --chat-menu: #ffffff;
  --chat-danger: #d93025;
  /* Which way a volunteer's own colour is pushed to become legible text. */
  --chat-author-mix: #000;
  /* The roster is a serif book; a chat is a messaging app. Use the phone's own
     UI face so bubbles, the composer and the menu read like WhatsApp. */
  --chat-font: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
    "Helvetica Neue", Arial, sans-serif;
  /* Height of .app-header below the notch: statusbar padding 8 + 35px icon +
     header padding-bottom 10. Search/Close stick under this, not under it. */
  --chat-sticky-top: calc(env(safe-area-inset-top, 0px) + 53px);

  /* On the body, so the wallpaper runs the whole screen rather than stopping
     where the log does. */
  background-color: var(--chat-wallpaper);
  background-image:
    radial-gradient(circle at 7px 7px, var(--chat-doodle) 1.5px, transparent 1.5px),
    radial-gradient(circle at 21px 21px, var(--chat-doodle) 1px, transparent 1px);
  background-size: 28px 28px, 28px 28px;
}

body.chat-screen.theme-dark {
  --chat-wallpaper: #0b141a;
  --chat-doodle: color-mix(in srgb, #fff 4%, transparent);
  --chat-in: #202c33;
  --chat-out: #005c4b;
  --chat-ink: #e9edef;
  --chat-muted: #8696a0;
  --chat-bar: #1f2c34;
  --chat-pill: #2a3942;
  --chat-system: color-mix(in srgb, #1f2c34 92%, transparent);
  --chat-quote: color-mix(in srgb, #fff 6%, transparent);
  --chat-menu: #233138;
  --chat-danger: #f15c6d;
  --chat-author-mix: #fff;
}

/* Nothing else in the app is a full screen of its own, so this is the one place
   that drops the tab bar: the composer takes the very bottom of the phone, and
   the floating X over the wallpaper is the way out. */
body.chat-screen .phone {
  padding-bottom: 0;
  /* Stops double-tap zoom from racing the long-press menu on this screen. */
  touch-action: manipulation;
}

body.chat-screen .dateline-row,
body.chat-screen .chat-page {
  font-family: var(--chat-font);
}

/* A narrower gutter than the rest of the app: the bubbles are the page here,
   and the wallpaper behind them already comes from the body. */
.chat-page {
  position: relative;
  display: flex;
  flex-direction: column;
  padding: 0 10px;
  color: var(--chat-ink);
  font-family: var(--chat-font);
}

/* Match the chat ground so the sticky title row does not flash a different
   sheet as messages pass underneath. */
body.chat-screen .app-header {
  background-color: var(--chat-wallpaper);
  background-image:
    radial-gradient(circle at 7px 7px, var(--chat-doodle) 1.5px, transparent 1.5px),
    radial-gradient(circle at 21px 21px, var(--chat-doodle) 1px, transparent 1px);
  background-size: 28px 28px, 28px 28px;
  border-bottom-color: transparent;
}

/* Sits in the Attendants Chat dateline, level with the kicker — not down in
   the log. Sticky under the app header so Search/Close stay on screen while
   messages scroll (top: 0 parked them under the statusbar and they vanished). */
body.chat-screen .chat-dateline {
  position: sticky;
  top: var(--chat-sticky-top);
  z-index: 14;
  align-items: center;
  background-color: var(--chat-wallpaper);
  background-image:
    radial-gradient(circle at 7px 7px, var(--chat-doodle) 1.5px, transparent 1.5px),
    radial-gradient(circle at 21px 21px, var(--chat-doodle) 1px, transparent 1px);
  background-size: 28px 28px, 28px 28px;
}

.chat-close {
  display: grid;
  place-items: center;
  flex: none;
  width: 36px;
  height: 36px;
  border-radius: 999px;
  background: var(--chat-system);
  color: var(--chat-ink);
  box-shadow: var(--shadow-md);
}

.chat-header-actions {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: -4px -6px -4px 0;
}

/* Collapsed: icon-only disc. Open: grows left into a pill with the field. */
.chat-search {
  display: flex;
  align-items: center;
  flex: none;
  width: 36px;
  height: 36px;
  border-radius: 999px;
  background: var(--chat-system);
  color: var(--chat-ink);
  box-shadow: var(--shadow-md);
  overflow: hidden;
  transition: width 0.22s ease;
}

.chat-search.is-open {
  width: min(240px, 64vw);
}

.chat-search-toggle {
  display: grid;
  place-items: center;
  flex: none;
  width: 36px;
  height: 36px;
  border: 0;
  border-radius: 999px;
  background: transparent;
  color: inherit;
  cursor: pointer;
}

.chat-search-input {
  flex: 1;
  min-width: 0;
  width: 0;
  height: 36px;
  padding: 0;
  border: 0;
  opacity: 0;
  pointer-events: none;
  background: transparent;
  color: var(--chat-ink);
  font: inherit;
  font-size: 14px;
  outline: none;
  transition: opacity 0.18s ease;
}

.chat-search.is-open .chat-search-input {
  width: auto;
  padding: 0 4px 0 0;
  opacity: 1;
  pointer-events: auto;
}

.chat-search-clear {
  display: none;
  place-items: center;
  flex: none;
  width: 28px;
  height: 28px;
  margin-right: 4px;
  padding: 0;
  border: 0;
  border-radius: 999px;
  background: transparent;
  color: var(--chat-muted);
  cursor: pointer;
}

.chat-search.is-open .chat-search-clear:not([hidden]) {
  display: grid;
}

.chat-search-input::-webkit-search-cancel-button,
.chat-search-input::-webkit-search-decoration {
  -webkit-appearance: none;
}

.chat-search-input::-moz-search-clear {
  display: none;
}

.chat-message.is-search-hidden,
.chat-day.is-search-hidden {
  display: none;
}

/* The group's standing note, drawn as one of the chat's own system pills. */
.chat-page .lede {
  align-self: center;
  max-width: 84%;
  margin: 10px 0 4px;
  padding: 6px 12px;
  border-radius: 8px;
  background: var(--chat-system);
  color: var(--chat-muted);
  font-size: 12.5px;
  text-align: center;
}

.chat-log {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 3px;
  padding: 8px 0 14px;
}

.empty-state {
  align-self: center;
  max-width: 84%;
  margin: 10px 0;
  padding: 8px 12px;
  border-radius: 8px;
  background: var(--chat-system);
  color: var(--chat-muted);
  font-size: 13px;
  text-align: center;
}

/* Centred day chips between bubbles — same quiet system pill as the empty state. */
.chat-day {
  align-self: center;
  max-width: 84%;
  margin: 10px 0 4px;
  padding: 6px 12px;
  border-radius: 8px;
  background: var(--chat-system);
  color: var(--chat-muted);
  font-size: 12.5px;
  font-weight: 600;
  text-align: center;
}

.chat-day time {
  font: inherit;
  color: inherit;
}

.chat-message {
  display: flex;
  align-items: flex-end;
  gap: 6px;
  max-width: 85%;
}

/* Yours sit on the right and carry no disc: on your own phone there is never a
   question whose they are. */
.chat-message.is-mine {
  align-self: flex-end;
}

.chat-main {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  min-width: 0;
}

.chat-message.is-mine .chat-main {
  align-items: flex-end;
}

/* Reactions sit on the bubble's bottom edge (left side), straddling it —
   not in a column beside the bubble. */
.chat-bubble-row {
  position: relative;
  display: block;
  min-width: 0;
}

.chat-bubble-row:has(.chat-reactions) {
  margin-bottom: 18px;
}

.chat-reactions {
  position: absolute;
  left: 6px;
  top: 100%;
  bottom: auto;
  display: flex;
  flex-wrap: wrap;
  gap: 3px;
  max-width: calc(100% - 12px);
  margin: 0;
  padding: 0;
  transform: none;
  z-index: 2;
}

.chat-message.is-mine .chat-reactions {
  left: auto;
  right: 6px;
  justify-content: flex-end;
}

.chat-reaction {
  display: inline-flex;
  margin: 0;
}

.chat-reaction button,
span.chat-reaction {
  display: inline-flex;
  align-items: center;
  min-height: 22px;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: transparent;
  color: inherit;
  box-shadow: none;
  font: inherit;
  font-size: 16px;
  line-height: 1.2;
  cursor: pointer;
}

.chat-message.is-mine .chat-reaction button,
.chat-message.is-mine span.chat-reaction {
  background: transparent;
}

.chat-reaction.is-mine button,
span.chat-reaction.is-mine {
  border: 0;
  box-shadow: none;
  opacity: 1;
}

/* A speech bubble, not a card: large soft corners, with the near corner drawn
   into a little tail that points at the speaker. */
.chat-bubble {
  position: relative;
  min-width: 0;
  padding: 8px 12px 6px;
  border-radius: 18px 18px 18px 4px;
  background: var(--chat-in);
  box-shadow: 0 1px 0.5px rgba(11, 20, 26, 0.13);
}

.chat-bubble::before {
  content: "";
  position: absolute;
  bottom: 0;
  left: -6px;
  width: 10px;
  height: 14px;
  background: inherit;
  clip-path: polygon(100% 0, 100% 100%, 0 100%);
}

.chat-message.is-mine .chat-bubble {
  border-radius: 18px 18px 4px 18px;
  background: var(--chat-out);
}

.chat-message.is-mine .chat-bubble::before {
  left: auto;
  right: -6px;
  clip-path: polygon(0 0, 100% 100%, 0 100%);
}

/* Each volunteer's own colour — the fill of their disc — pushed toward the
   opposite of the ground far enough to carry as small text on it. */
.chat-author {
  display: block;
  margin-bottom: 1px;
  font-size: 13px;
  font-weight: 600;
  color: color-mix(in srgb, var(--chat-author, var(--chat-accent)) 76%, var(--chat-author-mix));
}

/* The time sits under the bubble on the wallpaper, not tucked inside it —
   kept quiet so it does not compete with the message. */
.chat-meta {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 3px;
  padding: 0 4px;
  font-size: 11px;
  color: color-mix(in srgb, var(--chat-muted) 55%, var(--chat-wallpaper));
}

.chat-message.is-mine .chat-meta {
  justify-content: flex-end;
}

/* Reply and Delete live in the menu you get by holding a message, so nothing
   hangs off a bubble. These are the same two controls in plain HTML: they are
   the whole feature without script, they are what the menu clicks, and they
   reappear on keyboard focus, which is the one way in a long press is not. */
.chat-tools {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-top: 4px;
}

.chat-delete { margin: 0; }

.chat-reply,
.chat-delete button {
  min-height: 24px;
  padding: 2px 9px;
  border: 1px solid var(--chat-quote);
  border-radius: 999px;
  background: transparent;
  color: var(--chat-muted);
  font: inherit;
  font-size: 11px;
  cursor: pointer;
}

html.has-js .chat-tools {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
}

html.has-js .chat-tools:focus-within {
  position: static;
  width: auto;
  height: auto;
  margin: 4px 0 0;
  overflow: visible;
  clip: auto;
}

/* A held message keeps its place in the conversation while the menu is open. */
.chat-message.is-held .chat-bubble {
  box-shadow: 0 0 0 2px var(--chat-accent);
}

/* Holding a bubble raises our menu, so the phone must not also offer its own
   text-selection callout. Copy is in the menu in its place. */
html.has-js .chat-bubble {
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  user-select: none;
}

.chat-menu-backdrop {
  position: fixed;
  inset: 0;
  z-index: 18;
}

/* Placed by script at the point held, over the header and composer. */
.chat-menu {
  position: fixed;
  z-index: 19;
  min-width: 186px;
  padding: 6px;
  border-radius: 14px;
  background: var(--chat-menu);
  box-shadow: var(--shadow-lg);
}

.chat-react-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 2px;
  margin: 2px 2px 8px;
  padding: 4px 6px;
  border-radius: 999px;
  background: var(--chat-quote);
}

.chat-react-emoji {
  display: grid;
  place-items: center;
  width: 36px;
  height: 36px;
  border: 0;
  border-radius: 999px;
  background: transparent;
  font: inherit;
  font-size: 22px;
  line-height: 1;
  cursor: pointer;
}

.chat-react-emoji:hover {
  background: var(--chat-menu);
}

.chat-menu-item {
  display: flex;
  align-items: center;
  gap: 14px;
  width: 100%;
  min-height: 44px;
  padding: 0 12px;
  border: 0;
  border-radius: 10px;
  background: none;
  color: var(--chat-ink);
  font: inherit;
  font-size: 15px;
  text-align: left;
  cursor: pointer;
}

.chat-menu-item:hover { background: var(--chat-quote); }

.chat-menu-item.is-danger { color: var(--chat-danger); }

.chat-toast {
  position: fixed;
  left: 50%;
  bottom: calc(96px + env(safe-area-inset-bottom));
  z-index: 22;
  transform: translateX(-50%);
  margin: 0;
  padding: 8px 14px;
  border-radius: 999px;
  background: var(--chat-menu);
  color: var(--chat-ink);
  box-shadow: var(--shadow-md);
  font-size: 13px;
}

.chat-body {
  margin: 0;
  font-size: 14.5px;
  line-height: 1.35;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

.chat-reply-preview,
.chat-reply-target {
  display: grid;
  gap: 1px;
  border-left: 3px solid var(--chat-accent);
  border-radius: 4px;
  background: var(--chat-quote);
  font-size: 12.5px;
}

.chat-reply-preview {
  margin-bottom: 3px;
  padding: 4px 8px;
  color: var(--chat-muted);
}

.chat-reply-preview strong,
.chat-reply-target strong {
  color: var(--chat-accent);
  font-weight: 600;
}

.chat-reply-preview span,
.chat-reply-target span {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.chat-attachments {
  display: grid;
  gap: 3px;
  margin: 1px 0 3px;
}

.chat-attachment {
  color: inherit;
  text-decoration: none;
}

.chat-attachment-image {
  display: block;
  width: fit-content;
  max-width: 100%;
  overflow: hidden;
  border-radius: 12px;
  background: var(--chat-quote);
  cursor: zoom-in;
}

.chat-attachment-image img {
  display: block;
  width: 200px;
  max-width: 100%;
  height: auto;
  object-fit: contain;
}

.chat-attachment-file {
  display: flex;
  align-items: center;
  gap: 8px;
  min-height: 48px;
  padding: 8px;
  border-radius: 6px;
  background: var(--chat-quote);
  font-size: 13px;
}

.chat-file-icon {
  display: grid;
  place-items: center;
  flex: none;
  width: 38px;
  height: 30px;
  border-radius: 4px;
  background: #d93025;
  color: #fff;
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.04em;
}

/* Flush with the bottom of the phone. Sticky so the composer stays put while
   the log scrolls — paint the wallpaper behind it so messages do not show
   through under an attached preview. */
.chat-identify,
.chat-composer {
  position: sticky;
  bottom: 0;
  z-index: 5;
  margin: auto -10px 0;
  padding: 8px 10px calc(8px + env(safe-area-inset-bottom));
  background-color: var(--chat-wallpaper);
  background-image:
    radial-gradient(circle at 7px 7px, var(--chat-doodle) 1.5px, transparent 1.5px),
    radial-gradient(circle at 21px 21px, var(--chat-doodle) 1px, transparent 1px);
  background-size: 28px 28px, 28px 28px;
}

/* Soft blue/cyan→transparent wash from the EZRA mark, behind the composer so
   the input still floats over the wallpaper. Same cyan in light and dark. */
body.chat-screen .chat-identify::before,
body.chat-screen .chat-composer::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 150px;
  pointer-events: none;
  z-index: -1;
  background: linear-gradient(
    to top,
    color-mix(in srgb, var(--chat-fade) 50%, transparent),
    color-mix(in srgb, var(--chat-fade) 18%, transparent) 55%,
    transparent
  );
}

body.chat-screen.theme-dark .chat-identify::before,
body.chat-screen.theme-dark .chat-composer::before {
  background: linear-gradient(
    to top,
    color-mix(in srgb, var(--chat-fade) 42%, transparent),
    color-mix(in srgb, var(--chat-fade) 14%, transparent) 55%,
    transparent
  );
}

.chat-identify p {
  margin: 0 0 10px;
  color: var(--chat-muted);
  font-size: 13px;
}

.chat-composer-row {
  display: flex;
  align-items: flex-end;
  gap: 6px;
}

/* Attach is a label around the file input, so the picker still opens on a
   phone with no script running. */
.chat-attach,
.chat-emoji-toggle {
  display: grid;
  place-items: center;
  flex: none;
  width: 40px;
  height: 40px;
  border: 0;
  border-radius: 999px;
  background: transparent;
  color: var(--chat-muted);
  cursor: pointer;
}

.chat-attach {
  border: 1px solid color-mix(in srgb, var(--chat-muted) 35%, transparent);
  background: var(--chat-pill);
}

.chat-attach input { display: none; }

.chat-emoji-toggle { width: 34px; }

.chat-input-pill {
  display: flex;
  align-items: flex-end;
  flex: 1;
  min-width: 0;
  padding: 0 4px 0 12px;
  border: 1px solid color-mix(in srgb, var(--chat-muted) 35%, transparent);
  border-radius: 20px;
  background: var(--chat-pill);
}

.chat-composer textarea {
  flex: 1;
  min-width: 0;
  height: 40px;
  max-height: 120px;
  padding: 10px 0;
  border: 0;
  background: transparent;
  color: var(--chat-ink);
  font: inherit;
  font-size: 16px;
  line-height: 1.25;
  resize: none;
  overflow-y: auto;
}

.chat-composer textarea:focus { outline: none; }

.chat-composer textarea::placeholder {
  color: var(--chat-muted);
  opacity: 1;
}

.chat-send {
  display: grid;
  place-items: center;
  flex: none;
  width: 44px;
  height: 44px;
  border: 0;
  border-radius: 999px;
  background: var(--chat-send);
  color: #fff;
  cursor: pointer;
}

.chat-emoji-row {
  display: flex;
  gap: 6px;
  padding: 4px 2px 8px;
}

.chat-emoji {
  display: grid;
  place-items: center;
  min-width: 42px;
  min-height: 40px;
  border: 0;
  border-radius: 999px;
  background: transparent;
  font: inherit;
  font-size: 20px;
  line-height: 1;
  cursor: pointer;
}

.chat-file-hint {
  margin: 0 0 6px;
  padding: 0 4px;
  overflow: hidden;
  color: var(--chat-muted);
  font-size: 12px;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.chat-file-preview {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin: 0 0 8px;
  padding: 0 4px;
}

.chat-file-preview[hidden] {
  display: none;
}

.chat-file-thumb {
  display: block;
  width: 200px;
  max-width: 100%;
  height: auto;
  object-fit: contain;
  border-radius: 12px;
  background: var(--chat-quote);
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--chat-ink) 8%, transparent);
  cursor: zoom-in;
}

.chat-file-chip {
  display: inline-flex;
  align-items: center;
  max-width: 160px;
  min-height: 28px;
  padding: 4px 8px;
  overflow: hidden;
  border-radius: 999px;
  background: var(--chat-quote);
  color: var(--chat-muted);
  font-size: 12px;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Full-size image viewer — used instead of target=_blank, which iOS
   standalone / Home Screen apps often refuse to open. */
.chat-lightbox {
  position: fixed;
  inset: 0;
  z-index: 80;
  display: grid;
  place-items: center;
  padding: 16px;
  padding-bottom: calc(16px + env(safe-area-inset-bottom));
  background: rgba(11, 20, 26, 0.92);
  -webkit-tap-highlight-color: transparent;
}

.chat-lightbox[hidden] {
  display: none;
}

.chat-lightbox img {
  display: block;
  width: auto;
  height: auto;
  max-width: min(100%, 3000px);
  max-height: calc(100dvh - 48px);
  border-radius: 12px;
  object-fit: contain;
}

.chat-lightbox-close {
  position: absolute;
  top: calc(8px + env(safe-area-inset-top));
  right: 8px;
  z-index: 1;
  width: 44px;
  height: 44px;
  border: 0;
  border-radius: 999px;
  background: color-mix(in srgb, #fff 14%, transparent);
  color: #fff;
  font: inherit;
  font-size: 28px;
  line-height: 1;
  cursor: pointer;
}

.chat-reply-target {
  grid-template-columns: 1fr auto;
  align-items: center;
  margin-bottom: 6px;
  padding: 6px 8px;
}

.chat-reply-target > div {
  display: grid;
  min-width: 0;
}

.chat-reply-target button {
  border: 0;
  background: transparent;
  color: var(--chat-muted);
  font: inherit;
  font-size: 20px;
  line-height: 1;
  cursor: pointer;
}

/* — documents (attendant roles) — */

.doc-role {
  border-top: 1px solid var(--color-divider);
  padding: 0;
  scroll-margin-top: calc(56px + env(safe-area-inset-top));
}

.doc-role:first-of-type {
  border-top-color: var(--color-text);
}

.doc-role[open] {
  padding-bottom: 12px;
}

.doc-role:target .doc-when,
.doc-role[open]:target .doc-when {
  outline: 2px solid var(--color-accent-2);
  outline-offset: 2px;
}

.doc-role-head {
  display: flex;
  align-items: center;
  gap: 10px;
  list-style: none;
  cursor: pointer;
  min-height: 44px;
  padding: 12px 0;
}

.doc-role-head::-webkit-details-marker,
.doc-role-head::marker { display: none; content: none; }

.doc-role-head > div {
  flex: 1;
  min-width: 0;
}

.doc-role-head::after {
  content: '';
  width: 8px;
  height: 8px;
  flex: none;
  margin-top: -4px;
  border-right: 2px solid var(--color-neutral-700);
  border-bottom: 2px solid var(--color-neutral-700);
  transform: rotate(45deg);
  transition: transform 0.15s ease, margin-top 0.15s ease;
}

.doc-role[open] > .doc-role-head::after {
  margin-top: 4px;
  transform: rotate(225deg);
}

.doc-role-icon {
  flex: none;
  color: var(--color-accent);
  line-height: 1;
}

.doc-role-title {
  font-size: 18px;
  font-weight: 600;
  letter-spacing: -0.02em;
  line-height: 1.2;
  margin: 0;
}

.doc-role-detail {
  font-size: 12px;
  font-weight: 600;
  color: var(--color-accent-2-700);
  margin-top: 2px;
}

.doc-when {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
  margin: 12px 0 10px;
  padding: 10px 12px;
  background: var(--color-accent-2-100);
  border-radius: var(--radius-md);
}

.doc-when-slot {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}

.doc-when-label {
  font-size: 10px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--color-accent-2-700);
}

.doc-when-time {
  font-size: 16px;
  font-weight: 600;
  letter-spacing: -0.02em;
  line-height: 1.2;
  color: var(--color-text);
}

.doc-when-note {
  font-size: 12px;
  line-height: 1.35;
  color: var(--color-neutral-700);
}

.doc-group {
  font-size: 13px;
  font-style: italic;
  font-weight: 600;
  margin: 12px 0 4px;
}

.doc-points {
  margin: 0;
  padding: 0 0 0 1.15em;
}

.doc-points li {
  margin: 5px 0;
}

.doc-points strong {
  font-weight: 600;
  color: var(--color-text);
}

.doc-emergency {
  margin: 12px 0 4px;
  padding: 10px 12px;
  background: var(--color-surface);
  border-left: 3px solid var(--color-accent-2);
  border-radius: 0 var(--radius-md) var(--radius-md) 0;
  font-size: 14px;
}

.doc-emergency-label {
  display: block;
  font-size: 10px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--color-accent-2-700);
  font-weight: 600;
  margin-bottom: 4px;
}

/* — proof sheet (generate) — */

.proof-group {
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--color-neutral-700);
  border-bottom: 1px solid var(--color-text);
  padding-bottom: 5px;
  margin-top: var(--space-4);
}

.proof-row {
  display: flex;
  gap: 10px;
  align-items: flex-start;
  padding: 11px 0;
  border-bottom: 1px solid var(--color-divider);
}

.proof-row-bschool {
  background: var(--color-accent-2-100);
  margin: 0 -8px;
  padding-left: 8px;
  padding-right: 8px;
}

.proof-row-bschool .proof-reason { color: var(--color-accent-2-700); }
.proof-row-open .proof-reason { color: var(--color-accent-2-700); }

.proof-main { flex: 1; min-width: 0; }
.proof-name { font-size: 15px; }
.proof-reason { font-size: 12px; color: var(--color-neutral-700); }

.proof-action {
  font-size: 12px;
  color: var(--color-accent);
  background: none;
  border: 0;
  cursor: pointer;
  padding: 8px 4px;
  min-height: 44px;
  font-family: inherit;
}

.sheet-actions {
  display: flex;
  gap: 8px;
  align-items: center;
  padding: 12px 0 16px;
  border-top: 1px solid var(--color-divider);
  margin-top: var(--space-3);
}

.sheet-actions .btn { min-height: 44px; }
.sheet-actions form:first-child { flex: 1; }
.sheet-actions form:first-child .btn { width: 100%; }

/* — month view — */

.month-grid {
  display: flex;
  flex-direction: column;
}

.week-block {
  padding: 13px 0;
  border-top: 1px solid var(--color-divider);
  display: block;
  text-decoration: none;
  color: inherit;
}

.week-block-current { border-top: 1px solid var(--color-text); }

.week-block-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--space-2);
}

.week-block-title {
  font-size: 17px;
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 8px;
}

.week-block-dates { font-size: 12px; color: var(--color-neutral-700); }
.week-block-note { font-size: 12px; color: var(--color-neutral-700); margin-top: 7px; }
.week-block-note-diff { color: var(--color-accent-2-700); }


/* — quarter — */

.q-summary {
  font-size: 12px;
  color: var(--color-neutral-700);
  margin: 0 0 2px;
}

.q-summary-open { color: var(--color-accent-2-700); }

.q-month { margin-top: 18px; }

.q-month-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--space-2);
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--color-accent);
  border-bottom: 2px solid var(--color-text);
  padding-bottom: 4px;
  text-decoration: none;
}

.q-month-open { color: var(--color-accent-2-700); letter-spacing: 0.04em; }

/* One line per week: the label column is fixed so the chips of every week
   start on the same vertical, which is what makes the run readable. */
.q-week {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 9px 0;
  border-top: 1px solid var(--color-divider);
  text-decoration: none;
  color: inherit;
  min-height: 44px;
}

.q-week:first-of-type { border-top: 0; }

/* Colour rather than a rule: a border here would read as another row divider. */
.q-week-current .q-week-no { color: var(--color-accent); }

.q-week-label { flex: none; width: 88px; }
.q-week-no { font-size: 14px; display: block; }

.q-week-b {
  display: inline-block;
  min-width: 15px;
  padding: 0 3px;
  border-radius: 3px;
  background: var(--color-neutral-700);
  color: var(--color-bg);
  font-size: 10px;
  line-height: 15px;
  text-align: center;
  vertical-align: 2px;
}

.q-week-dates {
  font-size: 11px;
  color: var(--color-neutral-700);
  display: block;
}

.q-week-team {
  display: flex;
  flex-wrap: wrap;
  gap: 5px;
  flex: 1;
  min-width: 0;
}

.q-week-team .chip-rows {
  margin-top: 0;
  width: 100%;
  gap: 4px;
}

.q-week-team .chip-dept-label {
  width: 6.5em;
}

.q-week-team .chip-row {
  gap: 0;
}

.q-week-empty {
  font-size: 12px;
  color: var(--color-neutral-700);
  font-style: italic;
}


/* — me — */

.me-head {
  padding: 12px var(--space-4) 14px;
  display: flex;
  gap: 12px;
  align-items: center;
}

.me-name { font-size: 25px; margin: 0; letter-spacing: -0.02em; }
.me-trained { font-size: 12px; color: var(--color-neutral-700); }

.month-head {
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--color-accent);
  border-bottom: 2px solid var(--color-text);
  padding-bottom: 4px;
  margin: var(--space-4) 0 0;
}

.month-head:first-of-type { margin-top: 0; }

.duty {
  border-top: 1px solid var(--color-divider);
  padding: 12px 0;
  display: flex;
  gap: 12px;
  align-items: center;
}

.duty-when {
  display: flex;
  flex: none;
  align-items: center;
  gap: 4px;
}

.duty-rail { width: auto; min-width: 2em; }
.duty-day { font-size: 16px; }
.duty-weekday { font-size: 11px; color: var(--color-neutral-700); letter-spacing: 0.04em; }
.duty-icon { flex: none; color: var(--color-neutral-700); }
.duty-body { flex: 1; min-width: 0; }
.duty-task { font-size: 16px; }
.duty-bschool { font-size: 12px; color: var(--color-accent-2-700); }
.duty-detail { font-size: 12px; color: var(--color-neutral-700); }
.duty-detail-bschool { color: var(--color-accent-2-700); }

.duty-actions {
  display: flex;
  flex: none;
  align-items: center;
  gap: 2px;
}

.duty-answer {
  display: flex;
  align-items: center;
  gap: 2px;
  margin: 0;
}

.duty-action {
  display: grid;
  place-items: center;
  min-width: 40px;
  min-height: 44px;
  padding: 0 4px;
  background: none;
  border: 0;
  color: var(--color-neutral-700);
  text-decoration: none;
  font: inherit;
  font-size: 12px;
  cursor: pointer;
}

.duty-action.is-on {
  color: var(--color-accent);
}

.duty-action-no:hover { color: var(--color-accent-2-700); }

.duty-swap {
  color: var(--color-accent);
  padding: 0 6px;
}

.stack {
  margin-top: 22px;
  display: flex;
  flex-direction: column;
  gap: 9px;
}

.stack .btn { margin: 0; min-height: 44px; }

/* — away dates — */

.away-month {
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--color-neutral-700);
  border-bottom: 1px solid var(--color-text);
  padding-bottom: 4px;
  margin: var(--space-4) 0 10px;
}

.away-sub { font-size: 11px; color: var(--color-neutral-700); margin: 0 0 7px; }

.away-row {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 8px;
  margin-bottom: 8px;
}

.away-chip {
  position: relative;
  width: auto;
  min-width: 0;
  aspect-ratio: 1;
  padding: 6px;
  border-radius: var(--radius-md);
  text-align: center;
  border: 1px solid var(--color-divider);
  background: none;
  color: inherit;
  font: inherit;
  cursor: pointer;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
}

.away-chip input {
  position: absolute;
  opacity: 0;
  width: 0;
  height: 0;
  pointer-events: none;
}

.away-chip-date { display: block; font-size: 18px; line-height: 1.1; }
.away-chip-state { font-size: 10px; color: var(--color-neutral-700); }

.away-chip-icon {
  display: grid;
  place-items: center;
  width: 24px;
  height: 24px;
  color: inherit;
}

.away-chip-icon .icon {
  display: block;
}

.away-chip.is-rostered {
  border: 3px solid var(--away-roster-color, var(--color-accent));
  color: var(--away-roster-color, var(--color-accent));
}

.away-chip.is-rostered.is-av {
  --away-roster-color: var(--color-accent);
}

.away-chip.is-rostered.is-attendants {
  --away-roster-color: var(--color-accent-2);
}

.away-chip:has(input:checked),
.away-chip.is-away {
  background: var(--color-neutral-300);
  border-color: var(--color-neutral-500);
  color: var(--color-neutral-700);
}

.away-chip.is-rostered:has(input:checked) {
  border-color: var(--color-neutral-500);
  color: var(--color-neutral-700);
}

.away-chip:has(input:checked) .away-chip-state { color: var(--color-neutral-700); }

.away-chip:has(input:focus-visible) { outline: 2px solid var(--color-accent); outline-offset: 2px; }

.away-chip.is-past { opacity: 0.5; cursor: not-allowed; }

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* — admin — */

.person-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--space-2);
  padding: 10px 0;
  border-top: 1px solid var(--color-divider);
  min-height: 44px;
}

.person-row:first-of-type { border-top: 1px solid var(--color-text); }

summary.add-person-row {
  justify-content: flex-start;
  gap: 9px;
  border-top: 1px solid var(--color-text);
  color: var(--color-accent);
  cursor: pointer;
  list-style: none;
}

summary.add-person-row .icon {
  flex: none;
}

summary.add-person-row::-webkit-details-marker,
summary.add-person-row::marker { display: none; content: none; }

.person-id {
  display: flex;
  align-items: center;
  gap: 9px;
  min-width: 0;
  flex: 1;
}

.person-dot {
  width: 18px;
  height: 18px;
  flex: none;
  border-radius: 50%;
  background: var(--dot);
}

/* Load across the quarter, kept to initials and a count so twenty-four people
   fit in a few lines rather than a table the coordinator has to scroll. */
.turns {
  padding-bottom: 12px;
  margin-bottom: 4px;
  border-bottom: 1px solid var(--color-divider);
}

.turns-head {
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--color-neutral-700);
  margin-bottom: 8px;
}

.turns-list {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 11px;
  font-size: 13px;
  font-variant-numeric: tabular-nums;
}

.turn { white-space: nowrap; color: var(--color-neutral-700); }

.turn-initials {
  font-weight: 600;
  color: var(--ink);
  margin-right: 3px;
}

/* Nobody should sit at zero for a whole quarter. */
.turn-zero .turn-count { color: var(--color-accent-2-700); }

.person-name {
  font-size: 15px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.person-name-inactive { color: var(--color-neutral-500); text-decoration: line-through; }

.away-sheet-head {
  display: block;
  font-size: 12px;
  margin-bottom: 5px;
  color: color-mix(in srgb, var(--color-text) 70%, transparent);
}

.person-edit-actions {
  display: flex;
  gap: 8px;
  margin-top: var(--space-3);
}

.person-edit-actions .btn {
  flex: 1;
  min-height: 44px;
  margin-top: 0;
}

.person-remove {
  margin: 4px 0 16px;
}

.person-remove .btn {
  color: var(--color-accent-2-700);
  margin-top: 0;
}

.skill-toggles { display: flex; gap: 4px; }

.skill-toggle {
  width: 34px;
  height: 34px;
  display: grid;
  place-items: center;
  border-radius: var(--radius-md);
  border: 1px solid var(--color-divider);
  background: none;
  color: var(--color-neutral-400);
  cursor: pointer;
  padding: 0;
}

.skill-toggle.is-on {
  background: var(--color-accent-100);
  border-color: var(--color-accent-100);
  color: var(--color-accent-700);
}

/* The painted box is still under the 44px touch minimum, so the tap area is
   widened beyond it rather than the box being grown to the full target. */
.skill-toggle::after {
  content: "";
  position: absolute;
  inset: -9px -2px;
}

.skill-toggle { position: relative; }

.task-item { border-top: 1px solid var(--color-divider); }

.task-row {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: 12px 0;
  flex-wrap: nowrap;
}

summary.task-row {
  list-style: none;
  cursor: pointer;
}

summary.task-row::-webkit-details-marker,
summary.task-row::marker { display: none; content: none; }

.task-row-summary {
  flex: 1;
  min-width: 0;
  font-size: 15px;
  line-height: 1.35;
}

.task-row-main { flex: 1; min-width: 140px; }
.task-row-label { font-size: 15px; }
.task-row-meta { font-size: 12px; color: var(--color-neutral-700); }
.task-row-fields { display: flex; gap: 6px; align-items: center; flex-wrap: wrap; }
.task-row-fields .input { width: auto; min-width: 62px; }

.task-edit {
  padding: 0 0 14px;
}

.task-edit .task-row-fields { margin-bottom: 10px; }

/* — unlock — */

.dimmed { opacity: 0.35; pointer-events: none; }

.dim-line {
  border-top: 1px solid var(--color-divider);
  padding: 11px 0;
  font-size: 16px;
}

.sheet {
  position: sticky;
  bottom: 0;
  background: var(--color-surface);
  box-shadow: var(--shadow-lg);
  border-radius: var(--radius-lg) var(--radius-lg) 0 0;
  padding: 22px var(--space-4) 20px;
  margin-top: auto;
}

.sheet h3 { font-size: 23px; margin: 4px 0 8px; letter-spacing: -0.02em; }
.sheet p { font-size: 13px; margin: 0 0 16px; color: var(--color-neutral-800); }
.sheet .btn { min-height: 44px; }
.sheet-note { font-size: 11px; color: var(--color-neutral-700); margin: 14px 0 0; }

/* Passcode pad sits in the middle of the screen, not as a bottom sheet. */
body.unlock-screen .page.dimmed { display: none; }

body.unlock-screen .tabbar { display: none; }

body.unlock-screen .phone:has(.tabbar) {
  padding-bottom: env(safe-area-inset-bottom);
}

body.unlock-screen .sheet {
  flex: 1;
  display: flex;
  flex-direction: column;
  justify-content: center;
  position: static;
  margin: 0;
  box-shadow: none;
  border-radius: 0;
  background: transparent;
  padding-top: 12px;
  padding-bottom: 12px;
}

.sheet .unlock-welcome {
  font-size: 34px;
  font-weight: 700;
  letter-spacing: -0.03em;
  line-height: 1.15;
  margin: 0 0 10px;
  text-align: center;
}

.sheet .unlock-prompt {
  font-size: 15px;
  text-align: center;
  margin: 0 0 22px;
  color: var(--color-neutral-800);
}

.input.is-numpad-bound {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
  pointer-events: none;
}

.unlock-form.is-numpad .field label { display: none; }

.pin-dots {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 12px;
  min-height: 28px;
  margin: 4px 0 14px;
}

.pin-dot {
  width: 12px;
  height: 12px;
  border-radius: 50%;
  border: 2px solid var(--color-text);
  box-sizing: border-box;
}

.pin-dot.is-filled { background: var(--color-text); }

.numpad {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 8px;
  max-width: 260px;
  margin: 0 auto 12px;
}

.numpad-key {
  aspect-ratio: 1;
  width: 100%;
  max-width: 64px;
  min-height: 0;
  justify-self: center;
  display: grid;
  place-items: center;
  font-family: inherit;
  font-size: 22px;
  font-weight: 500;
  border: 1px solid var(--color-divider);
  border-radius: 50%;
  background: var(--color-bg);
  color: var(--color-text);
  cursor: pointer;
  padding: 0;
}

.numpad-key:active { background: var(--color-surface); }

.numpad-key-action {
  font-size: 20px;
  color: var(--color-neutral-700);
}

.numpad-key-go {
  background: var(--color-accent);
  border-color: var(--color-accent);
  color: var(--color-bg);
  font-size: 16px;
}

/* — reassign picker — */

.picker-backdrop {
  position: fixed;
  inset: 0;
  background: color-mix(in srgb, var(--color-neutral-900) 50%, transparent);
  display: flex;
  align-items: flex-end;
  justify-content: center;
  z-index: 20;
}

.picker {
  background: var(--color-surface);
  box-shadow: var(--shadow-lg);
  border-radius: var(--radius-lg) var(--radius-lg) 0 0;
  padding: 20px var(--space-4);
  width: 100%;
  max-width: 560px;
  max-height: 82vh;
  overflow-y: auto;
}

.picker h3 { font-size: 20px; margin: 4px 0 12px; }

.picker-option {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 10px 0;
  border: 0;
  border-top: 1px solid var(--color-divider);
  background: none;
  font: inherit;
  color: inherit;
  cursor: pointer;
  text-align: left;
  min-height: 48px;
}

.picker-option:disabled { opacity: 0.45; cursor: not-allowed; }
.picker-option-name { flex: 1; font-size: 16px; }
.picker-option-meta { font-size: 12px; color: var(--color-neutral-700); }

/* — misc — */

.icon { display: block; }

.list-plain { list-style: none; margin: 0; padding: 0; }

/* — tablet and desktop —
 *
 * The phone layout is the design, so nothing below reflows it; these rules only
 * let screens with room to spare use that room. Width is given out where it
 * buys something — a second column of weeks — and withheld where it does not:
 * stretching a list of names across a monitor makes it harder to read, not
 * easier, so the reading screens keep a comfortable measure and only the
 * grid-shaped ones opt in with `roomy`. */

@media (min-width: 700px) {
  .phone { max-width: 720px; }

  /* Main hall and B School, side by side. auto-fit means a Saturday, which has
     no B School, still fills the width rather than leaving a hole. */
  .slot-columns {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
    column-gap: 34px;
    align-items: start;
  }

  /* One month per column, so these do want to line up. */
  .quarter-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    column-gap: 34px;
    align-items: start;
  }

  /* The stacking margin becomes a gap once these sit in a grid. */
  .quarter-grid .q-month { margin-top: 0; }
  .quarter-grid { row-gap: 22px; }

  .statusbar-name { font-size: 26px; }
  .week-rail-label { font-size: 21px; }
}

/* Wide enough for both departments of one day. Day tabs stay, because the
   screen is still one meeting; confirm buttons stay for the same reason. */
@media (min-width: 900px) {
  /* Same shell for Week, Month and Quarter so the sticky header does not
     slide sideways when the view switcher is used. */
  body.paired .phone,
  body.roomy .phone { max-width: 880px; }

  .day-columns {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    column-gap: 34px;
    align-items: start;
  }

  .day-column + .day-column { margin-top: 0; }

  .group-head-align {
    font-size: 11px;
    letter-spacing: 0.12em;
    padding-bottom: 4px;
  }
}

@media (min-width: 1024px) {
  body.paired .phone,
  body.roomy .phone { max-width: 1140px; }

  body.roomy .quarter-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

@media print {
  .tabbar, .week-rail, .seg, .btn, .proof-action { display: none !important; }
  .phone { max-width: none; }
}
