/* Component styles for the Dashboard PWA.
 *
 * Phase 2 established these components from the old single-file app + the new tab bar / card /
 * skeleton / segmented / stale-banner pieces.
 * Phase 5 visual pass (styling only, no markup/JS/behaviour change): "Patina" palette (via
 * tokens.css), Space Grotesk on headings + titles (body stays system sans), tighter type scale,
 * restrained elevation on cards / panel bar, and press feedback on interactive elements.
 * The Android haptic on task-complete lives in js/tabs/tasks.js and is untouched. */

/* ---------- per-panel top bar ---------- */
.panelBar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 12px 16px;
  border-bottom: 1px solid var(--border);
  background: var(--bg);
  box-shadow: 0 3px 10px -6px rgba(0, 0, 0, .6);
  z-index: 1;
}
.panelBarTitle {
  font-family: var(--font-display);
  font-size: var(--fs-bar);
  font-weight: 600;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: .07em;
}
.panelBar button {
  background: var(--panel-raised);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 7px 12px;
  font-size: 12px;
  font-weight: 600;
  color: var(--text);
  cursor: pointer;
  font-family: inherit;
  transition: background .12s ease, border-color .12s ease, transform .08s ease;
}
.panelBar button:hover { background: var(--panel); border-color: var(--accent); }
.panelBar button:active { transform: scale(.96); }
.panelBar button:disabled { opacity: 0.5; cursor: default; transform: none; }

/* ---------- list items / cards ---------- */
.listItem, .card {
  display: block;
  padding: 12px 14px;
  margin: 8px 0;
  border-radius: var(--radius);
  background: var(--panel);
  border: 1px solid var(--border);
  box-shadow: var(--shadow-card);
  text-decoration: none;
  color: inherit;
  transition: border-color .12s ease, background .12s ease, box-shadow .12s ease, transform .08s ease;
}
a.listItem:hover, a.card:hover,
.card[role="button"]:hover,
.garageProfileCard:hover, .garageProfileCard:focus-visible,
.card[role="button"]:focus-visible {
  border-color: var(--accent);
  background: var(--panel-raised);
  box-shadow: var(--shadow-raised);
}
a.listItem:active, a.card:active,
.card[role="button"]:active,
.garageProfileCard:active {
  transform: scale(.988);
  box-shadow: var(--shadow-card);
}
.card[role="button"], .garageProfileCard { cursor: pointer; }
.card[role="button"]:focus-visible,
.garageProfileCard:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.card.isTapped { opacity: .6; }

.listItemTitle {
  font-family: var(--font-display);
  font-size: var(--fs-title);
  font-weight: 600;
  margin-bottom: 4px;
  line-height: 1.3;
  letter-spacing: -0.005em;
}
.listItemMeta {
  font-size: var(--fs-meta);
  color: var(--muted);
  line-height: 1.5;
}

/* Warhammer feed cards with an image use a full-width top banner (news-feed style). */
.listItem.hasBanner {
  padding: 0;
  overflow: hidden;
}
.listItemBanner {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 9;
  object-fit: cover;
  background: var(--panel-raised);
}
.listItemBannerBody {
  padding: 12px 14px;
}

/* Warhammer "new since last visit" pill. */
.whNewPill {
  display: inline-block;
  margin-left: 8px;
  padding: 1px 7px;
  border-radius: 999px;
  background: var(--accent);
  color: var(--accent-text);
  font-size: 10.5px;
  font-weight: 700;
  vertical-align: middle;
}
.listItem.isNew { border-color: var(--accent); }

/* ---------- skeleton loader ---------- */
.skeleton {
  margin: 8px 0;
  height: 64px;
  border-radius: var(--radius);
  background: var(--panel);
  border: 1px solid var(--border);
  box-shadow: var(--shadow-card);
  position: relative;
  overflow: hidden;
}
.skeleton::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(90deg, transparent, rgba(240, 233, 221, 0.05), transparent);
  animation: skeletonSweep 1.3s ease-in-out infinite;
}
@keyframes skeletonSweep {
  from { transform: translateX(-100%); }
  to { transform: translateX(100%); }
}
@media (prefers-reduced-motion: reduce) {
  .skeleton::after { animation: none; }
}

/* ---------- segmented control ---------- */
.segmented {
  display: flex;
  gap: 2px;
  background: var(--panel-raised);
  border: 1px solid var(--border);
  border-radius: 9px;
  padding: 2px;
  margin: 4px 2px 14px;
}
.segmented button {
  flex: 1;
  background: none;
  border: none;
  border-radius: 7px;
  padding: 8px;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--muted);
  font-family: inherit;
  cursor: pointer;
  transition: background .12s ease, color .12s ease;
}
.segmented button.active {
  background: var(--accent);
  color: var(--accent-text);
}

/* ---------- stale / info banner ---------- */
.staleBanner {
  margin: 8px 0 4px;
  padding: 8px 12px;
  border-radius: 8px;
  background: var(--panel-raised);
  border: 1px solid var(--border);
  color: var(--muted);
  font-size: 12px;
}

