:root {
  /* Lets the native checkbox and scrollbar follow the theme instead of
     staying light-mode bright against a dark page. */
  color-scheme: light dark;

  --bg: #f6f7f9;
  --panel: #ffffff;
  --border: #e3e6ea;
  --text: #1c1f23;
  --muted: #7a828c;
  --accent: #2f6fed;
  --danger: #d1443c;
  --ok: #2c9c62;
  --radius: 10px;
  --shadow: 0 1px 2px rgba(16, 24, 40, 0.06), 0 8px 24px rgba(16, 24, 40, 0.06);
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg: #14161a;
    --panel: #1c1f24;
    --border: #2b3038;
    --text: #e7eaee;
    --muted: #949ca7;
    --accent: #6f9dff;
    --danger: #f0736a;
    --ok: #5ac48b;
    --shadow: 0 1px 2px rgba(0, 0, 0, 0.4), 0 8px 24px rgba(0, 0, 0, 0.3);
  }
}

* {
  box-sizing: border-box;
}

html,
body {
  height: 100%;
  margin: 0;
}

html {
  -webkit-text-size-adjust: 100%; /* iOS otherwise inflates text in landscape */
}

body {
  background: var(--bg);
  color: var(--text);
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  font-size: 14px;
  line-height: 1.5;
  /* The list scrolls, the page never does — so a drag that runs past the end of
     the list must not turn into pull-to-refresh or rubber-band the whole app. */
  overscroll-behavior-y: none;
}

/* No 300ms double-tap-to-zoom wait on anything meant to be tapped. */
.task__check,
.task__title,
.task__action,
.task__edit-command,
.btn {
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
}

.hidden {
  display: none !important;
}

.muted,
.dot {
  color: var(--muted);
  font-size: 12px;
}

/* Layout — narrower than temp: a todo list that needs width is too long. */
.app {
  --gutter: 20px;

  display: flex;
  flex-direction: column;
  height: 100%;
  height: 100dvh; /* follows the mobile toolbars as they hide and reappear */
  margin: 0 auto;
  max-width: 640px;
  padding: var(--gutter);
  /* Clear of the notch and the home indicator, so the compose box at the bottom
     is not sitting under the bar you swipe up on. --keyboard is set from JS and
     is 0 everywhere except iOS with the on-screen keyboard open. */
  padding-top: calc(var(--gutter) + env(safe-area-inset-top, 0px));
  padding-right: calc(var(--gutter) + env(safe-area-inset-right, 0px));
  padding-bottom: calc(var(--gutter) + env(safe-area-inset-bottom, 0px) + var(--keyboard, 0px));
  padding-left: calc(var(--gutter) + env(safe-area-inset-left, 0px));
}

/* Topbar */
.topbar {
  align-items: center;
  display: flex;
  flex-wrap: wrap;
  gap: 8px 12px;
  padding-bottom: 12px;
}

.topbar__title {
  font-size: 16px;
  font-weight: 600;
  margin: 0;
}

.topbar__meta {
  align-items: center;
  display: flex;
  flex: 1;
  flex-wrap: wrap;
  gap: 6px;
  min-width: 0;
}

/* Status */
.status {
  font-size: 12px;
  color: var(--muted);
}

.status--live {
  color: var(--ok);
}

/* Pulsing dot: shows at a glance that the realtime stream is connected. */
.status--live::before {
  animation: pulse 2s ease-in-out infinite;
  background: var(--ok);
  border-radius: 50%;
  content: '';
  display: inline-block;
  height: 7px;
  margin-right: 5px;
  vertical-align: baseline;
  width: 7px;
}

.status--error {
  color: var(--danger);
}

@keyframes pulse {
  50% {
    opacity: 0.35;
  }
}

@media (prefers-reduced-motion: reduce) {
  .status--live::before {
    animation: none;
  }
}

/* Compose — under the list, not above it. On a phone this is the only control
   you reach for repeatedly, and the bottom of the screen is where the thumb
   already is and where the keyboard opens next to it. */
.compose {
  padding-top: 12px;
}

.compose__input {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  color: var(--text);
  font-family: inherit;
  /* 16px is a floor, not a preference: iOS zooms the page in on focus for
     anything smaller, and never zooms back out. */
  font-size: 16px;
  outline: none;
  padding: 13px 16px;
  width: 100%;
}

.compose__input:focus {
  border-color: var(--accent);
}

/* Only while the first load is in flight. */
.compose__input:disabled {
  opacity: 0.6;
}

/* List — scrolls on its own so the compose box stays put at the bottom. */
.list {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain; /* running off the end must not scroll the page */
  padding-right: 6px; /* keeps rows off the scrollbar once the list is long */
}

