/* DND Scheduler Mini App — hand-rolled stylesheet on Telegram theme variables.
   Light AND dark themes share the #472a5e purple accent. Inside Telegram the
   --tg-theme-* variables are set by the client; in a plain dev browser we fall
   back via prefers-color-scheme. */

:root {
  --accent: #472a5e;
  --accent-text: #ffffff;
  --bg: var(--tg-theme-bg-color, #ffffff);
  --bg-secondary: var(--tg-theme-secondary-bg-color, #f1eef5);
  --text: var(--tg-theme-text-color, #1c1424);
  --hint: var(--tg-theme-hint-color, #777080);
  --link: var(--tg-theme-link-color, #5a3a75);
  --danger: #b3364b;
  /* danger as TEXT, which needs contrast against the page rather than white-on-red like
     the toast: the base red is too dark to read on the dark theme's background */
  --danger-text: var(--danger);
  --ok: #2e7d4f;
  --border: color-mix(in srgb, var(--hint) 30%, transparent);
  --radius: 10px;
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg: var(--tg-theme-bg-color, #181320);
    --bg-secondary: var(--tg-theme-secondary-bg-color, #241c30);
    --text: var(--tg-theme-text-color, #eee8f4);
    --hint: var(--tg-theme-hint-color, #9c93a8);
    --link: var(--tg-theme-link-color, #b79ad1);
    --danger-text: #ff6b81;
  }
}

* { box-sizing: border-box; }
body {
  margin: 0;
  font-family: -apple-system, system-ui, "Segoe UI", Roboto, sans-serif;
  background: var(--bg);
  color: var(--text);
  font-size: 15px;
}
button {
  font: inherit;
  border: 1px solid var(--border);
  background: var(--bg-secondary);
  color: var(--text);
  border-radius: var(--radius);
  padding: 7px 14px;
  cursor: pointer;
}
button.primary { background: var(--accent); border-color: var(--accent); color: var(--accent-text); }
button.danger { color: var(--danger-text); border-color: var(--danger-text); }
button.link { border: none; background: none; color: var(--link); padding: 4px; }
/* .link and .danger have equal specificity, so a "link danger" button was rendering in
   the plain link colour — every destructive text button in the app was quietly blue */
button.link.danger { color: var(--danger-text); }
button:disabled { opacity: 0.5; cursor: default; }
input, select, textarea {
  font: inherit;
  background: var(--bg);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 7px 10px;
  width: 100%;
}
label { display: block; margin: 10px 0 4px; color: var(--hint); font-size: 13px; }
input.invalid, select.invalid, textarea.invalid {
  border-color: var(--danger);
  box-shadow: 0 0 0 1px var(--danger);
}

.app-header {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 12px;
  background: var(--accent);
  color: var(--accent-text);
  position: sticky;
  top: 0;
  z-index: 5;
}
.app-header h1 { font-size: 16px; margin: 0; flex: 1; }
.app-header select { width: auto; background: color-mix(in srgb, var(--accent) 80%, #fff); color: var(--accent-text); border-color: transparent; }

.tabs { display: flex; border-bottom: 1px solid var(--border); background: var(--bg); }
.tabs button { flex: 1; border: none; border-radius: 0; background: none; padding: 10px 4px; color: var(--hint); }
.tabs button.active { color: var(--accent); box-shadow: inset 0 -2px 0 var(--accent); font-weight: 600; }
@media (prefers-color-scheme: dark) {
  .tabs button.active { color: var(--link); box-shadow: inset 0 -2px 0 var(--link); }
}

.page { padding: 12px; max-width: 760px; margin: 0 auto; }
.row { display: flex; gap: 8px; align-items: center; }
.grow { flex: 1; }
/* Date&time + duration share a 2-row grid: labels on row 1, inputs on row 2. The
   input row therefore starts below the TALLER label, so the two inputs line up even
   when "Duration, minutes" wraps to two lines; the date echo drops into row 3. */
.dt-grid { display: grid; grid-template-columns: 1fr 76px; column-gap: 8px; align-items: start; }
.dt-grid .dt-echo { grid-column: 1; margin: 4px 0 0; }

/* one-tap preset chips above the reminder list */
.preset-chips { display: flex; flex-wrap: wrap; gap: 6px; margin: 0 0 10px; }
.preset-chip {
  border: 1px solid var(--border);
  background: var(--bg-secondary);
  color: var(--link);
  border-radius: 999px;
  padding: 3px 12px;
  font-size: 13px;
  cursor: pointer;
}
.preset-chip:hover { border-color: var(--accent); color: var(--accent); }

/* reminder rows: "[N] [unit ▾] before the game" on one line, message below */
.reminder-row { margin-bottom: 10px; }
.reminder-row .rem-amount { max-width: 5em; flex: 0 0 auto; text-align: center; }
.reminder-row .rem-unit { width: auto; flex: 0 0 auto; }
.reminder-row .rem-before { color: var(--hint); font-size: 13px; white-space: nowrap; }
.reminder-row .rem-del { margin-left: auto; }
.reminder-row > input { margin-top: 6px; }
.reminder-row .rem-ping {
  display: flex;
  align-items: center;
  gap: 6px;
  margin: 6px 0 0;
  color: var(--hint);
  font-size: 13px;
  cursor: pointer;
}
.reminder-row .rem-ping input { width: auto; }
.hint { color: var(--hint); font-size: 13px; }
.card {
  background: var(--bg-secondary);
  border-radius: var(--radius);
  padding: 12px;
  margin-bottom: 10px;
}

/* calendar */
.cal-nav { display: flex; gap: 6px; align-items: center; margin-bottom: 8px; }
.cal-title { flex: 1; font-weight: 600; text-transform: capitalize; }
.cal-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 3px; }
.cal-dow { text-align: center; color: var(--hint); font-size: 11px; padding: 2px 0; }
.cal-day {
  min-height: 64px;
  border-radius: 6px;
  background: var(--bg-secondary);
  padding: 2px 3px;
  font-size: 11px;
  overflow: hidden;
}
.cal-day.other { opacity: 0.4; }
.cal-day.clickable, .week-day h3.clickable { cursor: pointer; }
.cal-day.clickable:hover { outline: 1px solid var(--hint); }
.cal-day .num { color: var(--hint); }
/* today reads at a glance: the date itself sits in a filled accent disc. The disc
   carries the emphasis, so the cell keeps only a soft ring instead of a hard one. */
.cal-day.today { outline: 1px solid var(--accent); }
.cal-day.today .num {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 18px;
  height: 18px;
  padding: 0 4px;
  box-sizing: border-box;
  border-radius: 9px;
  background: var(--accent);
  color: #fff;
  font-weight: 600;
}
.chip {
  display: block;
  width: 100%;
  text-align: left;
  border: none;
  border-radius: 5px;
  padding: 2px 4px;
  margin-top: 2px;
  font-size: 11px;
  line-height: 1.25;
  color: #fff;
  background: var(--hint);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.chip.locked { background: var(--accent); }
.chip.unlocked { background: color-mix(in srgb, var(--accent) 45%, var(--hint)); }
.chip.mine { box-shadow: inset 0 0 0 1.5px #ffd54a; }

.week-day { margin-bottom: 10px; }
.week-day h3 { margin: 4px 0; font-size: 14px; text-transform: capitalize; }
.slot-card { cursor: pointer; }
.slot-card .status { font-size: 12px; font-weight: 600; }
.status.locked { color: var(--ok); }
.status.unlocked { color: var(--hint); }

/* modal */
.overlay {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.45);
  display: flex;
  align-items: flex-end;
  justify-content: center;
  z-index: 10;
}
.modal {
  background: var(--bg);
  border-radius: 14px 14px 0 0;
  padding: 16px;
  width: 100%;
  max-width: 640px;
  max-height: 88vh;
  overflow-y: auto;
}
@media (min-width: 700px) {
  .overlay { align-items: center; }
  .modal { border-radius: 14px; }
}
.modal h2 { margin: 0 0 10px; font-size: 17px; }
.modal .actions { display: flex; gap: 8px; margin-top: 14px; justify-content: flex-end; flex-wrap: wrap; }

.game-row { display: flex; align-items: center; gap: 8px; padding: 6px 0; border-bottom: 1px solid var(--border); }
.badge {
  font-size: 11px;
  border-radius: 999px;
  padding: 1px 8px;
  background: var(--bg-secondary);
  color: var(--hint);
}
.badge.ok { background: var(--ok); color: #fff; }
.badge.accent { background: var(--accent); color: #fff; }
.tabs .badge { margin-left: 4px; }

/* pending party invitees, listed beside confirmed members but visibly not yet in */
.muted { color: var(--hint); opacity: 0.75; }

/* party member rows and the invite picker.
   The picker is a people list, so it gets people-list affordances: a full-width tap
   target, an initial disc to scan by, and TWO selection indicators (tinted row + check)
   rather than one small box. */
.member-row, .pick-row {
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: 40px;
  margin: 0;
  color: var(--text);
  font-size: 15px;
}
.member-row { padding: 2px 0; }
.pick-row {
  min-height: 44px; /* touch target */
  padding: 5px 8px;
  border-bottom: 1px solid var(--border);
  border-radius: 8px;
  cursor: pointer;
}
.pick-row.picked { background: color-mix(in srgb, var(--accent) 14%, transparent); }
.pick-row .pick-name, .pick-row .hint { display: block; }
.pick-check { visibility: hidden; color: var(--accent); font-weight: 700; }
.pick-row.picked .pick-check { visibility: visible; }
@media (prefers-color-scheme: dark) {
  .pick-check { color: var(--link); }
}
.pick-search { margin-bottom: 8px; }
.pick-list { max-height: 46vh; overflow-y: auto; }
.avatar {
  flex: 0 0 auto;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--accent);
  color: var(--accent-text);
  font-weight: 600;
  font-size: 13px;
}
/* remove a member / revoke an invite: destructive, so it gets a real tap target */
.row-x {
  flex: 0 0 auto;
  width: 32px;
  height: 32px;
  padding: 0;
  border: none;
  background: none;
  color: var(--danger-text);
  line-height: 1;
}
/* the add-without-inviting escape hatch: separated from the invite path and named for
   what it does, so there is no mode to slip on */
.danger-zone { margin-top: 14px; padding-top: 10px; border-top: 1px solid var(--border); }
.danger-zone .hint { margin: 2px 0 0; }
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}
/* an invite addressed to you, and the party-only notice on a slot: both are
   "this concerns you" cards that must not read as ordinary body text */
.accent-card { border-left: 3px solid var(--accent); }

.toast {
  position: fixed;
  bottom: 14px;
  left: 50%;
  transform: translateX(-50%);
  background: var(--danger);
  color: #fff;
  border-radius: var(--radius);
  padding: 9px 16px;
  z-index: 20;
  max-width: 90vw;
}
.toast.ok { background: var(--ok); }
/* Date & time are flatpickr controls (shared.js): ordinary text inputs that inherit
   the base `input` styling. Only the width differs — the time is a fixed narrow field,
   the date fills the rest of its row. They are read-only (tap to open the picker). */
.fp-time { width: 7em; flex: 0 0 auto; text-align: center; }
.fp-date { flex: 1; min-width: 0; }
.fp-input[readonly] { cursor: pointer; }

/* flatpickr's popup, themed onto the app variables so it reads correctly in both
   light and dark — the vendored stylesheet ships a light theme only. */
.flatpickr-calendar {
  background: var(--bg);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: 0 6px 24px rgba(0, 0, 0, 0.35);
}
.flatpickr-months,
.flatpickr-weekdays,
span.flatpickr-weekday { background: var(--bg); color: var(--hint); fill: var(--text); }
.flatpickr-current-month,
.flatpickr-current-month input.cur-year,
.flatpickr-monthDropdown-months { color: var(--text); }
.flatpickr-monthDropdown-months { background: var(--bg); }
.flatpickr-prev-month svg,
.flatpickr-next-month svg { fill: var(--text); }
.flatpickr-prev-month:hover svg,
.flatpickr-next-month:hover svg { fill: var(--accent); }
.flatpickr-day { color: var(--text); border-radius: 6px; }
.flatpickr-day:hover,
.flatpickr-day:focus { background: var(--bg-secondary); border-color: var(--bg-secondary); }
.flatpickr-day.today { border-color: var(--accent); }
.flatpickr-day.selected,
.flatpickr-day.selected:hover {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--accent-text);
}
.flatpickr-day.flatpickr-disabled,
.flatpickr-day.prevMonthDay,
.flatpickr-day.nextMonthDay { color: var(--hint); }
.flatpickr-time input,
.flatpickr-time .flatpickr-am-pm,
.flatpickr-time .flatpickr-time-separator { color: var(--text); }
.flatpickr-time input:hover,
.flatpickr-time input:focus,
.flatpickr-time .flatpickr-am-pm:hover,
.flatpickr-time .flatpickr-am-pm:focus { background: var(--bg-secondary); }
.numInputWrapper span { border-color: var(--border); }
.numInputWrapper span:hover { background: var(--bg-secondary); }
.numInputWrapper span.arrowUp::after { border-bottom-color: var(--hint); }
.numInputWrapper span.arrowDown::after { border-top-color: var(--hint); }
/* popup pointer blends into the panel in both themes */
.flatpickr-calendar.arrowTop::before { border-bottom-color: var(--border); }
.flatpickr-calendar.arrowTop::after { border-bottom-color: var(--bg); }
.flatpickr-calendar.arrowBottom::before { border-top-color: var(--border); }
.flatpickr-calendar.arrowBottom::after { border-top-color: var(--bg); }
/* the undo offer is informational, not an error — neutral surface, action attached */
.toast.undo {
  display: flex;
  align-items: center;
  gap: 12px;
  background: var(--bg-secondary);
  color: var(--text);
  border: 1px solid var(--border);
}
.toast.undo button {
  background: none;
  border: none;
  padding: 0;
  color: var(--accent-text, var(--accent));
  font-weight: 600;
  cursor: pointer;
}

table { width: 100%; border-collapse: collapse; }
td, th { padding: 8px 6px; border-bottom: 1px solid var(--border); text-align: left; }