/* ---------- headings ---------- */
.taskGroup { margin-bottom: 20px; }
.taskGroup h3, .notesHeading, .garageDetailSection h3 {
  font-family: var(--font-display);
  font-size: var(--fs-bar);
  text-transform: uppercase;
  letter-spacing: .07em;
  color: var(--muted);
  margin: 16px 2px 6px;
  font-weight: 600;
}
.notesHeading { margin-top: 24px; }
.garageDetailSection h3 { margin: 0 0 6px; }

/* ---------- inline forms ---------- */
.inlineForm {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin: 4px 2px 4px;
}
.inlineForm input[type="text"],
.inlineForm input[type="number"] {
  flex: 1 1 140px;
  min-width: 0;
  background: var(--panel-raised);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 9px 11px;
  font-size: var(--fs-body);
  color: var(--text);
  font-family: inherit;
}
.inlineForm input::placeholder { color: var(--muted); }
.inlineForm input:focus { outline: none; border-color: var(--accent); }
.inlineForm input:disabled { opacity: .6; }
.inlineForm button[type="submit"] {
  flex: 0 0 auto;
  background: var(--accent);
  border: none;
  border-radius: 8px;
  padding: 9px 16px;
  font-size: 12.5px;
  font-weight: 700;
  color: var(--accent-text);
  cursor: pointer;
  font-family: inherit;
  transition: opacity .12s ease, transform .08s ease;
}
.inlineForm button[type="submit"]:hover { opacity: .92; }
.inlineForm button[type="submit"]:active { transform: scale(.97); }
.inlineForm button[type="submit"]:disabled { opacity: .5; cursor: default; transform: none; }

.inlineError {
  color: var(--error-text);
  font-size: 12px;
  margin: 0 2px 6px;
}
.inlineError:empty { display: none; }

.smallBtn {
  background: var(--panel-raised);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 6px 11px;
  font-size: 11.5px;
  font-weight: 600;
  color: var(--text);
  cursor: pointer;
  font-family: inherit;
  white-space: nowrap;
  transition: background .12s ease, border-color .12s ease, transform .08s ease;
}
.smallBtn:hover { background: var(--panel); border-color: var(--accent); }
.smallBtn:active { transform: scale(.96); }
.smallBtn:disabled { opacity: .5; cursor: default; transform: none; }

/* ---------- due-date presets + picker ---------- */
.dueRow {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin: 2px 2px 2px;
}
.duePresetGroup {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}
.duePresetBtn.active {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--accent-text);
}
.duePickerInput {
  background: var(--panel-raised);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 6px 10px;
  font-size: 12.5px;
  color: var(--text);
  font-family: inherit;
  color-scheme: dark;
}
.duePickerInput:focus { outline: none; border-color: var(--accent); }
.duePickerInput:disabled { opacity: .5; }
.dueSummary {
  font-size: 12px;
  color: var(--muted);
  margin: 0 2px 6px;
  min-height: 1em;
}

/* ---------- task rows ---------- */
.taskRow {
  display: flex;
  align-items: flex-start;
  gap: 10px;
}
.taskCheckbox {
  flex: 0 0 auto;
  width: 18px;
  height: 18px;
  margin-top: 2px;
  accent-color: var(--accent);
  cursor: pointer;
}
.taskContent { flex: 1; min-width: 0; }

/* ---------- Todoist project split (2026-09-18) ----------
   Chip on every task row, an optional filter chip row that defaults to All, and a project picker
   in the add form. Deliberately minimal and built from existing tokens — the broader styling pass
   is a separate, deferred job. */
.taskMetaRow {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 6px 8px;
}
.projectChip {
  flex: 0 0 auto;
  padding: 1px 8px;
  border-radius: 999px;
  border: 1px solid var(--border);
  background: var(--panel-raised);
  color: var(--muted);
  font-size: 10.5px;
  font-weight: 700;
  line-height: 1.6;
  white-space: nowrap;
}
/* Personal (Todoist Inbox) reads differently from work at a glance — derived from the API's
   is_inbox flag, never from a project name. */
.projectChip.isInbox {
  color: var(--accent);
  border-color: var(--accent);
  background: transparent;
}

.projectFilterRow {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin: 0 2px 8px;
}
.projectFilterRow[hidden] { display: none; }
.projectFilterBtn.active {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--accent-text);
}
.projectFilterNote {
  font-size: 12px;
  color: var(--muted);
  margin: 0 2px 10px;
}
.projectFilterNote[hidden] { display: none; }

