/* ---------------------------------------------------------------- tokens */
/* Adsurf's palette, taken from adsurf.net rather than guessed at:
 *   #42a8ce  ocean cyan .... the signature colour, on the logo and every link underline
 *   #30434c  deep slate ..... the header and footer bands
 *   #354f56  slate teal ..... the dark content sections
 *   #d5e6e9  pale ice ....... the light section wash
 *   #7e9099  muted slate .... secondary text
 *   #c3ac91  sand ........... the warm secondary accent
 *
 * --accent is a deeper ocean than the logo's cyan on purpose: buttons put white text on
 * it, and #42a8ce only reaches 2.6:1 against white, well under the 4.5:1 needed to be
 * readable. The logo cyan lives on as --brand, used where nothing sits on top of it -
 * chart bars, the wordmark, the dots - so the identity is kept without costing legibility.
 */
:root {
  --bg:        #f4f8f9;
  --panel:     #ffffff;
  --panel-2:   #eef5f7;
  --border:    #dbe7eb;
  --border-2:  #c2d6dd;
  --text:      #22343b;
  --muted:     #5b737d;   /* 4.5:1 on the tinted panel too */
  --faint:     #8198a0;   /* 3:1, the floor for non-essential text */
  --accent:    #1b7f9f;   /* 4.6:1 on white */
  --accent-2:  #e4f1f6;
  --brand:     #42a8ce;   /* the logo cyan, decoration only */
  --sand:      #c3ac91;
  --danger:    #c2453c;
  --warn:      #9d6c31;
  --ok:        #17806a;
  --shadow:    0 1px 2px rgba(34,52,59,.07), 0 10px 28px rgba(34,52,59,.08);
  --radius:    10px;
  --sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
}
/* The dark theme is built from the site's own dark bands (#30434c, #354f56) rather than
   a neutral grey, so it reads as the same brand with the lights off. */
@media (prefers-color-scheme: dark) {
  :root {
    --bg:      #14222a;
    --panel:   #1c2e37;
    --panel-2: #243a45;
    --border:  #2d4650;
    --border-2:#3d5b67;
    --text:    #e3eef2;
    --muted:   #9cb4bd;
    --faint:   #6f8b96;
    --accent:  #4fb3d9;
    --accent-2:#173948;
    --brand:   #63c0e2;
    --sand:    #d3bda2;
    --danger:  #ff7b70;
    --warn:    #d9b184;
    --ok:      #3fcfa6;
    --shadow:  0 1px 2px rgba(0,0,0,.45), 0 10px 28px rgba(0,0,0,.38);
  }
}

* { box-sizing: border-box; }
html, body { height: 100%; }
body {
  margin: 0;
  font-family: var(--sans);
  font-size: 14px;
  color: var(--text);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
}
.hidden { display: none !important; }

/* A completed task is frozen. The bar says so and carries the only way back. */
.lock-bar {
  display: flex; align-items: center; gap: 10px;
  margin: 0 0 12px; padding: 9px 11px; border-radius: 9px;
  background: var(--ok-2, var(--panel-2)); border: 1px solid var(--border);
}
.lock-note { flex: 1; font-size: 12px; color: var(--muted); }
.lock-reopen { flex: none; padding: 5px 12px; font-size: 12px; }
.locked { opacity: .55; }

/* One quiet line, not a banner: it is a reminder, not an error. */
.nudge {
  display: flex; align-items: center; gap: 10px;
  margin: 0 0 14px; padding: 9px 12px; border-radius: 9px;
  background: var(--panel-2); border: 1px solid var(--border);
}
.nudge-icon { flex: none; color: var(--accent); }
.nudge-text { flex: 1; font-size: 12px; color: var(--muted); }
.nudge-action {
  flex: none; cursor: pointer; padding: 5px 11px; font-size: 12px; font-weight: 600;
  border: 1px solid var(--accent); border-radius: 7px;
  background: transparent; color: var(--accent);
}
.nudge-action:hover { background: var(--accent-2); }

/* Subscribing is meant to be one tap. The buttons come first and the raw link sits
   underneath for Outlook and for anyone who would rather paste it themselves. */
.cal-row { display: flex; flex-wrap: wrap; gap: 8px; margin: 8px 0 6px; }
.cal-btn {
  display: inline-block; cursor: pointer; text-decoration: none;
  padding: 7px 13px; font-size: 12.5px; font-weight: 600;
  border: 1px solid var(--border-2); border-radius: 8px;
  background: var(--panel); color: var(--text);
}
.cal-btn:hover { background: var(--panel-2); border-color: var(--faint); }
.cal-btn.primary {
  background: var(--accent); border-color: var(--accent); color: #fff;
}
.cal-btn.primary:hover { filter: brightness(1.07); }

/* The subscribe link: shown as a field rather than text so it can be selected and
   copied on a phone, where selecting a paragraph is close to impossible. */
.tg-code input[type=text] {
  margin: 6px 0 4px;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 11px;
}
/* The circle stops inviting a click once there is nothing it will do. */
.status-btn.locked { cursor: default; }
button, input, select, textarea { font: inherit; color: inherit; }