.tasks {
  display: flex;
  flex-direction: column;
  gap: 6px;
  list-style: none;
  margin: 0;
  padding: 0;
}

.task {
  align-items: center;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  display: flex;
  gap: 12px;
  padding: 10px 8px 10px 14px;
}

.task__check {
  accent-color: var(--accent);
  cursor: pointer;
  flex-shrink: 0;
  height: 20px;
  margin: 0;
  width: 20px;
}

/* The label toggles the checkbox, so it is the tap target for most of the row.
   Stretching it means the target is the full height of the row rather than the
   height of one line of text, without the label itself setting that height. */
.task__title {
  align-items: center;
  align-self: stretch;
  cursor: pointer;
  display: flex;
  flex: 1;
  overflow-wrap: anywhere;
}

.task__actions {
  display: flex;
  flex-shrink: 0;
  margin: -8px 0;
}

/* A finished task keeps its place in the list and recedes instead of moving,
   so the row you just ticked is still where you left it. */
.task--done {
  background: transparent;
  border-style: dashed;
}

.task--done .task__title {
  color: var(--muted);
  text-decoration: line-through;
}

/* The action buttons reserve their width even when faded out, so hovering a row
   does not squeeze the task title. */
.task__action {
  align-items: center;
  background: none;
  border: none;
  border-radius: 6px;
  color: var(--muted);
  cursor: pointer;
  display: flex;
  flex-shrink: 0;
  height: 40px;
  justify-content: center;
  line-height: 1;
  opacity: 0;
  padding: 0;
  transition: opacity 0.12s ease;
}

.task__edit {
  font-size: 12px;
  font-weight: 600;
  width: 46px;
}

.task__delete {
  font-size: 20px;
  width: 40px;
}

.task:hover .task__action,
.task:focus-within .task__action,
.task__action:focus-visible {
  opacity: 1;
}

.task__edit:hover,
.task__edit:active {
  color: var(--accent);
}

.task__delete:hover,
.task__delete:active {
  color: var(--danger);
}

.task--editing {
  gap: 10px;
}

.task--editing .task__check {
  cursor: default;
  opacity: 0.65;
}

.task__edit-form {
  align-items: center;
  display: flex;
  flex: 1;
  gap: 8px;
  min-width: 0;
}

.task__edit-input {
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 8px;
  color: var(--text);
  flex: 1;
  font: inherit;
  min-width: 0;
  outline: none;
  padding: 7px 9px;
}

.task__edit-input:focus {
  border-color: var(--accent);
}

.task__edit-command {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 6px;
  color: var(--text);
  cursor: pointer;
  flex-shrink: 0;
  font: inherit;
  font-size: 12px;
  font-weight: 600;
  min-height: 34px;
  padding: 0 10px;
}

.task__edit-command:hover,
.task__edit-command:active {
  border-color: var(--muted);
}

.task__edit-save {
  border-color: var(--accent);
  color: var(--accent);
}

/* Touch screens have no hover, so the control has to stay visible. */
@media (hover: none) {
  .task__action {
    opacity: 1;
  }
}

.empty {
  color: var(--muted);
  font-size: 13px;
  padding: 24px 4px;
  text-align: center;
}

/* Buttons */
.btn {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 8px;
  color: var(--text);
  cursor: pointer;
  font-family: inherit;
  font-size: 13px;
  min-height: 36px;
  padding: 6px 14px;
  transition: border-color 0.12s ease, opacity 0.12s ease;
  white-space: nowrap;
}

.btn:hover,
.btn:active {
  border-color: var(--muted);
}

.btn--concealed {
  opacity: 0;
  pointer-events: none;
  visibility: hidden;
}

/* Toast — at the top, because the bottom now belongs to the compose box and,
   once the keyboard is open, is not on screen at all. */
.toast {
  background: var(--text);
  border-radius: 8px;
  color: var(--panel);
  font-size: 13px;
  left: 50%;
  max-width: calc(100% - 32px);
  opacity: 0;
  padding: 8px 16px;
  pointer-events: none;
  position: fixed;
  text-align: center;
  top: calc(12px + env(safe-area-inset-top, 0px));
  transform: translate(-50%, -8px);
  transition: opacity 0.18s ease, transform 0.18s ease;
}

.toast--show {
  opacity: 1;
  transform: translate(-50%, 0);
}

@media (max-width: 600px) {
  .app {
    --gutter: 12px;
  }
}

/* A tap has no cursor to aim with, so the controls get a little more room. */
@media (hover: none) {
  .btn {
    min-height: 40px;
  }

  .task {
    padding: 12px 8px 12px 14px;
  }
}