.projectRow {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  margin: 0 2px 8px;
}
.projectRowLabel {
  font-size: var(--fs-meta);
  color: var(--muted);
}
.projectRowLabel[hidden] { display: none; }
.projectSelect {
  background: var(--panel-raised);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 6px 10px;
  font-size: 12.5px;
  color: var(--text);
  font-family: inherit;
  color-scheme: dark;
}
.projectSelect:focus { outline: none; border-color: var(--accent); }
.projectSelect:disabled { opacity: .5; }
.projectSelect[hidden] { display: none; }
.projectRowNote {
  font-size: 12px;
  color: var(--muted);
}
.projectRowNote[hidden] { display: none; }

/* ---------- note rows ---------- */
.noteRow {
  display: flex;
  align-items: flex-start;
  gap: 10px;
}
.noteViewWrap { flex: 1; min-width: 0; }
.noteBtnGroup { flex: 0 0 auto; display: flex; gap: 8px; }
.noteEditBtn { flex: 0 0 auto; }
.noteDeleteBtn {
  flex: 0 0 auto;
  color: var(--error-text);
  border-color: var(--error-border);
}
.noteDeleteBtn:hover { background: var(--error-bg); border-color: var(--error-text); }
.noteEditForm { display: flex; flex-direction: column; gap: 6px; width: 100%; }
.noteEditForm input[type="text"] {
  background: var(--panel-raised);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 8px 10px;
  font-size: 13px;
  color: var(--text);
  font-family: inherit;
}
.noteEditForm input[type="text"]:focus { outline: none; border-color: var(--accent); }
.noteEditBtnRow { display: flex; gap: 8px; }

/* ---------- error bubble ---------- */
.bubble.error {
  max-width: none;
  padding: 12px 14px;
  border-radius: var(--radius);
  background: var(--error-bg);
  border: 1px solid var(--error-border);
  color: var(--error-text);
  font-size: var(--fs-body);
  line-height: 1.4;
}
.bubble.error details {
  margin-top: 8px;
  font-size: 12px;
}
.bubble.error a {
  color: var(--error-text);
  font-weight: 700;
}
.bubble.error.compact {
  font-size: 12.5px;
  padding: 10px 12px;
}

/* ---------- My Garage ---------- */
.garageProfileTitle {
  font-family: var(--font-display);
  font-size: var(--fs-title-lg);
  font-weight: 600;
  margin-bottom: 4px;
  letter-spacing: -0.01em;
}
.garageProfileHint {
  margin-top: 6px;
  color: var(--accent);
}
.garageBackBtn { margin-bottom: 14px; }
.garageDetailContent {
  display: flex;
  flex-direction: column;
  gap: 16px;
}
.garageField {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  padding: 7px 0;
  border-bottom: 1px solid var(--border);
  font-size: var(--fs-body);
  line-height: 1.4;
}
.garageField:last-child { border-bottom: none; }
.garageFieldLabel { color: var(--muted); flex: 0 0 auto; }
.garageFieldValue { text-align: right; flex: 1 1 auto; }
.garageNoteBlock {
  font-size: var(--fs-body);
  line-height: 1.5;
  color: var(--text);
}
.garageMaintWork {
  font-size: var(--fs-body);
  color: var(--text);
  margin-top: 4px;
  line-height: 1.4;
}

/* ---------- Verhuizing (office move tracker) ---------- */

/* Inline-editable text/textarea/select fields shared across the facts/movers/questions/risks
   sections — same visual language as .inlineForm inputs, but usable standalone (a field row, not
   necessarily inside a <form>). */
.moveField {
  display: flex;
  flex-direction: column;
  gap: 4px;
  margin: 0 0 12px;
}
.moveFieldLabel {
  font-size: 11.5px;
  font-weight: 600;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: .06em;
}
.moveField input[type="text"],
.moveField input[type="date"],
.moveField input[type="number"],
.moveField textarea,
.moveInput,
.moveTextarea,
.moveSelect {
  background: var(--panel-raised);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 9px 11px;
  font-size: var(--fs-body);
  color: var(--text);
  font-family: inherit;
  width: 100%;
  color-scheme: dark;
}
.moveField textarea, .moveTextarea {
  resize: vertical;
  min-height: 60px;
  line-height: 1.4;
}
.moveField input:focus, .moveField textarea:focus,
.moveInput:focus, .moveTextarea:focus, .moveSelect:focus {
  outline: none;
  border-color: var(--accent);
}
.moveSelect { flex: 0 0 auto; width: auto; cursor: pointer; }

/* Status pill — small color-coded label. Color is applied via a modifier class chosen from the
   item's own status VALUE (see js/tabs/move.js statusToneClass), not hardcoded per string, so an
   unrecognized future status value just falls back to the neutral tone instead of erroring. */
.statusPill {
  display: inline-flex;
  align-items: center;
  padding: 3px 9px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 700;
  border: 1px solid var(--border);
  color: var(--muted);
  background: var(--panel-raised);
  white-space: nowrap;
}
.statusPill.toneGood { color: var(--ok-text); background: var(--ok-bg); border-color: var(--ok-border); }
.statusPill.toneWarn { color: var(--accent); background: rgba(224, 138, 58, .12); border-color: var(--accent); }
.statusPill.toneBad { color: var(--error-text); background: var(--error-bg); border-color: var(--error-border); }

