/* ---------------------------------------------------------------
   Suitable Todo — shared theme
   Design tokens for light + dark, layered on Bootstrap 5.3's
   native `data-bs-theme` support.
   --------------------------------------------------------------- */

:root {
  --brand: #5b5ef4;
  --brand-hover: #4547d0;
  --brand-contrast: #fff;
  --brand-ring: rgba(91, 94, 244, 0.15);
  --brand-glow: rgba(91, 94, 244, 0.12);
  --brand-soft-bg: #ededfd;
  --brand-soft-bg-strong: #c7c8f8;

  /* The raised surfaces are pure white, so the page has to carry the whole
     contrast step. At #f4f6fb it was 3% off white and cards vanished into
     it; this is deep enough to read as a backdrop without going grey. */
  --app-bg: #e8ecf5;
  --surface: #fff;
  --surface-hover: #eef0f4;

  --border-strong: #9ca3af;
  --border-soft: #d1d5db;
  --border-faint: #e5e7eb;

  --text-strong: #111827;
  --text-body: #374151;
  --text-muted: #6b7280;
  --text-faint: #9ca3af;
  --text-danger: #dc2626;

  /* The soft fills were 100-level tints: amber-100 came out at 1.11:1 against
     a white card, so the badge shape vanished and only the text read. Low and
     Medium sit two steps deeper; High and Urgent are solid, so the two levels
     worth noticing carry the most weight. Every label clears 4.5:1 on its own
     fill, which is what caps how far each one can go. Urgent takes the same
     red as --text-danger, so it matches the overdue date sitting beside it. */
  --prio-1-bg: #d1d5db; --prio-1-fg: #1f2937;
  --prio-2-bg: #fbbf24; --prio-2-fg: #78350f;
  --prio-3-bg: #7c3aed; --prio-3-fg: #fff;
  --prio-4-bg: #dc2626; --prio-4-fg: #fff;

  --auth-shadow: 0 8px 32px rgba(91, 94, 244, 0.08);
  --elevation: 0 1px 2px rgba(17, 24, 39, 0.06), 0 4px 12px rgba(17, 24, 39, 0.07);
}

[data-bs-theme="dark"] {
  /* Lift the brand hue so it stays legible on dark surfaces. */
  --brand: #8385f8;
  --brand-hover: #9b9dfa;
  --brand-contrast: #14161b;
  --brand-ring: rgba(131, 133, 248, 0.25);
  --brand-glow: rgba(131, 133, 248, 0.18);
  --brand-soft-bg: #262a3d;
  --brand-soft-bg-strong: #343a56;

  --app-bg: #14161b;
  --surface: #1c1f27;
  --surface-hover: #262a33;

  --border-strong: #454b59;
  --border-soft: #343a45;
  --border-faint: #2a2f38;

  --text-strong: #f3f4f6;
  --text-body: #d1d5db;
  --text-muted: #9aa3b2;
  --text-faint: #6b7280;
  --text-danger: #f87171;

  --prio-1-bg: #343a45; --prio-1-fg: #d1d5db;
  --prio-2-bg: #4a3a12; --prio-2-fg: #fcd34d;
  --prio-3-bg: #6d28d9; --prio-3-fg: #fff;
  --prio-4-bg: #6b2727; --prio-4-fg: #fca5a5;  /* was #4c1d1d, only 1.18:1 on the card */

  --auth-shadow: 0 8px 32px rgba(0, 0, 0, 0.45);
  --elevation: 0 1px 2px rgba(0, 0, 0, 0.3), 0 4px 12px rgba(0, 0, 0, 0.25);

  /* Align Bootstrap's own surfaces with the app palette. */
  --bs-body-bg: var(--app-bg);
  --bs-body-color: var(--text-body);
  --bs-emphasis-color: var(--text-strong);
  --bs-secondary-color: var(--text-muted);
  --bs-border-color: var(--border-soft);
}

/* Bootstrap components that should sit on the raised surface, not the page. */
.card { --bs-card-bg: var(--surface); }
.modal-content { --bs-modal-bg: var(--surface); }
.dropdown-menu { --bs-dropdown-bg: var(--surface); }

/* Every card in the templates is `card border-0 shadow-sm`. Bootstrap's
   `.border-0` is `border:0!important`, and its `shadow-sm` is a 4px blur at
   7.5% black — so a white card on a light page had no edge at all. Restore
   the same outline `.todo-card` uses, which needs `!important` and the extra
   `.border-0` specificity to beat the utility class. */
.card.border-0 { border: 1px solid var(--border-strong) !important; }
.card.shadow-sm { box-shadow: var(--elevation) !important; }

body {
  background: var(--app-bg);
  min-height: 100vh;
}

/* --- App chrome ------------------------------------------------ */

.app-navbar {
  background: var(--surface);
  border-bottom: 1px solid var(--border-faint);
}