/* --------------------------------------------------------------- buttons */
.btn {
  border: 1px solid var(--border-2);
  background: var(--panel);
  border-radius: 8px;
  padding: 7px 13px;
  cursor: pointer;
  font-weight: 500;
  transition: background .12s, border-color .12s, transform .05s;
}
.btn:hover { background: var(--panel-2); }
.btn:active { transform: translateY(1px); }
.btn.primary { background: var(--accent); border-color: var(--accent); color: #fff; }
.btn.primary:hover { filter: brightness(1.07); }
.btn.ghost { background: transparent; border-color: transparent; color: var(--muted); }
.btn.ghost:hover { background: var(--panel-2); color: var(--text); }
.btn.danger { color: var(--danger); border-color: var(--border-2); background: transparent; }
.btn.danger:hover { background: rgba(217,69,60,.1); }
.btn.block { width: 100%; justify-content: center; }
.btn:disabled { opacity: .55; cursor: not-allowed; }

.icon-btn {
  border: none; background: transparent; color: var(--muted);
  width: 24px; height: 24px; border-radius: 6px; cursor: pointer;
  font-size: 16px; line-height: 1; display: inline-flex;
  align-items: center; justify-content: center;
}
.icon-btn:hover { background: var(--border); color: var(--text); }
.link-btn {
  background: none; border: none; color: var(--muted);
  cursor: pointer; padding: 0; font-size: 12px; text-decoration: underline;
}
.link-btn:hover { color: var(--text); }

input[type=text], input[type=email], input[type=password], input[type=search],
input[type=date], select, textarea {
  width: 100%;
  padding: 8px 10px;
  border: 1px solid var(--border-2);
  border-radius: 8px;
  background: var(--panel);
  outline: none;
}
input:focus, select:focus, textarea:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-2);
}
textarea { resize: vertical; min-height: 80px; }

.tabs { display: inline-flex; background: var(--panel-2); border: 1px solid var(--border); border-radius: 9px; padding: 2px; }
.tab {
  border: none; background: transparent; padding: 6px 14px;
  border-radius: 7px; cursor: pointer; color: var(--muted); font-weight: 500;
}
.tab.active { background: var(--panel); color: var(--text); box-shadow: var(--shadow); }

/* ------------------------------------------------------------------ auth */
.auth { min-height: 100%; display: grid; place-items: center; padding: 24px; }
.auth-card {
  width: 100%; max-width: 390px; background: var(--panel);
  border: 1px solid var(--border); border-radius: 14px;
  padding: 30px 28px; box-shadow: var(--shadow);
}
.auth-card { position: relative; overflow: hidden; }
.auth-card::before {
  content: "";
  position: absolute; top: 0; left: 0; right: 0; height: 3px;
  background: linear-gradient(90deg, var(--accent), var(--brand));
}
.auth-logo {
  margin: 0;
  text-align: center;
  font-size: 17px;
  letter-spacing: .01em;
  font-weight: 600;
  color: var(--text);
}
.auth-sub { margin: 6px 0 20px; color: var(--muted); font-size: 13px; text-align: center; }
.auth-tabs { width: 100%; margin-bottom: 18px; }
.auth-tabs .tab { flex: 1; }
.auth-form label { display: block; margin-bottom: 14px; font-size: 13px; color: var(--muted); }
.auth-form input { margin-top: 5px; }
.hint { display: block; margin-top: 4px; font-size: 11px; color: var(--faint); }
.error {
  margin: 14px 0 0; padding: 9px 11px; border-radius: 8px;
  background: rgba(217,69,60,.1); color: var(--danger); font-size: 13px;
}

/* ------------------------------------------------------------------ shell */
.app { display: grid; grid-template-columns: 250px 1fr; height: 100vh; overflow: hidden; }

.sidebar {
  background: var(--panel);
  border-right: 1px solid var(--border);
  padding: 18px 14px;
  display: flex; flex-direction: column; gap: 20px;
  overflow-y: auto;
}
.brand { padding: 2px 6px 0; display: flex; flex-direction: column; gap: 3px; }
.brand-logo { display: block; width: 132px; height: auto; }
/* The app's own name, quietly, under the company's: the logo says who, this says what. */
.brand-sub {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--muted);
  padding-left: 2px;
}

/* Centred with auto margins rather than a text-align on the card: the sign in forms
   below have left-aligned labels, and centring the whole card would drag those with
   it. `display` is left alone so the light/dark pair keeps hiding correctly. */
.auth-logo-img { display: block; width: 176px; height: auto; margin: 0 auto 10px; }

/* Only one of the two logo files is ever shown. */
.dark-only { display: none; }
@media (prefers-color-scheme: dark) {
  .light-only { display: none; }
  .dark-only { display: block; }
}