.moveStatusRow {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  margin-top: 6px;
}

.moveCheckboxRow {
  display: flex;
  align-items: center;
  gap: 7px;
  font-size: 12.5px;
  color: var(--muted);
}
.moveCheckboxRow input[type="checkbox"] {
  width: 16px;
  height: 16px;
  accent-color: var(--accent);
  cursor: pointer;
}

.moveItem { display: flex; flex-direction: column; gap: 6px; }
.moveItemHeadRow {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 10px;
}
.moveItemBody { flex: 1; min-width: 0; }
.moveItemActions { flex: 0 0 auto; display: flex; gap: 8px; }

.moveTaskItem {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 10px 0;
  border-bottom: 1px solid var(--border);
}
.moveTaskItem:last-child { border-bottom: none; }
.moveTaskItem.done .moveTaskText { color: var(--muted); text-decoration: line-through; }
.moveTaskText { flex: 1; min-width: 0; font-size: var(--fs-body); line-height: 1.4; }

/* ---------- Projects / status tab (2026-09-19, restructure plan step 6) ----------
   Reuses .listItem, .statusPill, .staleBanner, .notesHeading, .emptyMsg wholesale — only the
   pieces with no existing equivalent (health dot, "needs you" badge, stale-output line, collapsed
   blockers/decisions) get new classes. */
.statusSummaryLine {
  margin: 2px 2px 10px;
  font-size: 12px;
  color: var(--muted);
}
.statusCardTitleRow {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  margin-bottom: 4px;
}
.statusCardTitle {
  font-family: var(--font-display);
  font-size: var(--fs-title);
  font-weight: 600;
  line-height: 1.3;
  letter-spacing: -0.005em;
}
.healthDot {
  display: inline-block;
  flex: 0 0 auto;
  width: 9px;
  height: 9px;
  border-radius: 50%;
}
.healthDot--green { background: var(--ok-text); }
.healthDot--amber { background: var(--accent); }
.healthDot--red { background: var(--error-text); }
.healthDot--unknown { background: var(--muted); }

/* Same visual weight as .whNewPill (Warhammer "new" pill) — deliberately kept as its own class
   rather than reused directly, since the two badges mean different things even though they look
   the same today. */
.waitingPill {
  display: inline-block;
  padding: 1px 8px;
  border-radius: 999px;
  background: var(--accent);
  color: var(--accent-text);
  font-size: 10.5px;
  font-weight: 700;
  white-space: nowrap;
}

.statusCardMeta { margin-bottom: 6px; }
.statusCardNextAction {
  font-size: var(--fs-body);
  line-height: 1.4;
}
.statusStaleLine {
  margin-top: 6px;
  font-size: 12px;
  color: var(--accent);
  line-height: 1.4;
}
.statusProblemsBox {
  margin-top: 6px;
  font-size: 12px;
  color: var(--error-text);
  line-height: 1.4;
}
.statusProblemsBox div { margin-top: 2px; }

.statusDetails {
  margin-top: 8px;
  font-size: 12px;
}
.statusDetails summary {
  cursor: pointer;
  color: var(--muted);
}
.statusDetails summary:hover { color: var(--text); }
.statusDetailsList {
  margin: 6px 0 0;
  padding-left: 18px;
  color: var(--muted);
  line-height: 1.5;
}
.statusDetailsList li { margin: 3px 0; }

/* "Waiting on you" cards get a left accent bar instead of the full border-color swap other tabs
   use for emphasis, so it reads at a glance even in a long scroll. */
.statusCard--waiting {
  border-left: 3px solid var(--accent);
  padding-left: 11px;
}
/* "All good" cards are deliberately quieter/more compact — see the brief for this tab. */
.statusCard--compact { opacity: .85; }
.statusCard--compact .statusCardTitle { font-size: 13px; }
.statusCard--compact .statusCardNextAction { font-size: 12px; color: var(--muted); }

/* ---------- home hub + page navigation (phase 3, 2026-09-19) ----------
 * The bottom tab bar is gone. Every non-home page gets .pageBackBar (built by js/app.js, outside
 * the page module's container so a module re-render can't wipe it); Home is js/tabs/home.js. */

/* Inside a panel, the module's container. Same flex column the .panel itself used to be, so every
   module's .panelBar + .listArea layout is unchanged. */
.pageBody {
  flex: 1;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  min-height: 0;
  position: relative;
}

.pageBackBar {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  padding: 2px 8px 0;
  background: var(--bg);
}
.pageBackBtn {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  min-height: 44px;
  min-width: 44px;
  padding: 0 14px 0 8px;
  background: none;
  border: none;
  border-radius: 10px;
  color: var(--accent);
  font-family: var(--font-display);
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  transition: background .12s ease, transform .08s ease;
}
.pageBackBtn span { font-size: 26px; line-height: 1; margin-top: -3px; }
.pageBackBtn:hover { background: var(--panel); }
.pageBackBtn:active { transform: scale(.95); }
.pageBackBtn:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