.navbar-brand {
  font-weight: 700;
  letter-spacing: -0.5px;
  color: var(--brand) !important;
}

.sidebar {
  min-height: calc(100vh - 56px);
  border-right: 1px solid var(--border-faint);
  background: var(--surface);
}
/* Shared by the desktop sidebar and the navbar's collapsible mobile menu. */
.app-nav .nav-link {
  color: var(--text-body);
  border-radius: 8px;
  padding: 8px 12px;
  margin-bottom: 2px;
}
.app-nav .nav-link:hover {
  background: var(--brand-soft-bg);
  color: var(--brand);
}
/* The current page needs to read as selected at a glance, not just as
   "hovered a moment ago", so it gets a deeper fill than hover, plus weight
   so the cue does not rest on background contrast alone. */
.app-nav .nav-link.active {
  background: var(--brand-soft-bg-strong);
  color: var(--brand);
  font-weight: 600;
}
.app-nav .nav-link i { width: 20px; }
/* Roomier hit areas in the mobile menu, where there is no pointer to aim with. */
.navbar .app-nav .nav-link { padding: 11px 12px; }

/* --- Theme toggle ---------------------------------------------- */

.theme-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  padding: 0;
  border: 1px solid var(--border-strong);
  border-radius: 8px;
  background: transparent;
  color: var(--text-body);
  cursor: pointer;
  transition: background-color 0.15s, color 0.15s, border-color 0.15s;
}
.theme-toggle:hover {
  background: var(--surface-hover);
  color: var(--brand);
  border-color: var(--brand);
}
.theme-toggle .bi { font-size: 0.95rem; line-height: 1; }
/* Show the icon for the theme a click would switch *to*. */
.theme-toggle .icon-dark { display: none; }
[data-bs-theme="dark"] .theme-toggle .icon-dark { display: inline-block; }
[data-bs-theme="dark"] .theme-toggle .icon-light { display: none; }

.theme-toggle-floating {
  position: fixed;
  top: 1rem;
  right: 1rem;
  z-index: 10;
}

/* --- Install button -------------------------------------------- */

/* The auth pages have no navbar to hang it off, so it sits beside the
   floating toggle — far enough left to clear the toggle's 32px box. */
.install-app-floating {
  position: fixed;
  top: 1rem;
  right: 3.5rem;
  z-index: 10;
}

/* --- Layout helpers -------------------------------------------- */

/* The filter chips start after the "Filter:" label; the view-options row
   below them is indented to match, so both columns line up on "All".
   Both derive from one width, so they cannot drift apart. */
:root { --filter-label-w: 2.5rem; }
.filter-label {
  display: inline-block;
  width: var(--filter-label-w);
}
/* label width + its me-1 + the row's gap-2 */
.filter-indent { padding-left: calc(var(--filter-label-w) + 0.25rem + 0.5rem); }

/* Lets a flex child shrink below its content width so `.text-truncate`
   and normal wrapping can take effect. Bootstrap ships no equivalent. */
.min-w-0 { min-width: 0; }

/* --- Todo cards ------------------------------------------------ */

.todo-card {
  background: var(--surface);
  border: 1px solid var(--border-strong);
  border-radius: 12px;
  transition: box-shadow 0.15s, border-color 0.15s;
  /* Long prose in notes and meta wraps at word boundaries.
     `.text-truncate` sets white-space:nowrap, which opts its own
     elements out of this. */
  overflow-wrap: break-word;
}
.todo-card:hover {
  box-shadow: 0 4px 16px var(--brand-glow);
  border-color: var(--brand);
}
/* A pinned card is out of the sort order everything else obeys, so it needs
   to say why it is sitting at the top. The brand edge is the whole marker:
   a tinted fill would fight the priority badge for the same glance. */
.todo-card.pinned { border-left: 3px solid var(--brand); }
/* Closes the pinned section off from the rest. `:has` finds the last pinned
   card by what follows it rather than by counting, so the gap lands in the
   right place however the two groups happen to fall across the chunks
   "Show more" appends — and stays away when the section runs to the foot of
   what has been loaded, where there is nothing yet to be separated from. */
.todo-card.pinned:has(+ .todo-card:not(.pinned)) { margin-bottom: 1rem; }
.todo-card.completed { opacity: 0.55; }
/* The project card's "Complete" badge sits inside .project-name but is an
   inline-block, so the strikethrough stops at it rather than crossing it out. */
.todo-card.completed .todo-title,
.todo-card.completed .project-name {
  text-decoration: line-through;
  color: var(--text-faint);
}
/* De-emphasis marks completed todos out as the background against active
   ones. On the Completed page every card is done, so there is nothing to
   contrast against and the whole list just reads as washed out. The
   strikethrough stays on as the "done" marker. */