.module-switch { display: flex; flex-direction: column; gap: 6px; }
.module-btn {
  text-align: left; border: 1px solid transparent; background: transparent;
  border-radius: 9px; padding: 9px 11px; cursor: pointer; display: block;
}
.module-btn:hover { background: var(--panel-2); }
.module-btn.active { background: var(--accent-2); border-color: color-mix(in srgb, var(--accent) 30%, transparent); }
.module-name { display: block; font-weight: 600; }
.module-note { display: block; font-size: 11px; color: var(--muted); margin-top: 1px; }
.module-btn.active .module-name { color: var(--accent); }

.side-section { display: flex; flex-direction: column; gap: 7px; }
.side-head {
  display: flex; align-items: center; justify-content: space-between;
  font-size: 11px; text-transform: uppercase; letter-spacing: .07em;
  color: var(--faint); padding: 0 6px; font-weight: 600;
}
.category-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 2px; }
.cat-row {
  display: flex; align-items: center; gap: 8px;
  padding: 6px 8px; border-radius: 7px; cursor: pointer;
}
.cat-row:hover { background: var(--panel-2); }
.cat-row.active { background: var(--accent-2); }
.cat-row.drop-target { outline: 2px dashed var(--accent); outline-offset: -2px; }
.dot { width: 9px; height: 9px; border-radius: 50%; flex: none; }
.cat-name { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cat-count { color: var(--faint); font-size: 12px; font-variant-numeric: tabular-nums; }
/* Only fade the edit affordance away where a pointer can actually hover;
   touch/coarse pointers keep it permanently visible. */
@media (hover: hover) and (pointer: fine) {
  .cat-row .icon-btn { opacity: 0; transition: opacity .12s; }
  .cat-row:hover .icon-btn { opacity: 1; }
}
/* Outside the media query on purpose: focus must never land on an invisible
   control on hover-capable machines either (WCAG 2.4.7). */
.cat-row .icon-btn:focus-visible { opacity: 1; }

.side-foot { margin-top: auto; display: flex; align-items: center; justify-content: space-between; gap: 8px; padding-top: 8px; border-top: 1px solid var(--border); }
.user-chip { display: flex; align-items: center; gap: 8px; background: none; border: none; cursor: pointer; padding: 4px; border-radius: 8px; overflow: hidden; }
.user-chip:hover { background: var(--panel-2); }
.avatar {
  width: 26px; height: 26px; border-radius: 50%; flex: none;
  background: var(--accent); color: #fff; font-size: 11px; font-weight: 600;
  display: grid; place-items: center;
}
.user-name { font-size: 13px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ------------------------------------------------------------------ main */
.main { display: flex; flex-direction: column; overflow: hidden; }
.topbar {
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  padding: 14px 22px; border-bottom: 1px solid var(--border); background: var(--panel);
}
.topbar-left { display: flex; align-items: baseline; gap: 10px; }
.topbar-left h2 { margin: 0; font-size: 18px; letter-spacing: -.02em; }
.counter { color: var(--faint); font-size: 13px; }
.topbar-right { display: flex; align-items: center; gap: 10px; }
.topbar-right input[type=search] { width: 200px; }

.quick-add {
  /* align-items: end so the buttons sit on the controls' baseline rather than being
     pushed down by the labels above the fields. */
  display: flex; flex-wrap: wrap; align-items: end; gap: 8px; padding: 12px 22px;
  border-bottom: 1px solid var(--border); background: var(--panel-2);
}
.qa-field { display: flex; flex-direction: column; gap: 3px; flex: 0 1 138px; min-width: 104px; }
/* The title asks for little and takes whatever is left over, so the extra button in the
   actions does not push the whole bar onto a second line. Flexbox decides where to wrap
   from the requested widths, not the shrunk ones, so this number has to be modest even
   though the field always ends up the widest thing on the row. */
.qa-field.qa-title { flex: 1 1 140px; min-width: 0; }
.qa-field.qa-priority { flex-basis: 108px; }
.qa-field select, .qa-field input { width: 100%; }

/* The quick-add people menu. A button that says who is on it, and a tick list that
   floats over the board rather than stretching the bar out of one line. */
.qa-people { position: relative; }
.qa-people-btn {
  width: 100%; text-align: left; cursor: pointer;
  padding: 8px 10px; border: 1px solid var(--border-2); border-radius: 8px;
  background: var(--panel); color: var(--muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.qa-people-btn:hover { border-color: var(--faint); }
.qa-people-btn.chosen { color: var(--text); }
.qa-people-btn[aria-expanded="true"] { border-color: var(--accent); }
.qa-people-menu {
  position: absolute; z-index: 40; top: calc(100% + 4px); right: 0;
  min-width: 210px; max-height: 260px; overflow-y: auto;
  padding: 6px; border: 1px solid var(--border-2); border-radius: 10px;
  background: var(--panel); box-shadow: 0 10px 26px rgba(16, 42, 52, .16);
}
.qa-people-row {
  display: flex; align-items: center; gap: 8px;
  padding: 6px 8px; border-radius: 7px; cursor: pointer; font-size: 13px;
}
.qa-people-row:hover { background: var(--panel-2); }
.qa-people-row input { width: auto; margin: 0; }
.qa-people-all {
  display: block; width: 100%; text-align: left; cursor: pointer;
  padding: 6px 8px; margin-bottom: 4px; border: none; border-radius: 7px;
  background: none; color: var(--accent); font-size: 12px; font-weight: 600;
}
.qa-people-all:hover { background: var(--accent-2); }

/* Small enough to stay out of the way, dark enough to actually read. */
.qa-label {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--muted);
  padding-left: 2px;
}

.qa-actions { display: flex; gap: 8px; flex: 0 0 auto; align-items: center; }

/* The bulk bar sits above the list and stays put while you scroll a long selection -
   losing sight of Delete halfway down a hundred tasks is how people give up on it. */
.bulk-bar {
  position: sticky; top: 0; z-index: 20;
  display: flex; align-items: center; gap: 8px;
  margin: 0 0 12px; padding: 9px 12px; border-radius: 9px;
  background: var(--accent-2); border: 1px solid var(--accent);
}
.bulk-count { flex: 1; font-size: 13px; font-weight: 600; color: var(--accent); }
.bulk-bar .btn { padding: 5px 12px; font-size: 12px; }

/* In select mode the whole card is a target, so it has to look like one. */
.task.selectable { cursor: pointer; }
.task.selectable:hover { border-color: var(--accent); }
.task.picked { border-color: var(--accent); background: var(--accent-2); }
.task-pick {
  flex: none; width: 16px; height: 16px; margin: 11px 0 0 0; accent-color: var(--accent);
}
/* Nothing to tick on a task you are not allowed to delete: a checkbox that refuses
   when you press Delete is worse than no checkbox. */
.task-pick.locked { visibility: hidden; }
.quick-add button { flex: 0 0 auto; }
/* Secondary to Add, but a real way through rather than a footnote - so it keeps the
   accent colour and only loses the fill. */
.qa-more { white-space: nowrap; color: var(--accent); }
.qa-more:hover { background: var(--accent-2); color: var(--accent); }
.content { flex: 1; overflow-y: auto; padding: 18px 22px 60px; }

/* ------------------------------------------------------------- list view */
.group { margin-bottom: 22px; }
.group-head {
  display: flex; align-items: center; gap: 8px; margin-bottom: 8px;
  font-weight: 600; font-size: 13px;
}
.group-head .cat-count { font-weight: 400; }
.task-list { display: flex; flex-direction: column; gap: 6px; }

.task {
  display: flex; align-items: flex-start; gap: 10px;
  background: var(--panel); border: 1px solid var(--border);
  border-radius: var(--radius); padding: 10px 12px; cursor: pointer;
  transition: border-color .12s, box-shadow .12s;
}
.task:hover { border-color: var(--border-2); box-shadow: var(--shadow); }
.task.selected { border-color: var(--accent); }
.task.done .task-title { text-decoration: line-through; color: var(--faint); }
.task.dragging { opacity: .45; }

.status-btn {
  flex: none; width: 18px; height: 18px; margin-top: 1px;
  border-radius: 50%; border: 2px solid var(--border-2);
  background: transparent; cursor: pointer; display: grid; place-items: center;
  font-size: 11px; line-height: 1; color: #fff;
}
.status-btn.doing { border-color: var(--warn); background: var(--warn); }
.status-btn.done  { border-color: var(--ok);   background: var(--ok); }

.task-main { flex: 1; min-width: 0; }
/* Title and "Added ..." share a row: the date sits at the right edge and the title
   takes whatever is left, so a very long title wraps instead of pushing the date off. */
.task-head { display: flex; align-items: baseline; gap: 10px; }
.task-title { font-weight: 500; word-break: break-word; flex: 1; min-width: 0; }
.task-added {
  flex: none;
  font-size: 11px;
  color: var(--faint);
  white-space: nowrap;
  cursor: default;
}
/* The clock time, a shade behind the day, so the pair stays one quiet note at the end
   of the row instead of two labels. The separator is a real character in the markup,
   not generated here: CSS content is skipped by copy-and-paste and by some readers. */
.task-added-time {
  opacity: .75;
  font-variant-numeric: tabular-nums;      /* so times do not jitter between rows */
}

/* Faint until you go near it, and never invisible: a hover-only control cannot be found
   at all on a touch screen. Red only on hover, so a wall of cards is not dotted with
   warning colour. */
.task-del {
  flex: none;
  border: none;
  background: transparent;
  opacity: .4;
  width: 20px; height: 20px;
  border-radius: 6px;
  /* Smaller than the text around it: an emoji carries more visual weight per pixel than
     a glyph, so 12px here sits about the same as the 15px cross it replaced. */
  font-size: 12px; line-height: 1;
  /* Emoji ignore `color`, so the hover cue has to be desaturation and a halo instead. */
  filter: grayscale(1);
  display: grid; place-items: center;
  cursor: pointer;
  transition: opacity .12s, background .12s, filter .12s;
}
.task:hover .task-del { opacity: .7; }
.task-del:hover, .task-del:focus-visible {
  opacity: 1;
  filter: none;
  background: color-mix(in srgb, var(--danger) 14%, transparent);
}

@media (max-width: 560px) {
  /* On a phone the date drops under the title rather than squeezing it, and the delete
     button stays on the title's line where a thumb can reach it. */
  .task-head { flex-wrap: wrap; }
  .task-title { flex: 1 1 auto; }
  .task-added { order: 3; flex-basis: 100%; }
  .task-del { opacity: .7; }
}
.task-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 7px; margin-top: 5px; font-size: 12px; color: var(--muted); }
.chip {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 2px 8px; border-radius: 999px;
  background: var(--panel-2); border: 1px solid var(--border);
}
.chip.p1 { color: var(--danger); border-color: color-mix(in srgb, var(--danger) 35%, transparent); }
.chip.p3 { color: var(--faint); }
.chip.overdue { color: var(--danger); border-color: color-mix(in srgb, var(--danger) 35%, transparent); }
.chip.today { color: var(--warn); border-color: color-mix(in srgb, var(--warn) 40%, transparent); }
.mini-avatar {
  width: 18px; height: 18px; border-radius: 50%; background: var(--border-2);
  color: var(--text); font-size: 9px; font-weight: 600;
  display: inline-grid; place-items: center;
}

/* ------------------------------------------------------------ board view */

.empty { text-align: center; color: var(--faint); padding: 44px 20px; }
.empty strong { display: block; color: var(--muted); margin-bottom: 5px; font-size: 15px; }

/* ---------------------------------------------------------------- drawer */
.app:has(#drawer:not(.hidden)) { grid-template-columns: 250px 1fr 350px; }
.drawer { background: var(--panel); border-left: 1px solid var(--border); display: flex; flex-direction: column; overflow: hidden; }
.drawer-head { display: flex; justify-content: space-between; align-items: center; padding: 12px 16px; border-bottom: 1px solid var(--border); }
.drawer-module { font-size: 11px; text-transform: uppercase; letter-spacing: .07em; color: var(--faint); font-weight: 600; }
.drawer-body { padding: 16px; overflow-y: auto; display: flex; flex-direction: column; gap: 14px; }
.field { display: flex; flex-direction: column; gap: 5px; }
.field > span { font-size: 11px; text-transform: uppercase; letter-spacing: .06em; color: var(--faint); font-weight: 600; }
.field-row { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.drawer-title { font-size: 16px; font-weight: 600; border: 1px solid transparent; background: transparent; padding: 6px 8px; margin-left: -8px; }
.drawer-title:hover { border-color: var(--border); }
.saved-flash { color: var(--ok); font-size: 11px; }
.trail { font-size: 12px; color: var(--faint); line-height: 1.6; border-top: 1px solid var(--border); padding-top: 12px; }

.comments { display: flex; flex-direction: column; gap: 10px; border-top: 1px solid var(--border); padding-top: 14px; }
.comment { background: var(--panel-2); border: 1px solid var(--border); border-radius: 9px; padding: 9px 11px; }
.comment-head { display: flex; justify-content: space-between; align-items: center; gap: 8px; font-size: 12px; color: var(--muted); margin-bottom: 4px; }
.comment-body { white-space: pre-wrap; word-break: break-word; font-size: 13px; }
.comment-actions { display: flex; gap: 4px; }

/* ----------------------------------------------------------------- modal */
.modal-backdrop { position: fixed; inset: 0; background: rgba(10,12,16,.45); display: grid; place-items: center; padding: 20px; z-index: 50; }
.modal { background: var(--panel); border: 1px solid var(--border); border-radius: 13px; box-shadow: var(--shadow); width: 100%; max-width: 390px; padding: 20px; }
.modal h3 { margin: 0 0 14px; font-size: 16px; }
.modal .field { margin-bottom: 13px; }
.modal-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 16px; }
.modal-actions .spacer { flex: 1; }
.swatches { display: flex; flex-wrap: wrap; gap: 7px; }
.swatch { width: 24px; height: 24px; border-radius: 50%; border: 2px solid transparent; cursor: pointer; }
.swatch.active { border-color: var(--text); }

/* ----------------------------------------------------------------- toast */
.toast {
  position: fixed; bottom: 22px; left: 50%; transform: translateX(-50%);
  background: var(--text); color: var(--bg); padding: 9px 16px;
  border-radius: 9px; font-size: 13px; z-index: 60; box-shadow: var(--shadow);
}
.toast.error { background: var(--danger); color: #fff; }

/* ------------------------------------------------------------ responsive */
@media (max-width: 900px) {
  .app, .app:has(#drawer:not(.hidden)) { grid-template-columns: 1fr; grid-template-rows: auto 1fr; }
  .sidebar { flex-direction: row; flex-wrap: wrap; gap: 12px; align-items: center; }
  .side-section, .module-switch { flex-direction: row; align-items: center; flex-wrap: wrap; }
  .category-list { flex-direction: row; flex-wrap: wrap; }
  .cat-row { max-width: 45vw; }
  .side-foot { margin-top: 0; border-top: none; }
  .drawer { position: fixed; inset: 0; z-index: 40; }
  .board { grid-template-columns: 1fr; }
  .topbar { flex-wrap: wrap; }
  .topbar-right input[type=search] { width: 140px; }
  /* Two columns instead of one tall stack, so the form stops burying the task
     list on a phone. The title spans the full width; the rest pair up. */
  .quick-add { flex-wrap: wrap; }
  #quick-title { flex: 1 1 100%; }
  .quick-add select, .quick-add input[type=date] { flex: 1 1 calc(50% - 4px); min-width: 0; }
  .quick-add button { flex: 1 1 calc(50% - 4px); }
}


/* ---------------------------------------------------------------- google sign in */
.btn.google {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  background: #fff;
  color: #3c4043;
  border: 1px solid #dadce0;
  font-weight: 600;
  text-decoration: none;
  padding: 11px 16px;
}
.btn.google:hover { background: #f8f9fa; border-color: #d2d5d9; }
.btn.google:active { background: #f1f3f4; }
.google-mark { width: 18px; height: 18px; flex: none; }
.hint.center { text-align: center; display: block; margin-top: 8px; }

/* "or" rule between the Google button and the password form */
.auth-or {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 18px 0 14px;
  color: #9ca3af;
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: .06em;
}
.auth-or::before, .auth-or::after {
  content: "";
  flex: 1;
  height: 1px;
  background: #e5e7eb;
}


/* ---------------------------------------------------------- display pictures */
/* One rule set for both shapes: a photo fills the circle, initials sit in the middle. */
.avatar.has-photo,
.mini-avatar.has-photo {
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  color: transparent;
}
img.mini-avatar,
img.avatar {
  object-fit: cover;
  display: inline-block;
  background: var(--border-2);
}

.avatar-lg { width: 64px; height: 64px; font-size: 22px; }

.avatar-row {
  display: flex;
  align-items: center;
  gap: 14px;
  margin-bottom: 4px;
}
.avatar-actions { display: flex; flex-direction: column; align-items: flex-start; gap: 6px; }
.avatar-actions .btn { padding: 5px 11px; font-size: 12px; }


/* ------------------------------------------------------------ picture cropper */
.crop-wrap { display: flex; justify-content: center; margin: 4px 0 2px; }
.crop-canvas {
  border-radius: 12px;
  background: var(--panel-2);
  cursor: grab;
  /* Without this a drag on a touch screen scrolls the page instead of moving the photo. */
  touch-action: none;
  user-select: none;
}
.crop-canvas:active { cursor: grabbing; }
.crop-controls { display: flex; align-items: center; gap: 10px; margin-top: 12px; }
.crop-zoom { flex: 1; accent-color: var(--accent); }


/* ----------------------------------------------------------------- leaderboard */
/* Compact on purpose: one range control at the top drives everything below it, so no
   block has to repeat "last N days" in its own heading. */
.lb-top { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; margin-bottom: 14px; }
.lb-title { font-size: 16px; margin: 0; }
.lb-ranges { display: flex; gap: 2px; background: var(--panel-2); border: 1px solid var(--border); border-radius: 9px; padding: 2px; }
.lb-ranges .tab { font-size: 12px; padding: 4px 10px; }

.lb-tiles { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; margin-bottom: 16px; }
.lb-tile {
  background: var(--panel); border: 1px solid var(--border); border-radius: 10px;
  padding: 10px 12px; display: flex; flex-direction: column; gap: 1px;
}
.lb-tile-n { font-size: 22px; font-weight: 700; line-height: 1.1; color: var(--accent); }
.lb-tile-l { font-size: 11px; color: var(--muted); text-transform: uppercase; letter-spacing: .05em; }

.lb-sub { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; margin-bottom: 8px; font-size: 12px; font-weight: 600; text-transform: uppercase; letter-spacing: .06em; color: var(--muted); }
.lb-sub-note { font-weight: 400; text-transform: none; letter-spacing: 0; color: var(--faint); }

.lb-trend-wrap { margin-bottom: 18px; }
.lb-trend { display: flex; align-items: flex-end; gap: 4px; height: 64px; }
.lb-day { flex: 1; background: var(--brand); border-radius: 3px 3px 0 0; min-height: 3px; }
.lb-day.zero { background: var(--border-2); }
.lb-trend-axis { display: flex; justify-content: space-between; font-size: 11px; color: var(--faint); margin-top: 4px; }

.lb-panels { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; align-items: start; }
.lb-panel { min-width: 0; }
.lb-rows { display: flex; flex-direction: column; gap: 5px; }

.lb-bar-row { display: flex; align-items: center; gap: 8px; padding: 3px 6px; border-radius: 8px; min-width: 0; }
.lb-bar-row.me { background: var(--accent-2); }
.lb-rank { font-size: 11px; font-weight: 700; color: var(--faint); width: 20px; flex: none; }
.lb-avatar { width: 22px; height: 22px; font-size: 9px; flex: none; }
.lb-label { font-size: 13px; width: 132px; flex: none; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.lb-track { flex: 1; min-width: 24px; height: 8px; border-radius: 4px; background: var(--border-2); overflow: hidden; }
.lb-fill { display: block; height: 100%; border-radius: 4px; }
.lb-num { font-size: 13px; font-weight: 700; width: 28px; text-align: right; flex: none; }

@media (max-width: 760px) {
  .lb-tiles { grid-template-columns: repeat(2, 1fr); }
  .lb-panels { grid-template-columns: 1fr; gap: 16px; }
  .lb-label { width: 84px; }
}


/* --------------------------------------------------------- whose tasks (Work) */
/* One dropdown, deliberately: a row of buttons would grow with the team, and this stays
   the same width whether there are three people or thirty. */
.scope-select {
  width: auto;
  min-width: 104px;
  max-width: 168px;
  font-size: 13px;
  padding: 6px 8px;
  background: var(--panel-2);
  cursor: pointer;
}
@media (max-width: 760px) {
  .scope-select { min-width: 92px; max-width: 128px; }
}


/* ------------------------------------------------------ built-in categories */
/* The three shared Work categories the app seeds. They read as part of the furniture:
   a padlock where the "..." menu sits on the ones the team created. */
.cat-lock {
  display: inline-grid;
  place-items: center;
  width: 22px;
  height: 22px;
  flex: none;
  color: var(--faint);
}
.cat-lock svg { width: 11px; height: 11px; fill: currentColor; }
.cat-row.builtin:hover .cat-lock { color: var(--muted); }


/* ------------------------------------------------------------- activity log */
.modal.modal-wide { max-width: 700px; }

#log-btn svg { width: 17px; height: 17px; }

.log-table { border: 1px solid var(--border); border-radius: 10px; overflow: hidden; }

/* Header and rows share one grid definition, so the columns line up. */
.log-head, .log-row {
  display: grid;
  grid-template-columns: 150px 44px minmax(0, 1fr);
  gap: 12px;
  padding: 8px 12px;
  align-items: start;
}
.log-head {
  background: var(--panel-2);
  border-bottom: 1px solid var(--border);
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--muted);
}

/* Scrolls inside the modal, so a long history never pushes Close off the screen. */
.log-list { max-height: 56vh; overflow-y: auto; }
.log-row { border-top: 1px solid var(--border); font-size: 13px; }
.log-list .log-row:first-child { border-top: none; }

.log-when { color: var(--muted); font-size: 12px; white-space: nowrap; font-variant-numeric: tabular-nums; }

/* A quiet chip rather than a photo: down a long column, initials line up and stay
   readable where a row of faces turns into noise. */
.log-user {
  display: inline-block;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .04em;
  color: var(--muted);
  background: var(--panel-2);
  border: 1px solid var(--border);
  border-radius: 5px;
  padding: 1px 5px;
  text-align: center;
  cursor: default;
}

.log-summary { min-width: 0; }
.log-task { display: flex; align-items: center; gap: 6px; font-weight: 600; margin-bottom: 2px; }
.log-task span:last-child { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.log-line { display: flex; align-items: baseline; gap: 7px; color: var(--muted); font-size: 12.5px; }

/* One dot per change, coloured by what kind it was. */
.log-pip { width: 5px; height: 5px; border-radius: 50%; background: var(--border-2); flex: none; transform: translateY(-2px); }
.log-pip.done { background: var(--ok); }
.log-pip.add  { background: var(--accent); }
.log-pip.del  { background: var(--danger); }
.log-pip.warn { background: var(--warn); }

@media (max-width: 620px) {
  .log-head, .log-row { grid-template-columns: 1fr auto; gap: 4px 8px; }
  .log-head span:nth-child(3) { display: none; }
  .log-summary { grid-column: 1 / 3; margin-top: 4px; }
}


/* --------------------------------------------------------------- routines */
/* The schedule chip: quieter than priority, but distinct from a plain due date so a
   recurring task is recognisable at a glance in a long list. */
.chip.routine {
  color: var(--accent);
  border-color: color-mix(in srgb, var(--accent) 32%, transparent);
  background: var(--accent-2);
}


/* --------------------------------------------- notes and comments on a card */
/* Quiet by design: smaller than the title, muted, and clipped to one line each, so a
   card with a paragraph of notes is no taller than one without. */
.task-extras { margin-top: 6px; display: flex; flex-direction: column; gap: 3px; }
.task-extra { display: flex; align-items: baseline; gap: 7px; min-width: 0; font-size: 12px; }

/* Initials rather than a name: it identifies the author in three characters instead of
   pushing the words themselves off the card. */
.task-extra-who {
  flex: none;
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: .04em;
  color: var(--muted);
  background: var(--panel-2);
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 1px 4px;
  line-height: 1.35;
  cursor: default;
}
.task-extra-text {
  color: var(--muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-width: 0;
}
.task.done .task-extra-text { color: var(--faint); }


/* ------------------------------------------------- the New Task bar */
/* Sits directly above the list, aligned with the cards below it, so the button is where
   the eye already is when you go looking for somewhere to add work. */
.content-actions {
  /* Horizontal padding matches .content, so the button's left edge lines up exactly with
     the cards beneath it rather than floating a few pixels off. */
  padding: 16px 22px 0;
  display: flex;
  align-items: center;
  gap: 14px;
}

/* Pushed to the far side of the bar rather than sat next to the button: it is a hint,
   not a second action, and it should not compete with the thing you came here to press. */
.shortcut-tip {
  margin: 0 0 0 auto;
  font-size: 11.5px;
  color: var(--faint);
  white-space: nowrap;
}
.shortcut-tip kbd {
  font-family: var(--sans);
  font-size: 10.5px;
  font-weight: 600;
  color: var(--muted);
  background: var(--panel);
  border: 1px solid var(--border-2);
  border-bottom-width: 2px;
  border-radius: 4px;
  padding: 0 4px;
  margin: 0 1px;
}
/* A keyboard hint is no use without a keyboard, and the bar is tight on a phone. */
@media (max-width: 860px) {
  .shortcut-tip { display: none; }
}


/* ------------------------------------------------------------- assignees */
.assignees-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-bottom: 6px; }
.assignees-all { padding: 3px 9px; font-size: 11.5px; }
.assignees {
  display: flex; flex-direction: column; gap: 2px;
  max-height: 190px; overflow-y: auto;
  border: 1px solid var(--border); border-radius: 9px; padding: 6px;
  background: var(--panel);
}
.assignee-row { display: flex; align-items: center; gap: 8px; padding: 3px 4px; border-radius: 6px; cursor: pointer; font-size: 13px; }
.assignee-row:hover { background: var(--panel-2); }
.assignee-row input { width: auto; flex: none; }
.assignee-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* A tick beside whoever has finished their own piece. */
.assignee-done { flex: none; color: var(--ok); font-weight: 700; }

.chip.ok { color: var(--ok); border-color: color-mix(in srgb, var(--ok) 35%, transparent); }


/* --------------------------------------------------------------- telegram */
.tg-box { margin: 4px 0 2px; padding: 10px 12px; border: 1px solid var(--border); border-radius: 10px; background: var(--panel-2); }
.tg-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.tg-btn { padding: 4px 10px; font-size: 12px; flex: none; }
.tg-code { margin: 8px 0 0; font-size: 12.5px; }
/* The code is meant to be typed at a phone, so it gets room to breathe. */
.tg-digits { font-size: 14px; letter-spacing: .06em; color: var(--accent); }


/* ----------------------------------------------------------------- my day */
.myday-btn {
  display: flex; align-items: center; gap: 8px;
  width: 100%; text-align: left; cursor: pointer;
  border: 1px solid transparent; background: transparent;
  border-radius: 10px; padding: 9px 10px; color: var(--text);
}
.myday-btn:hover { background: var(--panel-2); }
.myday-btn.active { background: var(--accent-2); border-color: var(--accent); color: var(--accent); }
.myday-icon { font-size: 15px; line-height: 1; }
.myday-count { margin-left: auto; font-size: 12px; color: var(--muted); }

/* One quiet row of narrowing controls. No standing labels and no button that does
   nothing: the four controls say what they are, and Clear only appears once there is
   something to clear. */
.day-filters {
  display: flex; align-items: center; flex-wrap: wrap; gap: 6px;
  margin: -2px 0 14px;
}
.day-filters select, .day-filters input[type=date] {
  width: auto; padding: 4px 7px; font-size: 12px; line-height: 1.3;
  border-radius: 7px; color: var(--muted);
  background: var(--panel-2); border-color: transparent;
}
.day-filters select:hover, .day-filters input[type=date]:hover { color: var(--text); }
.day-filters select:focus, .day-filters input[type=date]:focus {
  color: var(--text); border-color: var(--accent);
}
.day-filters .day-cat { max-width: 170px; }
.day-filters input[type=date] { font-variant-numeric: tabular-nums; }
.day-clear {
  border: none; background: none; cursor: pointer; padding: 4px 6px;
  font-size: 12px; color: var(--faint);
}
.day-clear:hover { color: var(--accent); }
.day-filters + .day-head { margin-top: 0; }

/* A date rail down the left, so the day reads as a schedule rather than a pile. */
.day-head {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 8px; margin: 18px 0 8px; font-size: 12px; font-weight: 700;
  text-transform: uppercase; letter-spacing: .06em; color: var(--muted);
}
.day-head:first-child { margin-top: 0; }
.day-head.overdue { color: var(--danger); }
.day-head.done { color: var(--ok); }
.day-list { display: flex; flex-direction: column; gap: 7px; }
.day-row { display: flex; align-items: flex-start; gap: 10px; }
.day-when {
  flex: none; width: 64px; padding-top: 11px;
  font-size: 12px; color: var(--muted); text-align: right;
  font-variant-numeric: tabular-nums;
}
.day-where {
  flex: none; width: 58px; padding-top: 11px;
  font-size: 10.5px; font-weight: 700; letter-spacing: .05em;
  text-transform: uppercase; color: var(--faint);
}
.day-where.personal { color: var(--accent); }
.day-card { flex: 1; min-width: 0; }

@media (max-width: 640px) {
  .day-when { width: 52px; }
  .day-where { display: none; }
}