/* A plain full-width link row (Projects page -> Move). */
.listArea--fixed { flex: 0 0 auto; padding-bottom: 0; }
.pageLink {
  display: flex;
  align-items: center;
  justify-content: space-between;
  min-height: 44px;
  padding: 10px 14px;
  margin: 8px 0 0;
  border-radius: var(--radius);
  background: var(--panel);
  border: 1px solid var(--border);
  color: var(--accent);
  font-size: var(--fs-title);
  font-weight: 600;
  text-decoration: none;
  transition: border-color .12s ease, background .12s ease;
}
.pageLink:hover { border-color: var(--accent); background: var(--panel-raised); }
.pageLink:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.homeHeading {
  font-family: var(--font-display);
  font-size: var(--fs-bar);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .07em;
  color: var(--muted);
  margin: 18px 2px 8px;
}
.homeArea > .homeHeading:first-child { margin-top: 10px; }

/* needs-you-now strip */
.needItem {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-height: 48px;
  padding: 9px 14px;
  margin: 6px 0;
  border-radius: var(--radius);
  background: var(--panel);
  border: 1px solid var(--border);
  box-shadow: var(--shadow-card);
  color: inherit;
  text-decoration: none;
  transition: border-color .12s ease, background .12s ease, transform .08s ease;
}
.needItem--you { border-left: 3px solid var(--accent); padding-left: 11px; }
.needItem:hover { border-color: var(--accent); background: var(--panel-raised); }
.needItem:active { transform: scale(.988); }
.needItem:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.needItemMain {
  font-family: var(--font-display);
  font-size: var(--fs-title);
  font-weight: 600;
  line-height: 1.3;
}
.needItemSub {
  font-size: var(--fs-meta);
  color: var(--muted);
  line-height: 1.4;
  overflow: hidden;
  display: -webkit-box;
  -webkit-line-clamp: 1;
  -webkit-box-orient: vertical;
}
.needsClear, .needsNote {
  color: var(--muted);
  font-size: var(--fs-meta);
  padding: 6px 2px;
}

/* tile grid: two big thumb-sized tiles per row */
.homeGrid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 12px;
}
.homeGrid > .emptyMsg { grid-column: 1 / -1; }
.homeTile {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 6px;
  min-height: 124px;
  padding: 14px;
  border-radius: var(--radius);
  background: var(--panel);
  border: 1px solid var(--border);
  box-shadow: var(--shadow-card);
  color: inherit;
  text-decoration: none;
  transition: border-color .12s ease, background .12s ease, box-shadow .12s ease, transform .08s ease;
}
a.homeTile:hover { border-color: var(--accent); background: var(--panel-raised); box-shadow: var(--shadow-raised); }
a.homeTile:active { transform: scale(.975); box-shadow: var(--shadow-card); }
a.homeTile:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.homeTile.isTapped { opacity: .6; }
.homeTileIcon { color: var(--accent); line-height: 0; }
.homeTileIcon svg { width: 28px; height: 28px; }
.homeTileLabel {
  font-family: var(--font-display);
  font-size: var(--fs-title-lg);
  font-weight: 600;
  letter-spacing: -0.005em;
}
.homeTilePreview {
  font-size: var(--fs-meta);
  color: var(--muted);
  line-height: 1.4;
  overflow: hidden;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow-wrap: anywhere;
}
.homeTilePreview.isLoading { opacity: .6; }
.homeTilePreview.isUnavailable { color: var(--error-text); }
.homeTile--edit { border-style: dashed; }
.homeTile--edit.isHiddenTile { opacity: .55; }
.homeTileCtl { display: flex; gap: 6px; margin-top: auto; padding-top: 4px; }
.homeTileCtl .smallBtn { min-height: 36px; min-width: 40px; }
.homeTileCtl .smallBtn:disabled { opacity: .4; cursor: default; }

.homeCaptureNote { color: var(--ok-text); font-size: var(--fs-meta); margin: 12px 2px 0; }
.homeCaptureNote:empty { display: none; }

.homeFoot { margin: 20px 0 4px; text-align: center; font-size: 11px; }
.homeFoot a { color: var(--muted); text-decoration: none; padding: 8px; display: inline-block; }
.homeFoot a:hover { color: var(--text); }
.homeFoot .homeFootVersion { color: var(--muted); opacity: .6; }

/* quick-capture: a bottom bar button + a sheet anchored to the TOP of the screen so the on-screen
   keyboard (which rises from the bottom) can never cover the input. */