.all-completed .todo-card.completed { opacity: 1; }
.all-completed .todo-card.completed .todo-title { color: inherit; }

/* Titles can be a single unbroken token (a URL, a slug). `break-word` alone
   keeps min-content at the full token width, so the title would render on
   top of the row actions; `anywhere` shrinks min-content so it wraps inside
   its own column instead. Scoped to titles to keep short meta labels like
   "Q3 Planning" from breaking mid-word. */
.todo-title,
.project-name { overflow-wrap: anywhere; }

.priority-badge-1 { background: var(--prio-1-bg); color: var(--prio-1-fg); }
.priority-badge-2 { background: var(--prio-2-bg); color: var(--prio-2-fg); }
.priority-badge-3 { background: var(--prio-3-bg); color: var(--prio-3-fg); }
.priority-badge-4 { background: var(--prio-4-bg); color: var(--prio-4-fg); }

.tag-chip {
  display: inline-block;
  padding: 1px 8px;
  border-radius: 20px;
  font-size: 0.72rem;
  font-weight: 500;
  color: #fff;
  line-height: 1.6;
}

.overdue { color: var(--text-danger); }

.toggle-btn {
  width: 26px;
  height: 26px;
  border-radius: 6px;
  border: 2px solid var(--text-muted);
  background: var(--surface);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}
.toggle-btn.done {
  background: var(--brand);
  border-color: var(--brand);
  color: var(--brand-contrast);
}

.empty-state {
  text-align: center;
  padding: 80px 0;
  color: var(--text-faint);
}
.empty-state i { font-size: 3rem; display: block; margin-bottom: 1rem; }

/* --- Buttons & form controls ----------------------------------- */

.btn-brand {
  background: var(--brand);
  color: var(--brand-contrast);
  border: none;
}
.btn-brand:hover {
  background: var(--brand-hover);
  color: var(--brand-contrast);
}

.form-control, .form-select { border-color: var(--border-strong); }
.form-control:focus, .form-select:focus {
  border-color: var(--brand);
  box-shadow: 0 0 0 3px var(--brand-ring);
}

.btn-outline-secondary {
  border-color: var(--border-strong);
  color: var(--text-body);
}
.btn-outline-secondary:hover {
  background: var(--surface-hover);
  border-color: var(--text-muted);
  color: var(--text-strong);
}

.btn-outline-danger { border-color: var(--border-strong); }
.btn-outline-danger:hover { border-color: var(--text-danger); }

/* --- Touch targets --------------------------------------------- */

/* On touch devices the icon-only controls are the mis-tap risk: they are
   small squares, and Edit sits beside a destructive Delete. Grow them to a
   ~44px target and widen the gap. Pointer-driven screens keep the compact
   sizing, so the desktop layout is unaffected. */
@media (pointer: coarse), (max-width: 767.98px) {
  /* Keep the 26px box, but extend the tappable area around it. */
  .toggle-btn { position: relative; }
  .toggle-btn::after {
    content: "";
    position: absolute;
    inset: -9px;
    border-radius: 12px;
  }

  /* Row actions (edit / delete) and other icon-only buttons. */
  .todo-card .btn-sm,
  .empty-state .btn-sm {
    min-width: 44px;
    min-height: 44px;
  }
  /* Pull the destructive action away from Edit: gap-1 (4px) -> 8px. */
  .todo-card .gap-1 { gap: 0.5rem !important; }

  .theme-toggle { width: 44px; height: 44px; }
  .theme-toggle .bi { font-size: 1.1rem; }

  .navbar-toggler { min-width: 44px; min-height: 44px; }

  /* Filter chips and page-header buttons. */
  .btn-sm { min-height: 38px; min-width: 44px; }
}

/* --- Auth pages (login, register, password reset) --------------- */

.auth-body {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 100vh;
}
.auth-card {
  background: var(--surface);
  border-radius: 16px;
  border: 1px solid var(--border-strong);
  padding: 2.5rem 2rem;
  width: 100%;
  max-width: 420px;
  box-shadow: var(--auth-shadow);
}
.brand {
  font-size: 1.5rem;
  font-weight: 700;
  color: var(--brand);
  letter-spacing: -0.5px;
}
.field-error { color: var(--text-danger); font-size: 0.8rem; margin-top: 0.25rem; }
.form-text { color: var(--text-muted); font-size: 0.8rem; }

.auth-card .nav-tabs {
  border-bottom: 2px solid var(--border-faint);
  margin-bottom: 1.5rem;
}
.auth-card .nav-tabs .nav-link {
  border: none;
  border-bottom: 2px solid transparent;
  margin-bottom: -2px;
  color: var(--text-muted);
  padding: 0.5rem 1rem;
  font-weight: 500;
}
.auth-card .nav-tabs .nav-link.active {
  color: var(--brand);
  border-bottom-color: var(--brand);
  background: none;
}