.homeCaptureBar {
  flex: 0 0 auto;
  padding: 10px 16px calc(10px + var(--safe-bottom));
  background: var(--panel);
  border-top: 1px solid var(--border);
  box-shadow: var(--shadow-bar);
}
.homeCaptureBtn {
  display: block;
  width: 100%;
  max-width: 720px;
  margin: 0 auto;
  min-height: 48px;
  background: var(--accent);
  color: var(--accent-text);
  border: none;
  border-radius: var(--radius);
  font-family: var(--font-display);
  font-size: 15px;
  font-weight: 600;
  cursor: pointer;
  transition: transform .08s ease, filter .12s ease;
}
.homeCaptureBtn:hover { filter: brightness(1.08); }
.homeCaptureBtn:active { transform: scale(.98); }
.homeCaptureBtn:focus-visible { outline: 2px solid var(--text); outline-offset: 2px; }

/* Quick capture + Open Claude share the bottom bar: capture is the big primary, Claude a quieter
   secondary link beside it (thumb-reachable, not another tile). */
.homeCaptureRow {
  display: flex;
  gap: 10px;
  max-width: 720px;
  margin: 0 auto;
}
.homeCaptureRow .homeCaptureBtn { flex: 1 1 auto; width: auto; max-width: none; margin: 0; min-width: 0; }
.homeClaudeBtn {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 48px;
  padding: 0 18px;
  background: var(--panel-raised);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  font-family: var(--font-display);
  font-size: 15px;
  font-weight: 600;
  text-decoration: none;
  white-space: nowrap;
  transition: transform .08s ease, border-color .12s ease;
}
.homeClaudeBtn:hover { border-color: var(--accent); }
.homeClaudeBtn:active { transform: scale(.98); }
.homeClaudeBtn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.captureSheet {
  position: absolute;
  inset: 0;
  z-index: 10;
  display: flex;
  align-items: flex-start;
  justify-content: center;
}
.captureSheet[hidden] { display: none; }
.captureBackdrop {
  position: absolute;
  inset: 0;
  width: 100%;
  background: rgba(0, 0, 0, .6);
  border: none;
  padding: 0;
  cursor: pointer;
}
.captureCard {
  position: relative;
  width: 100%;
  max-width: 720px;
  padding: 16px 16px 16px;
  background: var(--panel);
  border-bottom: 1px solid var(--border);
  border-radius: 0 0 16px 16px;
  box-shadow: var(--shadow-raised);
}
.captureTitle {
  font-family: var(--font-display);
  font-size: var(--fs-bar);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .07em;
  color: var(--muted);
  margin-bottom: 10px;
}
.captureCard .segmented { margin: 0 0 12px; }
.captureCard .segmented button { min-height: 40px; }
.captureInput {
  display: block;
  width: 100%;
  min-height: 46px;
  background: var(--panel-raised);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 10px 12px;
  font-size: 16px; /* >=16px stops iOS zooming the page on focus */
  color: var(--text);
  font-family: inherit;
}
.captureInput::placeholder { color: var(--muted); }
.captureInput:focus { outline: none; border-color: var(--accent); }
.captureInput:disabled { opacity: .6; }
.captureCard .inlineError { margin: 8px 0 0; }
.captureActions { display: flex; gap: 10px; margin-top: 12px; }
.captureActions button {
  flex: 1;
  min-height: 46px;
  border-radius: 10px;
  font-family: inherit;
  font-size: 14px;
  font-weight: 700;
  cursor: pointer;
}
.captureCancel { background: var(--panel-raised); border: 1px solid var(--border); color: var(--text); }
.captureSave { background: var(--accent); border: none; color: var(--accent-text); }
.captureActions button:disabled { opacity: .6; cursor: default; }
.captureActions button:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* ---------- Voice capture (2026-09-20) ----------
 * Hold the Quick capture button to dictate. The card reuses .captureCard / .captureActions tokens but
 * sits at the BOTTOM (no keyboard is involved, so buttons land under the thumb). While listening the
 * sheet's bottom is raised (inline style) so the held button stays visible below the card. */
.homeCaptureBtn.voiceReady {
  -webkit-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
  touch-action: none;
  -webkit-tap-highlight-color: transparent;
}
.homeCaptureBtn.recording {
  background: var(--error-text);
  color: var(--accent-text);
  animation: voicePulse 1.1s ease-in-out infinite;
}
@keyframes voicePulse { 50% { filter: brightness(1.25); } }
@media (prefers-reduced-motion: reduce) { .homeCaptureBtn.recording { animation: none; } }
.voiceSheet { align-items: flex-end; }
.voiceBackdrop { cursor: default; }
.voiceCard {
  border-bottom: none;
  border-top: 1px solid var(--border);
  border-radius: 16px 16px 0 0;
  padding-bottom: calc(16px + var(--safe-bottom));
}
.voiceSheet[data-state="listening"] .voiceCard { padding-bottom: 16px; }
.voiceText {
  font-size: 22px;
  line-height: 1.35;
  color: var(--text);
  min-height: 3.2em;
  max-height: 40vh;
  overflow-y: auto;
  padding: 12px 14px;
  background: var(--panel-raised);
  border: 1px solid var(--border);
  border-radius: 10px;
  overflow-wrap: anywhere;
  user-select: none;
  -webkit-user-select: none;
}
.voiceText.live { color: var(--muted); }
.voiceMsg { font-size: 17px; line-height: 1.4; color: var(--text); margin: 4px 0 8px; }
.voiceHint { font-size: var(--fs-meta); color: var(--muted); margin-top: 10px; line-height: 1.4; }
.voiceText[hidden], .voiceMsg[hidden], .voiceHint[hidden] { display: none; }
.voiceCard .inlineError:empty { display: none; }
.voiceActions button { min-height: 60px; font-size: 17px; }
.voiceLink {
  display: block;
  width: 100%;
  min-height: 48px;
  margin-top: 8px;
  background: none;
  border: none;
  color: var(--accent);
  font-family: inherit;
  font-size: 15px;
  font-weight: 600;
  cursor: pointer;
}
.voiceLink[hidden] { display: none; }
.voiceLink:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
/* "Type it instead" is the main way out of a failure, so it is the primary button there. */
.voiceSheet[data-state="message"] .voiceLink {
  min-height: 60px;
  margin-top: 10px;
  background: var(--accent);
  color: var(--accent-text);
  border-radius: 10px;
  font-size: 17px;
  font-weight: 700;
}

/* ---------- Space news page (2026-09-19) ----------
 * Reuses .listItem / .listItemBanner / .duePresetGroup. An item is a <div> holding the link and a
 * thumbs row (buttons can't live inside an <a>). */
.spaceFilterArea { padding-bottom: 0; }
.spaceFilterArea .duePresetGroup { gap: 5px; }
.spaceChip { min-height: 40px; padding: 6px 9px; flex: 0 1 auto; }
.spaceItem { padding: 0; overflow: hidden; }
.spaceItemLink {
  display: block;
  color: inherit;
  text-decoration: none;
  transition: opacity .15s ease;
}
.spaceItemLink:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.spaceItem.isDown .spaceItemLink { opacity: .42; }
.spaceMeta { margin-top: 4px; }
.spaceTag {
  display: inline-block;
  margin-right: 8px;
  padding: 0 7px;
  border: 1px solid var(--border);
  border-radius: 999px;
  color: var(--accent);
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: .04em;
  text-transform: uppercase;
  vertical-align: 1px;
}
.spaceVotes {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 8px;
  padding: 0 10px 8px 14px;
}
.spaceVoteMsg { flex: 1 1 auto; margin: 0; align-self: center; }
.spaceVoteBtn {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  padding: 0;
  background: var(--panel-raised);
  color: var(--muted);
  border: 1px solid var(--border);
  border-radius: 10px;
  cursor: pointer;
  transition: background .12s ease, border-color .12s ease, color .12s ease, transform .08s ease;
}
.spaceVoteBtn svg { width: 20px; height: 20px; }
.spaceVoteBtn:hover { border-color: var(--accent); color: var(--text); }
.spaceVoteBtn:active { transform: scale(.94); }
.spaceVoteBtn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.spaceVoteBtn--up.active { background: var(--accent); border-color: var(--accent); color: var(--accent-text); }
.spaceVoteBtn--down.active { background: var(--error-bg); border-color: var(--error-border); color: var(--error-text); }
.spaceItem[aria-busy="true"] .spaceVoteBtn { opacity: .7; }

/* ---------- Visitor proposals on the public move page (2026-09-21) ----------
   Review screen inside the Verhuizing page (js/tabs/move-review.js), the count badge on the Projects ->
   Move link, and the banner that opens the review. Big thumb-sized buttons (>= 52px tall). Tokens only. */
.countBadge {
  display: inline-block;
  min-width: 20px;
  margin-left: 8px;
  padding: 1px 7px;
  border-radius: 999px;
  background: var(--accent);
  color: var(--accent-text);
  font-size: 11.5px;
  font-weight: 700;
  text-align: center;
  vertical-align: middle;
}
.countBadge[hidden] { display: none; }

.reviewBanner {
  display: block;
  width: 100%;
  min-height: 52px;
  margin: 4px 0 12px;
  padding: 12px 14px;
  border-radius: var(--radius);
  border: 1px solid var(--accent);
  border-left-width: 4px;
  background: var(--panel-raised);
  color: var(--text);
  font-family: var(--font-display);
  font-size: var(--fs-title);
  font-weight: 600;
  text-align: left;
  cursor: pointer;
}
.reviewBanner[hidden] { display: none; }
.reviewBanner:active { transform: scale(.988); }
.reviewBanner:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.reviewHead { display: flex; align-items: center; gap: 12px; margin: 4px 0 10px; }
.reviewHead .smallBtn { min-height: 40px; }
.reviewTitle { font-family: var(--font-display); font-size: var(--fs-title-lg); font-weight: 600; }
.reviewIntro { color: var(--muted); font-size: var(--fs-meta); line-height: 1.45; margin: 0 2px 12px; }
.reviewNotice {
  margin: 0 0 10px;
  padding: 9px 12px;
  border-radius: 8px;
  background: var(--ok-bg);
  border: 1px solid var(--ok-border);
  color: var(--ok-text);
  font-size: var(--fs-body);
}
.reviewNotice[hidden] { display: none; }

.reviewCard {
  margin: 0 0 14px;
  padding: 14px;
  border-radius: var(--radius);
  background: var(--panel);
  border: 1px solid var(--border);
  border-left: 4px solid var(--accent);
  box-shadow: var(--shadow-card);
}
.reviewCard.isBusy { opacity: .6; }
.reviewWho { font-family: var(--font-display); font-size: var(--fs-title-lg); line-height: 1.3; overflow-wrap: anywhere; }
.reviewKind { color: var(--muted); font-size: var(--fs-body); margin: 2px 0 10px; }
.reviewLabel {
  font-size: 11px;
  font-weight: 600;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: .06em;
  margin-bottom: 3px;
}
.reviewTarget, .reviewProposal { margin: 0 0 10px; }
.reviewTargetText, .reviewProposalText {
  padding: 8px 10px;
  border-radius: 8px;
  background: var(--panel-raised);
  border: 1px solid var(--border);
  font-size: var(--fs-body);
  line-height: 1.45;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}
.reviewTargetText { color: var(--muted); }
.reviewEdit {
  display: block;
  width: 100%;
  min-height: 96px;
  padding: 9px 11px;
  border-radius: 8px;
  border: 1px solid var(--accent);
  background: var(--panel-raised);
  color: var(--text);
  font-family: inherit;
  font-size: 16px; /* >=16px stops iOS zooming the page on focus */
  line-height: 1.4;
  resize: vertical;
}
.reviewMsg { margin: 6px 0 0; font-size: var(--fs-body); }

.reviewActions { display: flex; flex-direction: column; gap: 8px; margin-top: 10px; }
.bigBtn {
  display: block;
  width: 100%;
  min-height: 52px;
  padding: 12px 16px;
  border-radius: 10px;
  border: 1px solid var(--border);
  background: var(--panel-raised);
  color: var(--text);
  font-family: inherit;
  font-size: 15px;
  font-weight: 700;
  cursor: pointer;
  transition: opacity .12s ease, transform .08s ease;
}
.bigBtn:active { transform: scale(.98); }
.bigBtn:disabled { opacity: .5; cursor: default; transform: none; }
.bigBtn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.bigBtn--approve { background: var(--accent); border-color: var(--accent); color: var(--accent-text); }
.bigBtn--deny { background: var(--error-bg); border-color: var(--error-border); color: var(--error-text); }

.reviewFoot { margin-top: 6px; }
.reviewDenyAll { display: flex; flex-direction: column; gap: 8px; }
.reviewConfirmText { color: var(--text); font-size: var(--fs-body); line-height: 1.4; }

/* ---- Settings page + in-app approval bar (push notifications) ---- */
.settingsWrap { padding: 16px; }
.settingsH { font-family: var(--font-display); font-size: 18px; margin: 4px 0 8px; }
.settingsHint, .settingsStatus, .settingsMsg { color: var(--muted); font-size: var(--fs-body); line-height: 1.4; margin: 8px 0; }
.settingsBtn { display: block; width: 100%; margin: 10px 0; padding: 14px; border: 0; border-radius: 12px; background: var(--accent); color: var(--accent-text); font-size: 16px; font-weight: 600; }
.settingsBtnAlt { background: var(--panel-raised); color: var(--text); border: 1px solid var(--border); }
.settingsBtn:disabled { opacity: .6; }
.approvalBar { position: fixed; left: 0; right: 0; top: 0; z-index: 9000; padding: calc(env(safe-area-inset-top, 0px) + 8px) 8px 8px; background: var(--bg); border-bottom: 2px solid var(--accent); max-height: 60vh; overflow: auto; }
.approvalRow { background: var(--panel-raised); border: 1px solid var(--border); border-radius: 12px; padding: 12px; margin-bottom: 8px; }
.approvalTitle { font-weight: 700; font-size: var(--fs-title-lg); }
.approvalBody { color: var(--muted); font-size: var(--fs-body); margin: 4px 0 10px; word-break: break-word; }
.approvalBtns { display: flex; gap: 10px; }
.approvalBtns button { flex: 1; padding: 14px; border-radius: 10px; border: 1px solid var(--border); font-size: 16px; font-weight: 600; }
.approvalApprove { background: var(--ok-bg); color: var(--ok-text); border-color: var(--ok-border) !important; }
.approvalDeny { background: var(--error-bg); color: var(--error-text); border-color: var(--error-border) !important; }
.approvalBtns button:disabled { opacity: .5; }
.approvalMsg { color: var(--muted); font-size: var(--fs-meta); margin-top: 6px; }
