/* ---- Self-hosted variable fonts (offline-first, no Google Fonts dependency) ---- */
@font-face {
  font-family: 'Inter'; font-style: normal; font-weight: 100 900; font-display: swap;
  src: url('fonts/inter-cyrillic.woff2') format('woff2');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
@font-face {
  font-family: 'Inter'; font-style: normal; font-weight: 100 900; font-display: swap;
  src: url('fonts/inter-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* Display font — Manrope (HAS Cyrillic, so Russian headings get display treatment too) */
@font-face {
  font-family: 'Manrope'; font-style: normal; font-weight: 200 800; font-display: swap;
  src: url('fonts/manrope-cyrillic.woff2') format('woff2');
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
@font-face {
  font-family: 'Manrope'; font-style: normal; font-weight: 200 800; font-display: swap;
  src: url('fonts/manrope-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

:root {
  /* BLUEPRINT identity (v62): cyan engineering canvas on near-black blue-graphite.
     Runtime palette (SCHEMES in app.js) overrides --bg…--muted + --primary/-2/--accent at runtime. */
  --bg: #0a0e14;
  --bg-2: #0d1219;
  --panel: #10161f;
  --panel-2: #152130;
  --border: #21344c;
  --text: #dfe9f2;
  --muted: #7d93aa;
  /* default scheme = Cyan. Semantics kept INDEPENDENT of the accent so they survive scheme/custom swaps. */
  --primary: #4db8d8;
  --primary-2: #74d0ec;
  --success: #46c79a;
  --warning: #e0b34a;
  --danger: #e0676a;
  --accent: #2f93b8;

  /* Accent-derived soft tints — react automatically when --primary changes at runtime */
  --accent-soft:   color-mix(in oklab, var(--primary) 15%, transparent);
  --accent-softer: color-mix(in oklab, var(--primary) 8%,  transparent);
  --accent-line:   color-mix(in oklab, var(--primary) 38%, transparent);
  --accent-ring:   color-mix(in oklab, var(--primary) 28%, transparent);

  /* accent-reactive alpha tints — derived from --primary/--accent so ALL 8 presets recolor every state */
  --primary-05: color-mix(in oklab, var(--primary) 5%, transparent);
  --primary-06: color-mix(in oklab, var(--primary) 6%, transparent);
  --primary-07: color-mix(in oklab, var(--primary) 7%, transparent);
  --primary-12: color-mix(in oklab, var(--primary) 12%, transparent);
  --primary-15: color-mix(in oklab, var(--primary) 15%, transparent);
  --primary-16: color-mix(in oklab, var(--primary) 16%, transparent);
  --primary-18: color-mix(in oklab, var(--primary) 18%, transparent);
  --primary-20: color-mix(in oklab, var(--primary) 20%, transparent);
  --primary-25: color-mix(in oklab, var(--primary) 25%, transparent);
  --primary-30: color-mix(in oklab, var(--primary) 30%, transparent);
  --primary-35: color-mix(in oklab, var(--primary) 35%, transparent);
  --primary-40: color-mix(in oklab, var(--primary) 40%, transparent);
  --primary-50: color-mix(in oklab, var(--primary) 50%, transparent);
  --primary-55: color-mix(in oklab, var(--primary) 55%, transparent);
  --primary-60: color-mix(in oklab, var(--primary) 60%, transparent);
  --primary-75: color-mix(in oklab, var(--primary) 75%, transparent);
  --primary-80: color-mix(in oklab, var(--primary) 80%, transparent);
  --accent-06: color-mix(in oklab, var(--accent) 6%, transparent);
  --accent-10: color-mix(in oklab, var(--accent) 10%, transparent);
  --accent-15: color-mix(in oklab, var(--accent) 15%, transparent);
  --accent-20: color-mix(in oklab, var(--accent) 20%, transparent);
  --accent-30: color-mix(in oklab, var(--accent) 30%, transparent);
  --accent-50: color-mix(in oklab, var(--accent) 50%, transparent);

  /* Tinted elevation scale (iris-navy, not pure black) — Phase 5A: re-tinted toward
     the --primary (#7c5cff) hue at low lightness so depth reads as part of the iris
     palette instead of a flat grey-black. Same geometry (blur/spread/offset) and
     opacities as before; only the rgba *hue* is shifted toward indigo. */
  --shadow:   0 14px 36px -10px rgba(22, 14, 58, .55);
  --shadow-1: 0 1px 2px rgba(16, 10, 44, .42), 0 3px 8px -3px rgba(16, 10, 44, .36);
  --shadow-2: 0 10px 28px -10px rgba(22, 14, 58, .55);
  --shadow-3: 0 28px 64px -18px rgba(18, 11, 52, .7);
  --glow:     0 8px 28px -6px color-mix(in oklab, var(--primary) 55%, transparent);

  /* Motion */
  --ease-out:    cubic-bezier(.16, 1, .3, 1);
  --ease-spring: cubic-bezier(.34, 1.4, .5, 1);
  /* Motion duration scale (P3A) — names the de-facto tiers already in use.
     fast=150ms covers the dominant 150ms UI transitions; base=250ms the 250/260ms
     pops; slow=400ms the 400/420ms fills/view-enter. Intentionally-tuned micro-timings
     (50/120/180/200/300/340ms) and ambient loops (2s+) are left literal. */
  --dur-fast: 150ms;
  --dur-base: 250ms;
  --dur-slow: 400ms;

  /* Radius scale (P3A) — additive aliases over the existing centres (10/14).
     --radius-sm (10) and --radius (14) are unchanged; --radius-md aliases --radius,
     --radius-lg names the 16px overlay corner used by gate/empty-state icons. */
  --radius: 3px;
  --radius-sm: 3px;
  --radius-md: var(--radius);
  --radius-lg: 4px;
  /* --radius-pill (P3B): names the 999px pill radius used by all chips/badges/pills.
     Pure alias — value identical to the literal 999px, so zero visual change. */
  --radius-pill: 3px;
  /* --chip-pad (P3B): canonical padding for the *interactive* chip family
     (.chip / .chip.smart). The dense inline micro-pills keep their own 1px/2px
     vertical padding (task-row + calendar density is load-bearing). */
  --chip-pad: 6px 11px;

  /* Spacing scale (P3A) — canonical 4/8/12/16/20/24 backbone (additive; existing
     literal paddings/gaps are left in place — these tokens are for future use). */
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 20px;
  --space-6: 24px;

  /* Z-index scale (P3A) — NAMES the current stacking order; values are identical to
     what shipped, so substituting these changes nothing visually. */
  --z-topbar: 5;
  --z-bottomnav: 30;
  --z-sheet-backdrop: 49;
  --z-sheet: 50;
  --z-modal: 60;
  --z-toast: 80;

  /* Glass (P3A) — shared frosted-surface blur + 1px inner top-edge highlight. */
  --glass-blur: 14px;
  --glass-edge: inset 0 1px 0 rgba(255, 255, 255, .08);

  --font-display: ui-monospace, "SF Mono", "JetBrains Mono", "Cascadia Code", "DejaVu Sans Mono", Menlo, Consolas, "Liberation Mono", monospace;
}

[data-theme="light"] {
  --bg: #f7f6fb;
  --bg-2: #efedf6;
  --panel: #ffffff;
  --panel-2: #f4f2fa;
  --border: #e6e3f0;
  --text: #18152a;
  --muted: #4d4660;
  /* Light theme: harmonized to the same iris hue family as dark (more blue-violet),
     opacities unchanged so light cards stay airy. */
  --shadow:   0 14px 32px -12px rgba(48, 34, 96, .14);
  --shadow-1: 0 1px 2px rgba(48, 34, 96, .06), 0 2px 6px -2px rgba(48, 34, 96, .08);
  --shadow-2: 0 10px 26px -10px rgba(48, 34, 96, .12);
  --shadow-3: 0 24px 56px -18px rgba(48, 34, 96, .18);
}

* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }
/* overscroll-behavior-y: none — kills accidental pull-to-refresh / rubber-band on iOS PWA */
html, body { height: 100%; margin: 0; overscroll-behavior-y: none; }
body {
  font-family: ui-monospace, "SF Mono", "JetBrains Mono", "Cascadia Code", "DejaVu Sans Mono", Menlo, Consolas, "Liberation Mono", monospace;
  background: var(--bg);
  color: var(--text);
  font-size: 14px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* Ambient aurora — slow-drifting tonal mesh behind everything (fixed, non-interactive) */
/* BLUEPRINT (v62): the ambient aurora is replaced by a fixed engineering dot/line grid.
   Grid lines are derived from --primary via color-mix, so the runtime palette recolors them. */
body::before {
  content: ""; position: fixed; inset: 0; z-index: -2;
  pointer-events: none;
  background-image:
    linear-gradient(color-mix(in oklab, var(--primary) 10%, transparent) 1px, transparent 1px),
    linear-gradient(90deg, color-mix(in oklab, var(--primary) 10%, transparent) 1px, transparent 1px);
  background-size: 40px 40px;
  -webkit-mask-image: radial-gradient(135% 115% at 50% 0, #000 58%, transparent 100%);
          mask-image: radial-gradient(135% 115% at 50% 0, #000 58%, transparent 100%);
}
/* Fine grain overlay — breaks up flat panels */
body::after {
  content: ""; position: fixed; inset: 0; z-index: -1;
  pointer-events: none; opacity: .035;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}
[data-theme="light"] body::after { opacity: .02; }
@keyframes auroraDrift {
  0%   { transform: translate3d(0,0,0) scale(1); }
  50%  { transform: translate3d(-2.5%, 1.5%, 0) scale(1.06); }
  100% { transform: translate3d(2%, -1.5%, 0) scale(1.03); }
}

.app {
  display: grid;
  grid-template-columns: 260px 1fr;
  min-height: 100vh; /* fallback */
  min-height: 100dvh;
}

/* SIDEBAR */
.sidebar {
  background: linear-gradient(180deg, rgba(255,255,255,.02), rgba(255,255,255,0)) , var(--panel);
  border-right: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  padding: 18px 14px;
  gap: 18px;
  position: sticky; top: 0; height: 100vh; /* fallback */
  height: 100dvh;
}
.brand { display: flex; align-items: center; gap: 12px; padding: 6px 6px 14px; border-bottom: 1px solid var(--border); }
.logo {
  width: 38px; height: 38px; border-radius: 10px;
  background: linear-gradient(135deg, var(--primary), var(--accent));
  display: grid; place-items: center; color: #fff; font-size: 20px; box-shadow: var(--shadow);
}
.brand-title { font-weight: 700; letter-spacing: .2px; }
.brand-sub { color: var(--muted); font-size: 12px; }

.nav { display: flex; flex-direction: column; gap: 4px; }
.nav-item {
  display: flex; align-items: center; gap: 10px;
  background: transparent; color: var(--text);
  border: 1px solid transparent;
  padding: 10px 12px; border-radius: var(--radius-sm); cursor: pointer;
  font-size: 14px; transition: background var(--dur-fast), border-color var(--dur-fast), transform .05s;
}
.nav-item:hover { background: var(--panel-2); }
.nav-item.active {
  background: linear-gradient(180deg, var(--primary-16), var(--primary-06));
  border-color: var(--primary-35);
}
.nav-icon { width: 22px; text-align: center; color: var(--muted); }
.nav-item.active .nav-icon { color: var(--primary-2); }
.badge {
  margin-left: auto;
  background: var(--panel-2);
  color: var(--muted);
  border: 1px solid var(--border);
  padding: 1px 7px; border-radius: var(--radius-pill); font-size: 11px;   /* P3B: pill radius via token (1px micro-pad kept) */
}

.sidebar-foot { margin-top: auto; }
.user-chip {
  display: flex; align-items: center; gap: 10px;
  background: var(--panel-2); border: 1px solid var(--border);
  padding: 10px; border-radius: var(--radius-sm);
}
.avatar {
  width: 32px; height: 32px; border-radius: 50%;
  background: linear-gradient(135deg, var(--accent), var(--primary));
  display: grid; place-items: center; color: #fff; font-weight: 700;
}
.user-name { font-weight: 600; }
.user-email { color: var(--muted); font-size: 12px; }

/* MAIN */
.main { display: flex; flex-direction: column; min-width: 0; }

/* TOPBAR */
.topbar {
  position: sticky; top: 0; z-index: var(--z-topbar);
  display: flex; align-items: center; gap: 12px;
  padding: 12px 22px;
  background: color-mix(in oklab, var(--bg), transparent 10%);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--border);
}
.search { flex: 1; position: relative; }
.search-icon {
  position: absolute; left: 12px; top: 50%; transform: translateY(-50%);
  color: var(--muted);
}
#global-search {
  width: 100%;
  padding: 10px 14px 10px 34px;
  background: var(--panel);
  border: 1px solid var(--border);
  color: var(--text);
  border-radius: var(--radius-sm);
  outline: none;
}
#global-search:focus { border-color: var(--primary); box-shadow: 0 0 0 3px var(--primary-18); }

.topbar-actions { display: flex; align-items: center; gap: 8px; }
.status-dot { color: var(--success); font-size: 22px; line-height: 1; }
.status-dot.warn { color: var(--warning); }
.status-dot.err { color: var(--danger); }

/* BUTTONS */
.btn {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 9px 14px; border-radius: var(--radius-sm); cursor: pointer;
  border: 1px solid var(--border); background: var(--panel);
  color: var(--text); font-size: 13px;
  transition: transform .05s, background var(--dur-fast), border-color var(--dur-fast);
}
.btn:hover { background: var(--panel-2); }
.btn:active { transform: translateY(1px); }
.btn:disabled, button:disabled { opacity: .5; cursor: not-allowed; }
.btn-sm { padding: 6px 10px; font-size: 12px; }
.btn-primary {
  background: linear-gradient(180deg, var(--primary), color-mix(in oklab, var(--primary), #000 12%));
  border-color: color-mix(in oklab, var(--primary), #000 12%);
  color: white;
  box-shadow: 0 4px 14px var(--primary-35);
}
.btn-primary:hover { background: linear-gradient(180deg, var(--primary-2), var(--primary)); }
.btn-ghost { background: transparent; }
.btn.danger { color: var(--danger); border-color: rgba(239,79,90,.4); }

/* VIEWS */
.view { display: none; padding: 22px; flex: 1; min-height: 0; }
.view.active { display: block; }

.page-head {
  display: flex; align-items: flex-end; justify-content: space-between; gap: 12px;
  margin-bottom: 18px;
}
.page-head h1 { font-size: 24px; margin: 0 0 4px; letter-spacing: .2px; }
.page-actions { display: flex; gap: 8px; }
.muted { color: var(--muted); }
.small { font-size: 12px; }

/* GRID & CARDS */
.grid { display: grid; gap: 14px; margin-bottom: 14px; }
/* Primary KPI row sits at the top of the dashboard as the attention-grab band;
   give it a touch more breathing room below before the secondary bento. */
.grid.kpis { grid-template-columns: repeat(4, 1fr); gap: var(--space-4); margin-bottom: var(--space-6); }
.grid.two-col { grid-template-columns: 1.2fr 1fr; }
.card {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 16px;
  box-shadow: var(--shadow);
}
.card-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 12px; }
.card-head h3 { margin: 0; font-size: 14px; letter-spacing: .3px; line-height: 1.2; }

.kpi-label { color: var(--muted); font-size: 12px; }
.kpi-value { font-size: 28px; font-weight: 700; margin-top: 4px; }
.kpi-value.success { color: var(--success); }
.kpi-value.danger { color: var(--danger); }
.kpi-sub { font-size: 12px; margin-top: 2px; }

/* FOCUS LIST */
.task-mini-list { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 8px; }
.task-mini {
  display: flex; align-items: center; gap: 10px;
  padding: 10px 12px; border-radius: var(--radius-sm);
  background: var(--panel-2); border: 1px solid var(--border);
}
.task-mini .ttl { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pill {
  display: inline-flex; align-items: center;
  font-size: 11px; font-weight: 600; letter-spacing: .02em;
  padding: 2px 8px; border-radius: 999px; line-height: 1.5;
  white-space: nowrap;
}
.pill.high { background: rgba(239,79,90,.18); color: #ff8c93; }
.pill.med  { background: rgba(245,165,36,.18); color: #ffc266; }
.task .pill::before { content: ''; width: 6px; height: 6px; border-radius: 50%; background: currentColor; margin-right: 6px; flex-shrink: 0; }
.pill.low  { background: rgba(62,207,142,.18); color: #6ee0a8; }

/* :focus-visible — accessible keyboard nav across interactives */
:focus { outline: none; }
button:focus-visible, a:focus-visible, input:focus-visible, textarea:focus-visible, select:focus-visible,
.nav-item:focus-visible, .chip:focus-visible, .palette-item:focus-visible, .ctx-item:focus-visible,
.task:focus-visible, .kcard:focus-visible, .note-item:focus-visible, .project-item:focus-visible,
.cal-day:focus-visible, .accent-swatch:focus-visible, .link-pill:focus-visible,
/* Phase 4B: div-based clickables that had click handlers but no keyboard ring.
   They now carry tabindex/role + Enter/Space handlers in app.js, so this CSS
   ring finally fires for keyboard users. */
.goal-row:focus-visible, .cstack-card:focus-visible, .tl-task:focus-visible,
.progress.clickable:focus-visible, .welcome-shortcut:focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: 2px;
  border-radius: inherit;
}

/* TIMELINE */
.timeline { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 10px; max-height: 280px; overflow: auto; }
.timeline li {
  display: flex; gap: 10px; align-items: flex-start;
  padding: 8px 0; border-bottom: 1px dashed var(--border);
}
.timeline li:last-child { border: 0; }
.tl-time { color: var(--muted); font-size: 12px; white-space: nowrap; }
.tl-text { flex: 1; }

/* CHART */
.chart { display: grid; grid-template-columns: repeat(7, 1fr); gap: 10px; height: 160px; align-items: end; padding-top: 14px; }
.bar-wrap { display: flex; flex-direction: column; align-items: center; gap: 6px; height: 100%; justify-content: end; }
.bar {
  width: 100%;
  background: linear-gradient(180deg, var(--primary), var(--accent));
  border-radius: 6px 6px 0 0;
  min-height: 6px;
  transition: height var(--dur-slow) ease;
}
.bar-label { font-size: 11px; color: var(--muted); }

/* FILTERS */
.smart-lists { display: flex; gap: 6px; flex-wrap: wrap; margin-bottom: 10px; }
.chip.smart {
  background: var(--panel-2); color: var(--text);
  border: 1px solid var(--border); padding: var(--chip-pad);   /* P3B: unified interactive-chip padding (was 6px 10px) */
  border-radius: var(--radius-pill); cursor: pointer; font-size: 12px;
}
.chip.smart:hover { border-color: var(--primary); }
.chip.smart.active {
  background: linear-gradient(135deg, var(--primary-25), var(--accent-20));
  border-color: var(--primary-60);
  color: var(--text);
}
.chip.smart.custom { border-style: dashed; }
.chip.smart.save-btn { color: var(--muted); border-style: dashed; }
.chip.smart.save-btn:hover { color: var(--text); }
.filters { display: grid; grid-template-columns: 150px 140px 140px 140px 1fr; gap: 10px; margin-bottom: 14px; }
@media (max-width: 1200px) { .filters { grid-template-columns: repeat(2, 1fr); } }

/* PROJECTS in sidebar */
.projects-section {
  margin-top: 8px; padding-top: 14px;
  border-top: 1px solid var(--border);
  display: flex; flex-direction: column; gap: 6px;
}
.projects-head { display: flex; align-items: center; justify-content: space-between; padding: 0 4px; }
.projects-list { display: flex; flex-direction: column; gap: 2px; max-height: 220px; overflow: auto; }
.project-item {
  display: flex; align-items: center; gap: 9px;
  padding: 7px 10px; border-radius: var(--radius-sm); cursor: pointer;
  font-size: 13px; color: var(--text); background: transparent;
  border: 1px solid transparent;
}
.project-item:hover { background: var(--panel-2); }
.project-item.active { background: var(--panel-2); border-color: var(--primary-35); }
.proj-dot { width: 10px; height: 10px; border-radius: 50%; flex-shrink: 0; }
.proj-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.proj-count { color: var(--muted); font-size: 11px; }
.proj-actions { display: none; gap: 2px; }
.project-item:hover .proj-actions { display: flex; }
.proj-actions .icon-btn { width: 22px; height: 22px; font-size: 11px; }

/* Project chip on task row */
.proj-chip {
  display: inline-flex; align-items: center; gap: 4px;
  font-size: 11px; padding: 1px 7px; border-radius: 999px;
  background: var(--panel-2); border: 1px solid var(--border);
}
.proj-chip .d { width: 7px; height: 7px; border-radius: 50%; }

/* PROJECT MODAL */
.color-grid { display: grid; grid-template-columns: repeat(8, 1fr); gap: 6px; }
.color-grid .cb {
  width: 100%; aspect-ratio: 1; border-radius: 8px;
  cursor: pointer; border: 2px solid transparent;
}
.color-grid .cb.selected { border-color: var(--text); transform: scale(1.05); }
/* Theme ALL form controls by container (was a brittle hardcoded id-list that left the task-modal's
   time/project/estimate/pin/recurrence/deps/link fields as unstyled white native widgets). */
.filters select, .filters input, .form-row input, .form-row select,
.modal-body input:not([type=checkbox]):not([type=radio]):not([type=color]),
.modal-body select, .modal-body textarea,
#note-title, #note-tags, #note-body, #chat-input,
#set-name, #set-email, #set-apikey, #set-model, #set-provider {
  background: var(--panel);
  border: 1px solid var(--border);
  color: var(--text);
  padding: 9px 12px;
  border-radius: var(--radius-sm);
  outline: none;
  font-size: 13px;
  width: 100%;
  color-scheme: dark; /* make native date/time/select pickers render dark, not white */
}
[data-theme="light"] .filters select, [data-theme="light"] .filters input,
[data-theme="light"] .form-row input, [data-theme="light"] .form-row select,
[data-theme="light"] .modal-body input, [data-theme="light"] .modal-body select, [data-theme="light"] .modal-body textarea {
  color-scheme: light;
}
.filters select:focus, .filters input:focus, .form-row input:focus, .form-row select:focus,
.modal-body input:focus, .modal-body select:focus, .modal-body textarea:focus,
#note-title:focus, #note-body:focus, #chat-input:focus,
#set-name:focus, #set-email:focus, #set-apikey:focus, #set-model:focus {
  border-color: var(--primary); box-shadow: 0 0 0 3px var(--primary-18);
}
/* Light theme: native placeholders render too faint on white — bump to a readable AA gray */
[data-theme="light"] input::placeholder,
[data-theme="light"] textarea::placeholder { color: #6c6680; opacity: 1; }

/* AUTH GATE — full-screen cold-start, sits BELOW modals (z 40) so auth modal can stack on top */
.auth-gate {
  position: fixed; inset: 0; z-index: 40;
  display: flex; align-items: center; justify-content: center;
  padding: 24px;
  /* iOS Safari shrinks position:fixed under URL bar; min-height + safe-area
     keep the auth card centered and clear of home-indicator. */
  padding-top: max(24px, env(safe-area-inset-top));
  padding-bottom: max(24px, env(safe-area-inset-bottom));
  overflow: auto;
  min-height: 100dvh;
}
.auth-gate[hidden] { display: none !important; }
.gate-bg {
  position: absolute; inset: 0; z-index: -1;
  overflow: hidden;
  background: var(--bg); /* OPAQUE fallback first — if the color-mix gradients below are unsupported and
                            invalidate that declaration, the gate stays opaque (never see-through → never
                            lets the app behind it show through / capture taps). */
  background:
    radial-gradient(1200px 600px at 20% 0%, color-mix(in oklab, var(--primary) 28%, transparent), transparent 60%),
    radial-gradient(900px 500px at 100% 100%, color-mix(in oklab, var(--accent) 22%, transparent), transparent 60%),
    var(--bg);
}

/* Falling pattern: violet "rain" of lines + dots drifting downward.
   Ported from a React/framer-motion component to pure CSS — the whole effect
   is an animated multi-layer background-position. Lives behind the auth card. */
.gate-bg::before {
  content: "";
  position: absolute; inset: 0; z-index: 0;
  /* fade the pattern toward the centre so it frames the card, not fights it */
  -webkit-mask-image: radial-gradient(ellipse at center, transparent 0%, transparent 30%, #000 100%);
          mask-image: radial-gradient(ellipse at center, transparent 0%, transparent 30%, #000 100%);
  background-image:
    radial-gradient(4px 100px at 0px 235px, var(--primary), transparent),
    radial-gradient(4px 100px at 300px 235px, var(--primary), transparent),
    radial-gradient(1.5px 1.5px at 150px 117.5px, var(--primary) 100%, transparent 150%),
    radial-gradient(4px 100px at 0px 252px, var(--primary), transparent),
    radial-gradient(4px 100px at 300px 252px, var(--primary), transparent),
    radial-gradient(1.5px 1.5px at 150px 126px, var(--primary) 100%, transparent 150%),
    radial-gradient(4px 100px at 0px 150px, var(--primary), transparent),
    radial-gradient(4px 100px at 300px 150px, var(--primary), transparent),
    radial-gradient(1.5px 1.5px at 150px 75px, var(--primary) 100%, transparent 150%),
    radial-gradient(4px 100px at 0px 253px, var(--primary), transparent),
    radial-gradient(4px 100px at 300px 253px, var(--primary), transparent),
    radial-gradient(1.5px 1.5px at 150px 126.5px, var(--primary) 100%, transparent 150%),
    radial-gradient(4px 100px at 0px 204px, var(--primary), transparent),
    radial-gradient(4px 100px at 300px 204px, var(--primary), transparent),
    radial-gradient(1.5px 1.5px at 150px 102px, var(--primary) 100%, transparent 150%),
    radial-gradient(4px 100px at 0px 134px, var(--primary), transparent),
    radial-gradient(4px 100px at 300px 134px, var(--primary), transparent),
    radial-gradient(1.5px 1.5px at 150px 67px, var(--primary) 100%, transparent 150%),
    radial-gradient(4px 100px at 0px 179px, var(--primary), transparent),
    radial-gradient(4px 100px at 300px 179px, var(--primary), transparent),
    radial-gradient(1.5px 1.5px at 150px 89.5px, var(--primary) 100%, transparent 150%),
    radial-gradient(4px 100px at 0px 299px, var(--primary), transparent),
    radial-gradient(4px 100px at 300px 299px, var(--primary), transparent),
    radial-gradient(1.5px 1.5px at 150px 149.5px, var(--primary) 100%, transparent 150%),
    radial-gradient(4px 100px at 0px 215px, var(--primary), transparent),
    radial-gradient(4px 100px at 300px 215px, var(--primary), transparent),
    radial-gradient(1.5px 1.5px at 150px 107.5px, var(--primary) 100%, transparent 150%),
    radial-gradient(4px 100px at 0px 281px, var(--primary), transparent),
    radial-gradient(4px 100px at 300px 281px, var(--primary), transparent),
    radial-gradient(1.5px 1.5px at 150px 140.5px, var(--primary) 100%, transparent 150%),
    radial-gradient(4px 100px at 0px 158px, var(--primary), transparent),
    radial-gradient(4px 100px at 300px 158px, var(--primary), transparent),
    radial-gradient(1.5px 1.5px at 150px 79px, var(--primary) 100%, transparent 150%),
    radial-gradient(4px 100px at 0px 210px, var(--primary), transparent),
    radial-gradient(4px 100px at 300px 210px, var(--primary), transparent),
    radial-gradient(1.5px 1.5px at 150px 105px, var(--primary) 100%, transparent 150%);
  background-size:
    300px 235px, 300px 235px, 300px 235px,
    300px 252px, 300px 252px, 300px 252px,
    300px 150px, 300px 150px, 300px 150px,
    300px 253px, 300px 253px, 300px 253px,
    300px 204px, 300px 204px, 300px 204px,
    300px 134px, 300px 134px, 300px 134px,
    300px 179px, 300px 179px, 300px 179px,
    300px 299px, 300px 299px, 300px 299px,
    300px 215px, 300px 215px, 300px 215px,
    300px 281px, 300px 281px, 300px 281px,
    300px 158px, 300px 158px, 300px 158px,
    300px 210px, 300px 210px, 300px 210px;
  animation: gate-falling 150s linear infinite;
}

@keyframes gate-falling {
  from {
    background-position:
      0px 220px, 3px 220px, 151.5px 337.5px, 25px 24px, 28px 24px, 176.5px 150px,
      50px 16px, 53px 16px, 201.5px 91px, 75px 224px, 78px 224px, 226.5px 230.5px,
      100px 19px, 103px 19px, 251.5px 121px, 125px 120px, 128px 120px, 276.5px 187px,
      150px 31px, 153px 31px, 301.5px 120.5px, 175px 235px, 178px 235px, 326.5px 384.5px,
      200px 121px, 203px 121px, 351.5px 228.5px, 225px 224px, 228px 224px, 376.5px 364.5px,
      250px 26px, 253px 26px, 401.5px 105px, 275px 75px, 278px 75px, 426.5px 180px;
  }
  to {
    background-position:
      0px 6800px, 3px 6800px, 151.5px 6917.5px, 25px 13632px, 28px 13632px, 176.5px 13758px,
      50px 5416px, 53px 5416px, 201.5px 5491px, 75px 17175px, 78px 17175px, 226.5px 17181.5px,
      100px 5119px, 103px 5119px, 251.5px 5221px, 125px 8428px, 128px 8428px, 276.5px 8495px,
      150px 9876px, 153px 9876px, 301.5px 9965.5px, 175px 13391px, 178px 13391px, 326.5px 13540.5px,
      200px 14741px, 203px 14741px, 351.5px 14848.5px, 225px 18770px, 228px 18770px, 376.5px 18910.5px,
      250px 5082px, 253px 5082px, 401.5px 5161px, 275px 6375px, 278px 6375px, 426.5px 6480px;
  }
}

/* Dotted blur veil over the rain — softens lines into a glowing pixel-grain,
   the same "screen-door" overlay the original component layered on top. */
.gate-bg::after {
  content: "";
  position: absolute; inset: 0; z-index: 1;
  background-image: radial-gradient(circle at 50% 50%, transparent 0, transparent 2px, var(--bg) 2px);
  background-size: 8px 8px;
  filter: brightness(2.2);
}
/* The soft "glow" blur is the single most expensive part on mobile: a full-screen
   Gaussian that must recompute every animation frame because the rain behind it moves.
   Enable it only on larger / precise-pointer screens (desktops) where the GPU budget
   exists; phones keep the animated rain + dotted veil without the per-frame blur. */
@media (min-width: 900px) and (pointer: fine) {
  .gate-bg::after {
    -webkit-backdrop-filter: blur(1em);
            backdrop-filter: blur(1em);
  }
}
[data-theme="light"] .gate-bg::after { filter: none; }

@media (prefers-reduced-motion: reduce) {
  .gate-bg::before { animation: none; }
}
.gate-card {
  width: min(520px, 100%);
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 20px;
  padding: 32px 32px 24px;
  box-shadow: 0 30px 80px rgba(0,0,0,.5);
  text-align: center;
}
.gate-logo {
  display: flex; align-items: center; gap: 12px;
  justify-content: center; margin-bottom: 24px;
}
.gate-card h1 {
  font-size: 22px; margin: 0 0 8px;
  letter-spacing: -.01em;
}
.gate-blurb {
  margin: 0 auto 22px; max-width: 420px;
  font-size: 13px; line-height: 1.55;
}
.gate-ctas {
  display: flex; flex-direction: column; gap: 8px;
  margin-bottom: 22px;
}
.btn-lg { padding: 13px 20px !important; font-size: 14px !important; }
.gate-features {
  display: grid; grid-template-columns: 1fr 1fr; gap: 10px;
  margin-bottom: 22px;
  padding: 14px;
  background: var(--panel-2); border: 1px solid var(--border);
  border-radius: 12px;
}
.gate-feat {
  display: flex; align-items: center; gap: 8px;
  font-size: 12px; color: var(--muted);
  text-align: left;
}
.gate-feat span:first-child { font-size: 14px; }
.gate-skip {
  background: transparent; border: 0;
  color: var(--muted); cursor: pointer;
  padding: 8px; font-size: 12px;
  display: flex; flex-direction: column; gap: 2px;
  align-items: center;
  margin: 0 auto;
}
.gate-skip:hover { color: var(--text); }
.gate-skip[hidden] { display: none !important; }
@media (max-width: 600px) {
  .gate-card { padding: 22px; border-radius: 16px; }
  .gate-features { grid-template-columns: 1fr; }
  .gate-card h1 { font-size: 18px; }
}

/* AUTH MODAL */
.auth-card { width: min(420px, 100%); }
.auth-tabs {
  display: inline-flex;
  background: var(--panel-2);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 3px;
  margin-bottom: 14px;
}
.auth-tabs .seg {
  padding: 7px 18px;
  font-size: 13px;
}
.auth-blurb { margin: 0 0 14px; }
.auth-warn {
  margin: 0 0 14px;
  padding: 10px 12px;
  background: rgba(245,165,36,.1);
  border: 1px solid rgba(245,165,36,.4);
  border-radius: var(--radius-sm);
  font-size: 12px;
  line-height: 1.45;
  color: #ffc266;
}
.auth-warn[hidden] { display: none !important; }
.auth-error {
  margin: 10px 0 0;
  padding: 10px 12px;
  background: rgba(239,79,90,.1);
  border: 1px solid rgba(239,79,90,.4);
  border-radius: var(--radius-sm);
  color: #ff8c93;
  font-size: 13px;
}
.auth-error[hidden] { display: none !important; }

/* USER-CHIP login state */
.user-chip {
  position: relative;
}
.signin-btn { padding: 6px 12px; font-size: 12px; }
.signout-btn {
  width: 28px; height: 28px;
  font-size: 12px;
  position: absolute;
  top: 6px; right: 6px;
  opacity: 0;
  transition: opacity var(--dur-fast);
}
.user-chip:hover .signout-btn { opacity: 1; }
.signout-btn[hidden] { display: none !important; }
.signin-btn[hidden] { display: none !important; }
.sync-status {
  font-size: 10.5px;
  margin-top: 2px;
  display: flex; align-items: center; gap: 4px;
}
.sync-status[hidden] { display: none !important; }
.sync-status.synced { color: var(--success); }
.sync-status.syncing { color: var(--warning); }
.sync-status.error  { color: var(--danger); }
.sync-status::before {
  content: '●';
  font-size: 10px;
}

/* HISTORY RESTORE UI */
.history-list {
  display: flex; flex-direction: column; gap: 6px;
  margin-top: 10px;
  padding: 8px;
  background: var(--panel-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  max-height: 320px; overflow: auto;
}
.history-list[hidden] { display: none !important; }
.hist-item {
  display: grid; grid-template-columns: 1fr auto auto;
  gap: 10px; align-items: center;
  padding: 8px 10px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 6px;
}
.hist-time {
  font-size: 12.5px; font-weight: 500;
}
.hist-meta { color: var(--muted); font-size: 11px; margin-top: 2px; }
.hist-restore-btn {
  background: var(--primary-15);
  border: 1px solid var(--primary-40);
  color: var(--primary-2);
  padding: 4px 10px; border-radius: 6px;
  cursor: pointer; font-size: 11px;
}
.hist-restore-btn:hover { background: var(--primary-30); }

/* MULTI-DEVICE SESSIONS in account section */
.sessions-wrap { display: flex; flex-direction: column; gap: 8px; }
.sessions-list {
  display: flex; flex-direction: column; gap: 6px;
  padding: 8px;
  background: var(--panel-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  max-height: 240px; overflow: auto;
}
.sessions-list[hidden] { display: none !important; }
.sess-item {
  display: grid; grid-template-columns: 1fr auto; gap: 8px;
  padding: 8px 10px; border-radius: 6px;
  background: var(--panel);
  border: 1px solid transparent;
}
.sess-item.current {
  border-color: rgba(62,207,142,.4);
  background: rgba(62,207,142,.06);
}
.sess-ua {
  font-size: 12px; line-height: 1.35;
  overflow: hidden; text-overflow: ellipsis;
}
.sess-meta {
  display: flex; flex-direction: column; gap: 2px;
  font-size: 10.5px; color: var(--muted);
  white-space: nowrap; text-align: right;
}
.sess-current-tag {
  font-size: 10px; color: var(--success);
  text-transform: uppercase; letter-spacing: 1px;
  margin-left: 6px;
}

/* ACCOUNT CARD in settings */
.account-body { display: flex; flex-direction: column; gap: 10px; padding-top: 4px; }
#account-status { font-size: 11px; padding: 2px 8px; border-radius: 999px; }
#account-status.in { background: rgba(62,207,142,.15); color: var(--success); }

/* WELCOME CARD (empty first-run) */
.welcome-card {
  display: flex; gap: 18px; align-items: flex-start;
  padding: 24px 26px;
  margin-bottom: 14px;
  background: linear-gradient(135deg, var(--primary-12), var(--accent-06));
  border-color: var(--primary-35);
}
.welcome-card[hidden] { display: none !important; }
.welcome-emoji {
  width: 64px; height: 64px; border-radius: 16px; flex-shrink: 0;
  background: linear-gradient(135deg, var(--primary), var(--accent));
  display: grid; place-items: center;
  font-size: 32px; color: #fff;
  box-shadow: 0 8px 24px var(--primary-35);
}
.welcome-body { flex: 1; min-width: 0; }
.welcome-body h2 { margin: 0 0 6px; font-size: 20px; }
.welcome-body p { margin: 0 0 14px; }
.welcome-ctas { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 12px; }
.welcome-hint { margin: 0; opacity: .8; }
.welcome-hint kbd { margin: 0 1px; }
@media (max-width: 600px) {
  .welcome-card { flex-direction: column; padding: 18px; gap: 12px; }
  .welcome-emoji { width: 48px; height: 48px; font-size: 24px; }
  .welcome-body h2 { font-size: 17px; }
}

/* DATA SUMMARY in settings */
.data-actions { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 12px; }
.danger-zone {
  margin-top: 8px; padding-top: 14px;
  border-top: 1px dashed rgba(239,79,90,.3);
}
.dz-title {
  color: var(--danger); font-size: 11px;
  text-transform: uppercase; letter-spacing: 1px;
  margin-bottom: 8px; font-weight: 600;
}

/* RESET MODAL */
.reset-list {
  list-style: none; padding: 12px 14px; margin: 6px 0;
  background: var(--panel-2); border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  display: flex; flex-direction: column; gap: 4px;
}
.reset-list li { font-size: 13px; }
.reset-list li::before { content: '· '; color: var(--muted); }
.reset-confirm-label {
  display: flex; gap: 10px; align-items: flex-start;
  padding: 10px 12px; margin-top: 8px;
  background: rgba(239,79,90,.06); border: 1px solid rgba(239,79,90,.3);
  border-radius: var(--radius-sm); cursor: pointer;
  font-size: 13px;
}
.reset-confirm-label input { margin-top: 2px; flex-shrink: 0; }
.reset-foot { gap: 6px; }
.reset-foot .btn:nth-child(2) { margin-right: auto; }
/* #reset-do:disabled now covered by the unified .btn:disabled / button:disabled rule */

/* SIDEBAR user-info layout fix */
.user-info { min-width: 0; flex: 1; }
.user-info .user-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.user-info .user-email[hidden] { display: none; }

/* SETTINGS: provider local hint */
.local-hint {
  margin: 10px 0 0; padding: 10px 12px;
  background: var(--primary-06); border: 1px solid var(--primary-25);
  border-radius: var(--radius-sm); font-size: 12px;
}

/* AUTO ROLLOVER BANNER */
.rollover-banner {
  display: flex; align-items: center; gap: 12px;
  padding: 12px 16px; margin-bottom: 14px;
  background: linear-gradient(135deg, rgba(245,165,36,.18), rgba(239,79,90,.12));
  border: 1px solid rgba(245,165,36,.45);
  border-radius: var(--radius-sm);
  flex-wrap: wrap;
}
.rollover-banner .ro-text { flex: 1; font-size: 13px; }
.rollover-banner strong { color: #ffc266; }
.rollover-banner[hidden] { display: none !important; }
.backup-banner {
  background: linear-gradient(135deg, var(--primary-15), var(--accent-10));
  border-color: var(--primary-40);
}
.backup-banner strong { color: var(--primary-2); }

/* GOALS */
.goals-list { display: flex; flex-direction: column; gap: 10px; }
.goal-row {
  display: grid; grid-template-columns: 32px 1fr auto;
  gap: 12px; align-items: center;
  padding: 10px 12px;
  background: var(--panel-2); border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  cursor: pointer;
}
.goal-row:hover { border-color: var(--primary-40); }
.goal-row .gico { font-size: 22px; }
.goal-row .gtitle { font-weight: 600; font-size: 13px; }
.goal-row .gsub { color: var(--muted); font-size: 11px; margin-top: 2px; }
.goal-row .gtrack {
  background: var(--border); height: 6px; border-radius: 3px; margin-top: 6px;
  overflow: hidden;
}
.goal-row .gfill {
  height: 100%; background: linear-gradient(90deg, var(--primary), var(--accent));
  transition: width var(--dur-slow) ease;
}
.goal-row .gfill.done { background: linear-gradient(90deg, var(--success), #60d6a3); }
.goal-row .gpct {
  font-weight: 700; font-size: 14px; font-variant-numeric: tabular-nums;
  color: var(--muted);
}
.goal-row.complete .gpct { color: var(--success); }

/* QUICK ADD */
.quick-add {
  display: flex; align-items: center; gap: 10px;
  padding: 4px 12px; margin-bottom: 10px;
  background: var(--panel); border: 1px dashed var(--border);
  border-radius: var(--radius-sm);
  transition: border-color var(--dur-fast);
}
.quick-add:focus-within { border-color: var(--primary); border-style: solid; box-shadow: 0 0 0 3px var(--primary-12); }
.quick-add .qa-ico { color: var(--muted); font-size: 16px; }
#quick-add-input {
  flex: 1; background: transparent !important; border: 0 !important;
  padding: 10px 0 !important; color: var(--text);
  border-radius: 0 !important;
}
#quick-add-input:focus { box-shadow: none !important; }
.qa-hint { padding: 2px 8px; border: 1px solid var(--border); border-radius: 4px; font-family: ui-monospace, monospace; font-size: 11px; }

/* TASK LIST */
.task-list { display: flex; flex-direction: column; gap: 8px; }
.task {
  position: relative;
  display: grid;
  grid-template-columns: 22px 1fr auto auto;
  gap: 12px; align-items: center;
  padding: 13px 15px;
  background: var(--panel); /* solid fallback */
  background: linear-gradient(180deg, var(--panel-2), var(--panel)); /* subtle top sheen for depth */
  border: 1px solid var(--border);
  border-left: 3px solid var(--border);
  border-radius: var(--radius);
  transition: transform var(--dur-fast) var(--ease-out), border-color var(--dur-fast), box-shadow .22s var(--ease-out);
}
/* priority left rail — bolder + faint matching glow into the card */
.task.pri-high { border-left-color: var(--danger); }
.task.pri-med  { border-left-color: var(--warning); }
.task.pri-low  { border-left-color: var(--success); }
.task.pri-high::before, .task.pri-med::before, .task.pri-low::before {
  content: ''; position: absolute; left: 0; top: 0; bottom: 0; width: 40px; pointer-events: none;
  border-radius: var(--radius) 0 0 var(--radius); opacity: .5;
}
.task.pri-high::before { background: linear-gradient(90deg, rgba(239,79,90,.12), transparent); }
.task.pri-med::before  { background: linear-gradient(90deg, rgba(245,165,36,.12), transparent); }
.task.pri-low::before  { background: linear-gradient(90deg, rgba(62,207,142,.10), transparent); }
.task > * { position: relative; } /* keep content above the ::before glow */
.task:hover { border-color: var(--accent-line); }
@media (hover: hover) {
  .task:hover { transform: translateY(-2px); box-shadow: 0 10px 26px -14px rgba(0,0,0,.6), 0 2px 6px -3px rgba(0,0,0,.4); }
}
.task.done { opacity: .56; }
@media (hover: hover) { .task.done:hover { opacity: .85; } }
.task.done .title { text-decoration: line-through; color: var(--muted); }
.task.in-progress .title::before {
  content: ''; display: inline-block; width: 6px; height: 6px;
  border-radius: 50%; background: var(--warning);
  margin-right: 7px; vertical-align: middle;
  animation: doingPulse 2s ease-in-out infinite;
}
@keyframes doingPulse {
  0%, 100% { opacity: .7; }
  50% { opacity: 1; box-shadow: 0 0 0 4px rgba(245,165,36,.18); }
}
.task.selected {
  border-color: var(--primary);
  background: var(--primary-07);
  box-shadow: inset 3px 0 0 var(--primary);
}

.bulk-bar {
  display: none; align-items: center; gap: 8px;
  padding: 10px 14px; margin-bottom: 10px;
  background: linear-gradient(135deg, var(--primary-15), var(--accent-10));
  border: 1px solid var(--primary-40);
  border-radius: var(--radius-sm);
  animation: slidein .2s ease;
  flex-wrap: wrap;
}
.bulk-bar.show { display: flex; }
.bulk-count { font-weight: 600; margin-right: auto; font-size: 13px; }
.task .check {
  appearance: none; width: 18px; height: 18px; border-radius: 6px;
  border: 1.5px solid var(--border); background: var(--panel-2);
  cursor: pointer; position: relative;
  transition: transform .12s var(--ease-spring), background var(--dur-fast), border-color var(--dur-fast);
}
.task .check:hover { border-color: var(--success); }
.task .check:active { transform: scale(.85); }
.task .check:checked {
  background: var(--success); border-color: var(--success);
  animation: checkPop var(--dur-base) var(--ease-spring);
}
@keyframes checkPop { 0% { transform: scale(.7); } 55% { transform: scale(1.15); } 100% { transform: scale(1); } }
.task .check:hover { box-shadow: 0 0 0 3px var(--primary-12); }
.task .check:checked::after {
  content: "✓"; position: absolute; inset: 0; display: grid; place-items: center;
  color: white; font-size: 12px; font-weight: 700;
}
.task .title { font-weight: 600; font-size: 14px; letter-spacing: -.01em; }
.task .meta { color: var(--muted); font-size: 12px; display: flex; gap: 6px; flex-wrap: wrap; align-items: center; margin-top: 5px; line-height: 1.35; }
.task .tag {
  background: var(--primary-12); color: var(--primary-2);
  padding: 1px 8px; border-radius: 999px; font-size: 11px;
}
/* due date as a soft pill; overdue turns red */
.task .due {
  background: var(--panel-2); border: 1px solid var(--border);
  padding: 1px 8px; border-radius: 999px; font-variant-numeric: tabular-nums;
}
.task .due.overdue { background: rgba(239,79,90,.14); border-color: rgba(239,79,90,.38); color: #ff8c93; font-weight: 600; }
.task .actions { display: flex; gap: 4px; }
.icon-btn {
  background: transparent; border: 1px solid transparent; color: var(--muted);
  width: 28px; height: 28px; border-radius: 8px; cursor: pointer;
}
.icon-btn:hover { background: var(--panel-2); color: var(--text); }

/* KANBAN */
.kanban { display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px; }
.kanban-col {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  min-height: 380px;
  display: flex; flex-direction: column;
}
.kanban-head {
  display: flex; align-items: center; gap: 8px;
  padding: 12px 14px; border-bottom: 1px solid var(--border);
  font-weight: 600;
}
.kanban-head .count { margin-left: auto; color: var(--muted); font-weight: 400; font-size: 12px; }
.dot { width: 10px; height: 10px; border-radius: 50%; display: inline-block; }
.dot.blue { background: var(--primary); }
.dot.amber { background: var(--warning); }
.dot.green { background: var(--success); }
.kanban-body {
  padding: 10px; display: flex; flex-direction: column; gap: 8px; flex: 1;
  min-height: 100px;
}
.kanban-body.drop-hover { background: var(--primary-06); border-radius: 0 0 var(--radius) var(--radius); }
.kcard {
  background: var(--panel-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 10px 12px;
  cursor: grab;
}
.kcard.dragging { opacity: .55; transform: scale(1.03) rotate(1.2deg); box-shadow: 0 14px 32px rgba(124,92,255,.28); }

/* Kanban touch popover (long-press) */
.kanban-popover {
  position: fixed;
  z-index: 200;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 12px;
  box-shadow: 0 14px 36px rgba(0,0,0,.5);
  padding: 12px;
  min-width: 240px;
  max-width: 320px;
  animation: fade .12s ease;
}
.kanban-popover .kp-title {
  font-size: 13px; font-weight: 600;
  margin-bottom: 10px;
  overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap;
}
.kanban-popover .kp-row {
  display: flex; flex-direction: column; gap: 4px;
  margin-bottom: 6px;
}
.kanban-popover .kp-row:last-child {
  flex-direction: row; gap: 6px; margin-bottom: 0;
  border-top: 1px dashed var(--border); padding-top: 8px;
}
.kp-btn {
  background: var(--panel-2);
  border: 1px solid var(--border);
  color: var(--text);
  padding: 8px 12px;
  border-radius: 8px;
  font-size: 13px;
  cursor: pointer;
  text-align: left;
}
.kp-btn:hover { border-color: var(--primary); }
.kp-btn.active {
  background: var(--primary-18);
  border-color: var(--primary-50);
  color: var(--text);
}
.kp-btn.ghost { background: transparent; color: var(--muted); flex: 1; text-align: center; }
.kanban-popover .kp-row:last-child .kp-btn { flex: 1; text-align: center; }
.kcard .kt { font-weight: 600; margin-bottom: 4px; }
.kcard .km { color: var(--muted); font-size: 11px; display: flex; gap: 6px; flex-wrap: wrap; }

/* KB */
.kb-layout { display: grid; grid-template-columns: 280px 1fr; gap: 14px; min-height: 540px; }
.kb-list {
  background: var(--panel); border: 1px solid var(--border); border-radius: var(--radius);
  padding: 10px; overflow: auto; display: flex; flex-direction: column; gap: 6px;
}
.note-item {
  padding: 10px; border-radius: var(--radius-sm); border: 1px solid transparent;
  cursor: pointer;
}
.note-item:hover { background: var(--panel-2); }
.note-item.active { background: var(--panel-2); border-color: var(--primary-35); }
.note-item .nt { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.note-item .nm { color: var(--muted); font-size: 11px; }
.kb-editor {
  background: var(--panel); border: 1px solid var(--border); border-radius: var(--radius);
  padding: 14px; display: flex; flex-direction: column; gap: 10px;
}
.kb-meta { display: flex; gap: 12px; align-items: center; }
#note-body { min-height: 380px; resize: vertical; font-family: inherit; }

/* RULES */
.rules { display: flex; flex-direction: column; gap: 8px; }
.rule {
  display: grid; grid-template-columns: 1fr auto auto;
  gap: 10px; align-items: center;
  padding: 10px 12px; background: var(--panel-2);
  border: 1px solid var(--border); border-radius: var(--radius-sm);
}
.rule .rn { font-weight: 600; }
.rule .rd { color: var(--muted); font-size: 12px; margin-top: 2px; }
.switch {
  appearance: none; width: 38px; height: 22px; border-radius: 999px;
  background: var(--border); cursor: pointer; position: relative; transition: background .2s;
}
.switch:checked { background: var(--primary); }
.switch::after {
  content: ""; position: absolute; top: 2px; left: 2px;
  width: 18px; height: 18px; border-radius: 50%; background: white; transition: left .2s;
}
.switch:checked::after { left: 18px; }
.templates { display: flex; flex-wrap: wrap; gap: 8px; }
.tpl {
  background: var(--panel-2); border: 1px dashed var(--border);
  color: var(--text); padding: 8px 12px; border-radius: var(--radius-sm);
  cursor: pointer; font-size: 12px;
}
.tpl:hover { border-color: var(--primary); }

/* ASSISTANT */
.assistant { display: grid; grid-template-rows: 1fr auto auto; gap: 12px; min-height: calc(100vh - 200px); min-height: calc(100dvh - 200px); }
.chat {
  background: var(--panel); border: 1px solid var(--border); border-radius: var(--radius);
  padding: 14px; overflow: auto; min-height: 360px;
  max-height: calc(100vh - 320px); /* fallback */
  max-height: calc(100dvh - 320px);
  display: flex; flex-direction: column; gap: 10px;
}
.msg { display: flex; gap: 10px; align-items: flex-start; position: relative; }
.msg .av {
  width: 28px; height: 28px; border-radius: 8px;
  display: grid; place-items: center; font-size: 13px;
  color: #fff; flex-shrink: 0;
}
.msg.user .av { background: linear-gradient(135deg, #4b5b8d, #2c3554); }
.msg.ai .av { background: linear-gradient(135deg, var(--primary), var(--accent)); }
.bubble {
  background: var(--panel-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 10px 12px; max-width: 80%;
  word-wrap: break-word;
}
/* Inside an AI bubble, markdown-rendered <p> shouldn't add weird default margins */
.msg.ai .bubble p { margin: 0 0 .4em; }
.msg.ai .bubble p:last-child { margin-bottom: 0; }
.msg.ai .bubble pre { margin: .4em 0; }
.msg.ai .bubble ul, .msg.ai .bubble ol { margin: .2em 0 .4em; padding-left: 22px; }
.msg.user .bubble { white-space: pre-wrap; }

/* AI action result cards (rendered after the bubble) */
.ai-actions {
  display: flex; flex-direction: column; gap: 6px;
  margin-top: 8px;
  max-width: 80%;
}
.ai-action {
  display: grid; grid-template-columns: 28px 1fr auto;
  gap: 10px; align-items: center;
  padding: 8px 10px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 8px;
  font-size: 12.5px;
}
.ai-action.ok { border-color: rgba(62,207,142,.3); background: linear-gradient(135deg, rgba(62,207,142,.06), transparent); }
.ai-action.fail { border-color: rgba(245,165,36,.3); background: linear-gradient(135deg, rgba(245,165,36,.06), transparent); }
.ai-action[style*="cursor: pointer"]:hover {
  border-color: var(--primary);
  transform: translateX(2px);
  transition: all var(--dur-fast);
}
.aa-ico {
  width: 28px; height: 28px; border-radius: 6px;
  display: grid; place-items: center;
  background: var(--panel-2); color: var(--text);
  font-size: 14px;
}
.ai-action.ok .aa-ico { background: rgba(62,207,142,.18); color: #6ee0a8; }
.ai-action.fail .aa-ico { background: rgba(245,165,36,.18); color: #ffc266; }
.aa-body { min-width: 0; }
.aa-title { font-weight: 600; }
.aa-detail { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; margin-top: 2px; }
.aa-result { font-size: 11px; white-space: nowrap; }

.bubble.typing {
  position: relative; min-width: 50px;
}
.bubble.typing::after {
  content: ''; display: inline-block;
  width: 6px; height: 6px; border-radius: 50%;
  background: var(--muted);
  box-shadow: 12px 0 0 var(--muted), 24px 0 0 var(--muted);
  animation: typingDots 1s infinite;
  vertical-align: middle;
}
/* When the richer skeleton placeholder OR the signal-trace is showing, drop the dots (avoid double indicator). */
.bubble.typing:has(.skel-msg)::after,
.bubble.typing:has(.signal-trace)::after { content: none; }
@keyframes typingDots {
  0%, 60%, 100% { opacity: .3; }
  30% { opacity: 1; }
}
.msg.user .bubble { background: var(--primary-12); border-color: var(--primary-30); }
.suggestions { display: flex; flex-wrap: wrap; gap: 8px; }
.chip {
  background: var(--panel-2);
  border: 1px solid var(--border);
  color: var(--text);
  padding: var(--chip-pad); border-radius: var(--radius-pill); cursor: pointer; font-size: 12px;   /* P3B: unified interactive-chip padding (was 7px 11px) */
}
.chip:hover { border-color: var(--primary); }
.composer { display: grid; grid-template-columns: 1fr auto auto; gap: 8px; align-items: end; }
.composer-info { font-size: 11px; color: var(--muted); text-align: right; padding: 5px 2px 0; opacity: .85; user-select: none; }
.mic-btn, .mic-btn-small {
  cursor: pointer; transition: background .2s;
}
.mic-btn.listening, .mic-btn-small.listening {
  background: rgba(239,79,90,.2) !important;
  border-color: var(--danger) !important;
  color: var(--danger);
  animation: micPulse 1.2s ease-in-out infinite;
}
@keyframes micPulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(239,79,90,.5); }
  50% { box-shadow: 0 0 0 6px rgba(239,79,90,0); }
}
#chat-input { min-height: 56px; resize: vertical; font-family: inherit; }

/* FORM */
.form-row {
  display: grid; grid-template-columns: 140px 1fr; gap: 12px; align-items: center;
  padding: 10px 0; border-bottom: 1px dashed var(--border);
}
.form-row:last-child { border: 0; }
.form-row label { color: var(--muted); font-size: 13px; }
.data-actions { display: flex; gap: 8px; flex-wrap: wrap; }

/* MODAL */
.modal {
  position: fixed; inset: 0;
  background: rgba(0,0,0,.7);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  display: grid; place-items: center;
  padding: 16px; z-index: var(--z-modal);
  animation: fade var(--dur-fast) ease;
}
.modal[hidden] { display: none !important; }
@keyframes fade { from { opacity: 0; } to { opacity: 1; } }
.modal-card {
  width: min(560px, 100%);
  background: var(--panel); border: 1px solid var(--border);
  border-radius: var(--radius); box-shadow: var(--shadow);
  overflow: hidden;
  display: flex; flex-direction: column; max-height: 90dvh; /* head+foot fixed, body scrolls — never overflows viewport */
}
.modal-head, .modal-foot {
  display: flex; align-items: center; justify-content: space-between;
  padding: 14px 16px; border-bottom: 1px solid var(--border);
  flex: 0 0 auto;
}
.modal-foot { border-bottom: 0; border-top: 1px solid var(--border); }
.modal-head h3 { margin: 0; }
.x {
  background: transparent; border: 0; color: var(--muted); font-size: 16px; cursor: pointer;
  width: 34px; height: 34px; border-radius: 8px; display: inline-flex; align-items: center; justify-content: center;
}
.x:hover { background: var(--panel-2); color: var(--text); }
.x:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; }
/* Invisible expanded hit area: 34px visual stays, ~48px effective touch target.
   Clicks on a pseudo-element register on its parent — no JS needed. */
.x { position: relative; }
.x::after { content: ''; position: absolute; inset: -7px; }
.modal-body { padding: 14px 16px; display: flex; flex-direction: column; gap: 10px; flex: 1 1 auto; min-height: 0; overflow-y: auto; }
.modal-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.modal-grid .span-2 { grid-column: span 2; }

/* TAG SUGGEST in modal */
.tag-suggest {
  display: flex; flex-wrap: wrap; gap: 4px;
  margin-top: 6px; max-height: 60px; overflow: auto;
}
.tag-suggest .tg {
  background: var(--panel-2); border: 1px solid var(--border);
  padding: 2px 8px; border-radius: 999px;
  cursor: pointer; font-size: 11px; color: var(--muted);
}
.tag-suggest .tg:hover { background: var(--primary-15); color: var(--text); border-color: var(--primary); }

/* SUBTASKS in modal */
.subtasks-section {
  display: flex; flex-direction: column; gap: 8px;
  background: var(--panel-2); border: 1px solid var(--border);
  border-radius: var(--radius-sm); padding: 10px 12px;
  margin-top: 14px; /* match .deps-section / .links-section vertical rhythm */
}
.subtasks-head { display: flex; justify-content: space-between; align-items: center; }
.subtasks-head-actions { display: flex; align-items: center; gap: 10px; }
#m-subtask-ai-btn { white-space: nowrap; }
.deps-section { margin-top: 14px; }
.dep-chips { display: flex; flex-wrap: wrap; gap: 6px; margin: 6px 0; }
.dep-chip { display: inline-flex; align-items: center; gap: 6px; padding: 3px 6px 3px 10px; border-radius: 999px; background: var(--panel-2); border: 1px solid var(--border); font-size: 12px; }
.dep-chip.dep-done { opacity: .6; text-decoration: line-through; }
.dep-chip .dep-x { border: none; background: transparent; color: var(--muted); cursor: pointer; font-size: 15px; line-height: 1; padding: 0 2px; }
.dep-chip .dep-x:hover { color: var(--danger); }
.dep-select { width: 100%; }
.blocked-badge { color: var(--danger); font-size: 12px; }
.links-section { margin-top: 14px; }
.links-list { display: flex; flex-wrap: wrap; gap: 6px; margin: 6px 0; }
.link-chip { display: inline-flex; align-items: center; gap: 4px; padding: 3px 4px 3px 8px; border-radius: 8px; background: var(--panel-2); border: 1px solid var(--border); font-size: 12px; max-width: 100%; }
.link-chip-a { color: var(--primary); text-decoration: none; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 260px; }
.link-chip-a:hover { text-decoration: underline; }
.link-add { display: grid; grid-template-columns: 1fr 140px auto; gap: 6px; }
.link-pill { color: var(--primary); text-decoration: none; font-size: 12px; border-radius: 4px; padding: 0 3px; transition: background var(--dur-fast); }
.link-pill:hover { text-decoration: underline; background: var(--accent-soft); }
.streak-badge { font-size: 12px; color: #ff8a3d; font-weight: 600; }
.md-link-blocked { color: var(--danger); text-decoration: line-through dotted; cursor: not-allowed; }
/* D1 day timeline — tertiary full-width band below the bento */
.day-timeline-card { margin-top: var(--space-5); }
.day-timeline { display: flex; flex-direction: column; gap: 2px; }
.tl-row { display: grid; grid-template-columns: 54px 1fr; align-items: stretch; gap: 8px; }
.tl-when { font-variant-numeric: tabular-nums; color: var(--muted); font-size: 13px; padding-top: 9px; text-align: right; }
.tl-task { display: flex; align-items: center; gap: 8px; padding: 8px 10px; border-radius: 8px; border: 1px solid var(--border); background: var(--panel-2); cursor: pointer; transition: border-color var(--dur-fast), transform .05s; min-width: 0; }
.tl-task:hover { border-color: var(--primary); }
.tl-task:active { transform: scale(.995); }
.tl-row.tl-past .tl-task { opacity: .55; }
.tl-dot { width: 9px; height: 9px; border-radius: 50%; flex: 0 0 auto; }
.tl-title { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; flex: 1; min-width: 0; }
.tl-untimed-head { margin: 10px 0 4px; padding-left: 2px; text-transform: uppercase; letter-spacing: .04em; font-size: 11px; }
.tl-untimed { margin-left: 0; }
@media (max-width: 560px) { .tl-row { grid-template-columns: 46px 1fr; gap: 6px; } .tl-when { font-size: 12px; } }
@media (max-width: 560px) { .link-add { grid-template-columns: 1fr auto; } .link-add #m-link-label { grid-column: 1 / -1; } }
.subtasks-list { display: flex; flex-direction: column; gap: 4px; }
.subtask-item {
  display: flex; align-items: center; gap: 8px;
  padding: 4px 6px; border-radius: 6px;
}
.subtask-item:hover { background: rgba(255,255,255,.03); }
.subtask-item .sub-check {
  appearance: none; width: 16px; height: 16px; border-radius: 4px;
  border: 1.5px solid var(--border); background: transparent;
  cursor: pointer; position: relative; flex-shrink: 0;
}
.subtask-item .sub-check:checked { background: var(--success); border-color: var(--success); }
.subtask-item .sub-check:checked::after {
  content: "✓"; position: absolute; inset: 0; display: grid; place-items: center;
  color: white; font-size: 11px; font-weight: 700;
}
.subtask-item.done .sub-input { text-decoration: line-through; color: var(--muted); }
.sub-input {
  flex: 1; background: transparent !important; border: 0 !important;
  border-bottom: 1px solid transparent !important;
  padding: 4px 0 !important; color: var(--text); font-size: 13px;
  border-radius: 0 !important;
}
.sub-input:focus { border-bottom-color: var(--primary) !important; box-shadow: none !important; }
.sub-del {
  background: transparent; border: 0; color: var(--muted); cursor: pointer;
  width: 22px; height: 22px; border-radius: 6px; font-size: 14px;
}
.sub-del:hover { background: rgba(239,79,90,.15); color: var(--danger); }
.subtask-add { display: grid; grid-template-columns: 1fr auto; gap: 6px; }

/* progress badge */
.progress {
  background: rgba(62,207,142,.15); color: #6ee0a8;
  padding: 1px 7px; border-radius: 999px; font-size: 11px;
  font-variant-numeric: tabular-nums;
}
.progress.partial { background: rgba(245,165,36,.15); color: #ffc266; }
.recur-pill {
  background: var(--accent-15); color: #d8b4fe;
  padding: 1px 7px; border-radius: 999px; font-size: 11px;
}

/* tiny progress bar under task title */
.bar-thin {
  height: 4px; background: var(--border); border-radius: 999px;
  margin-top: 8px; overflow: hidden; max-width: 240px;
}
.bar-thin > i {
  display: block; height: 100%; border-radius: 999px;
  background: linear-gradient(90deg, var(--primary), var(--accent));
  transition: width var(--dur-slow) var(--ease-out);
}

/* TOASTS */
.toast-host {
  position: fixed; right: 16px; bottom: 16px; display: flex; flex-direction: column; gap: 8px; z-index: var(--z-toast);
}
.toast {
  background: var(--panel); border: 1px solid var(--border);
  border-radius: var(--radius-sm); padding: 10px 14px;
  box-shadow: var(--shadow);
  animation: slidein var(--dur-base) ease;
  transition: opacity .2s ease; /* smooth fade-out when opacity set to 0 */
  max-width: 360px;
}
.toast.success { border-color: rgba(62,207,142,.4); }
.toast.warn { border-color: rgba(245,165,36,.4); }
.toast.err, .toast.error { border-color: rgba(239,79,90,.4); }
.toast.info { border-color: var(--primary-40); }
.toast.update-toast { display: flex; align-items: center; gap: 10px; padding: 10px 14px; }
.render-error {
  background: rgba(239,79,90,.08);
  border: 1px solid rgba(239,79,90,.4) !important;
  margin-bottom: 14px;
  display: flex; flex-direction: column; gap: 6px;
}
.render-error strong { color: var(--danger); }

.offline-banner {
  background: linear-gradient(90deg, rgba(245,165,36,.2), rgba(239,79,90,.15));
  border-bottom: 1px solid rgba(245,165,36,.4);
  color: var(--text);
  text-align: center;
  padding: 8px 14px;
  font-size: 13px;
  position: sticky; top: 0; z-index: 6;
}
.offline-banner[hidden] { display: none !important; }
.ai-warn {
  background: rgba(245,165,36,.08);
  border-left: 2px solid rgba(245,165,36,.5);
  padding: 8px 10px;
  border-radius: 6px;
  margin: 0;
  font-size: 11.5px;
  line-height: 1.5;
}
#btn-test-ai[disabled] { cursor: wait; } /* opacity via unified button:disabled rule; wait-cursor signals in-progress */
@keyframes slidein { from { transform: translateY(10px); opacity: 0; } to { transform: translateY(0); opacity: 1; } }

/* POMODORO PILL */
.pomo-pill {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 7px 12px; border-radius: 999px;
  background: var(--panel); border: 1px solid var(--border);
  color: var(--text); cursor: pointer; font-size: 12px;
  font-variant-numeric: tabular-nums;
}
.pomo-pill:hover { border-color: var(--primary); }
.pomo-pill.running {
  background: linear-gradient(135deg, var(--primary-20), var(--accent-20));
  border-color: var(--primary-50);
}
.pomo-pill.break { background: rgba(62,207,142,.15); border-color: rgba(62,207,142,.4); }
.pomo-time { font-weight: 700; font-size: 13px; }
.pomo-phase { color: var(--muted); font-size: 11px; }
.pomo-pill.running .pomo-phase, .pomo-pill.break .pomo-phase { color: var(--text); }

/* CALENDAR */
.cal-weekdays {
  display: grid; grid-template-columns: repeat(7, 1fr); gap: 6px;
  margin-bottom: 6px; padding: 0 4px;
}
.cal-weekdays span { color: var(--muted); font-size: 11px; text-transform: uppercase; letter-spacing: 1px; padding: 4px; }
.cal-grid {
  display: grid; grid-template-columns: repeat(7, 1fr); gap: 6px;
  min-height: 60vh;
}
.cal-day {
  background: var(--panel); border: 1px solid var(--border);
  border-radius: var(--radius-sm); padding: 6px 8px;
  min-height: 88px; display: flex; flex-direction: column; gap: 4px;
  cursor: pointer; transition: border-color .12s, transform .05s;
  position: relative;
}
.cal-day:hover { border-color: var(--primary-40); }
.cal-day.dim { opacity: .4; }
.cal-day.today { border-color: var(--primary); box-shadow: inset 0 0 0 1px var(--primary-30); }
.cal-day.weekend { background: var(--panel-2); }
.cal-day .num { font-weight: 600; font-size: 13px; align-self: flex-end; }
.cal-day.today .num { color: var(--primary-2); }
.cal-tasks { display: flex; flex-direction: column; gap: 2px; flex: 1; overflow: hidden; }
.cal-tag {
  font-size: 10.5px; padding: 1px 5px; border-radius: 4px;
  background: var(--panel-2); border-left: 2px solid var(--primary);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.cal-tag.done { opacity: .55; text-decoration: line-through; border-left-color: var(--success); }
.cal-tag.overdue { border-left-color: var(--danger); }
.cal-tag.high { border-left-color: var(--danger); }
.cal-tag.med { border-left-color: var(--warning); }
.cal-tag.low { border-left-color: var(--success); }
.cal-more { font-size: 10.5px; color: var(--muted); padding: 1px 5px; }

/* COMMAND PALETTE */
.palette-modal { align-items: flex-start; padding-top: 12vh; background: rgba(0,0,0,.55); }
.palette {
  width: min(640px, 100%);
  background: var(--panel); border: 1px solid var(--border);
  border-radius: var(--radius); box-shadow: 0 20px 60px rgba(0,0,0,.5);
  overflow: hidden; display: flex; flex-direction: column;
}
#palette-input {
  background: var(--panel) !important; border: 0 !important;
  border-bottom: 1px solid var(--border) !important;
  border-radius: 0 !important;
  padding: 16px 18px !important; font-size: 15px !important;
  outline: none !important;
}
.palette-results { max-height: 56vh; overflow: auto; padding: 6px; }
.palette-item {
  display: flex; align-items: center; gap: 10px;
  padding: 9px 12px; border-radius: var(--radius-sm); cursor: pointer;
}
.palette-item.active { background: var(--panel-2); border: 1px solid var(--primary-35); }
.palette-item:hover { background: var(--panel-2); }
.palette-ico {
  width: 26px; height: 26px; border-radius: 7px; flex-shrink: 0;
  background: var(--panel-2); display: grid; place-items: center;
  color: var(--muted); font-size: 13px;
}
.palette-item .ptxt { flex: 1; min-width: 0; }
.palette-item .pt { font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.palette-item .ps { color: var(--muted); font-size: 11px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.palette-item .pkind {
  font-size: 10px; padding: 2px 7px; border-radius: 999px;
  background: var(--panel-2); color: var(--muted); border: 1px solid var(--border);
}
.palette-section {
  padding: 8px 12px 4px; color: var(--muted);
  font-size: 11px; text-transform: uppercase; letter-spacing: 1px;
}
.palette-foot {
  display: flex; gap: 14px; padding: 10px 16px;
  border-top: 1px solid var(--border);
}

/* KB toggle / preview / backlinks / markdown */
.kb-toggle { display: inline-flex; background: var(--panel-2); border: 1px solid var(--border); border-radius: 999px; padding: 2px; }
.seg {
  background: transparent; color: var(--muted); border: 0;
  padding: 5px 12px; border-radius: 999px; cursor: pointer; font-size: 12px;
}
.seg.active { background: var(--panel); color: var(--text); box-shadow: 0 1px 3px rgba(0,0,0,.2); }

.markdown-view {
  min-height: 380px; padding: 14px 16px;
  background: var(--panel-2); border: 1px solid var(--border);
  border-radius: var(--radius-sm); overflow: auto;
  font-size: 14px; line-height: 1.65;
}
.markdown-view h1, .markdown-view h2, .markdown-view h3 { margin: .8em 0 .4em; line-height: 1.25; }
.markdown-view h1 { font-size: 22px; border-bottom: 1px solid var(--border); padding-bottom: 4px; }
.markdown-view h2 { font-size: 18px; }
.markdown-view h3 { font-size: 15px; color: var(--primary-2); }
.markdown-view p { margin: .4em 0; }
.markdown-view code {
  background: var(--primary-12); color: var(--primary-2);
  padding: 1px 6px; border-radius: 4px; font-size: .92em;
  font-family: ui-monospace, monospace;
}
.markdown-view pre {
  background: var(--bg); border: 1px solid var(--border);
  padding: 10px 12px; border-radius: var(--radius-sm); overflow: auto;
}
.markdown-view pre code { background: transparent; color: var(--text); padding: 0; }
.markdown-view blockquote {
  border-left: 3px solid var(--primary);
  padding: 4px 12px; margin: .5em 0; color: var(--muted);
  background: var(--primary-05);
}
.markdown-view ul, .markdown-view ol { padding-left: 22px; margin: .4em 0; }
.markdown-view li { margin: 2px 0; }
.markdown-view a { color: var(--primary-2); text-decoration: none; }
.markdown-view a:hover { text-decoration: underline; }
.markdown-view hr { border: 0; border-top: 1px solid var(--border); margin: 1em 0; }
.wikilink {
  background: var(--accent-15); color: #d8b4fe;
  padding: 1px 6px; border-radius: 4px; cursor: pointer;
  border-bottom: 1px dashed var(--accent-50);
}
.wikilink:hover { background: var(--accent-30); }
.wikilink.broken { background: rgba(239,79,90,.12); color: #ff8c93; border-bottom-color: rgba(239,79,90,.5); }

.kb-backlinks {
  border-top: 1px dashed var(--border);
  padding-top: 10px; margin-top: 4px;
  display: flex; flex-direction: column; gap: 4px;
}
.kb-backlinks .bl-title { color: var(--muted); font-size: 11px; text-transform: uppercase; letter-spacing: 1px; }
.kb-backlinks .bl-item {
  font-size: 12px; padding: 4px 8px; border-radius: 6px;
  background: var(--panel-2); cursor: pointer;
  display: flex; gap: 6px; align-items: center;
}
.kb-backlinks .bl-item:hover { background: var(--primary-12); }
.kb-backlinks .bl-kind { font-size: 10px; color: var(--muted); }

/* STATS */
.chart-30 { display: grid; grid-template-columns: repeat(30, 1fr); gap: 3px; height: 160px; align-items: end; padding-top: 14px; }
.chart-30 .bar-wrap { display: flex; flex-direction: column; align-items: center; gap: 4px; height: 100%; justify-content: end; }
.chart-30 .bar { width: 100%; background: var(--primary); border-radius: 3px 3px 0 0; min-height: 3px; }
.chart-30 .bar-label { display: none; }

.hbars { display: flex; flex-direction: column; gap: 10px; padding: 6px 0; }
.hb-row { display: grid; grid-template-columns: 80px 1fr 40px; gap: 10px; align-items: center; }
.hb-track { background: var(--border); height: 10px; border-radius: 5px; overflow: hidden; }
.hb-fill { height: 100%; border-radius: 5px; }
.hb-fill.high { background: var(--danger); }
.hb-fill.med { background: var(--warning); }
.hb-fill.low { background: var(--success); }
.hb-val { text-align: right; color: var(--muted); font-variant-numeric: tabular-nums; }

/* HEATMAP */
.heatmap {
  display: grid; grid-template-columns: repeat(13, 1fr); gap: 4px;
  padding: 8px 0;
}
.heat-week { display: grid; grid-template-rows: repeat(7, 1fr); gap: 4px; }
.heat-cell {
  width: 100%; aspect-ratio: 1; border-radius: 3px;
  background: var(--panel-2);
  border: 1px solid var(--border);
}
.heat-cell.l1 { background: var(--primary-25); border-color: var(--primary-30); }
.heat-cell.l2 { background: var(--primary-50); border-color: var(--primary-55); }
.heat-cell.l3 { background: var(--primary-75); border-color: var(--primary-80); }
.heat-cell.l4 { background: var(--primary); border-color: var(--primary); }

/* PROJECT STATS */
.proj-stats { display: flex; flex-direction: column; gap: 10px; }
.ps-row { display: grid; grid-template-columns: 18px 1fr auto; gap: 10px; align-items: center; }
.ps-row .pdot { width: 12px; height: 12px; border-radius: 50%; }
.ps-row .pname { font-size: 13px; }
.proj-stats .ptrack { background: var(--border); height: 6px; border-radius: 3px; overflow: hidden; margin-top: 4px; }
.proj-stats .pfill { height: 100%; }
.ps-row .pinfo { color: var(--muted); font-size: 11px; font-variant-numeric: tabular-nums; }

.tag-cloud { display: flex; flex-wrap: wrap; gap: 8px; }
.tag-cloud .t {
  background: var(--panel-2); border: 1px solid var(--border);
  padding: 4px 10px; border-radius: 999px; cursor: pointer;
  display: inline-flex; gap: 6px; align-items: center;
}
.tag-cloud .t:hover { border-color: var(--primary); }
.tag-cloud .t .n { color: var(--muted); font-size: 11px; }

/* HELP OVERLAY */
.help-body { display: grid; grid-template-columns: 1fr 1fr; gap: 8px 24px; }
.kb-row { display: flex; align-items: center; gap: 10px; padding: 6px 0; }
.kb-row span { color: var(--muted); font-size: 13px; }
kbd {
  background: var(--panel-2); border: 1px solid var(--border);
  border-bottom-width: 2px; border-radius: 5px;
  padding: 2px 7px; font-size: 11px; font-family: ui-monospace, monospace;
  color: var(--text); box-shadow: 0 1px 0 rgba(0,0,0,.2);
}

/* WIKILINK AUTOCOMPLETE POPUP */
.kb-editor { position: relative; }
.wiki-pop {
  position: absolute;
  left: 14px; right: 14px;
  max-height: 240px; overflow: auto;
  background: var(--panel);
  border: 1px solid var(--primary-50);
  border-radius: var(--radius-sm);
  box-shadow: 0 12px 36px rgba(0,0,0,.45);
  z-index: 20;
  display: none;
}
.wiki-pop.show { display: block; }
.wiki-pop-head {
  padding: 6px 12px; color: var(--muted); font-size: 11px;
  text-transform: uppercase; letter-spacing: 1px;
  border-bottom: 1px solid var(--border);
}
.wiki-pop-item {
  display: flex; gap: 10px; align-items: center;
  padding: 8px 12px; cursor: pointer;
}
.wiki-pop-item:hover, .wiki-pop-item.active { background: var(--panel-2); }
.wiki-pop-kind {
  width: 22px; height: 22px; border-radius: 6px;
  display: grid; place-items: center;
  background: var(--panel-2); color: var(--muted); font-size: 12px;
  flex-shrink: 0;
}
.wiki-pop-title { font-size: 13px; flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.wiki-pop-create {
  color: var(--primary-2);
  border-top: 1px dashed var(--border);
}

/* CONTEXT MENU (right-click on task) */
.ctx-menu {
  position: fixed;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  box-shadow: 0 14px 40px rgba(0,0,0,.5);
  padding: 4px;
  min-width: 220px;
  z-index: 200;
  animation: fade .12s ease;
}
.ctx-item {
  padding: 7px 12px; border-radius: 6px;
  cursor: pointer; font-size: 13px;
  display: flex; align-items: center; gap: 8px;
  color: var(--text);
}
.ctx-item:hover { background: var(--panel-2); }
.ctx-item.danger { color: var(--danger); }
.ctx-item.danger:hover { background: rgba(239,79,90,.12); }
.ctx-sep { height: 1px; background: var(--border); margin: 4px 6px; }
.ctx-label { padding: 6px 12px 2px; font-size: 11px; text-transform: uppercase; letter-spacing: .04em; color: var(--muted); }
.ctx-row { justify-content: space-between; gap: 4px; padding-right: 6px; }
.ctx-row-label { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ctx-row-x { border: none; background: transparent; color: var(--muted); cursor: pointer; font-size: 16px; line-height: 1; padding: 0 4px; border-radius: 4px; }
.ctx-row-x:hover { color: var(--danger); background: rgba(239,79,90,.12); }
.ctx-menu { max-height: 70vh; overflow-y: auto; }

/* POMO SESSIONS CARD */
.pomo-sessions { display: flex; gap: 12px; align-items: center; flex-wrap: wrap; }
.pomo-sessions .ps-stat {
  display: flex; flex-direction: column; gap: 2px;
  background: var(--panel-2); border: 1px solid var(--border);
  border-radius: var(--radius-sm); padding: 10px 14px;
}
.pomo-sessions .ps-num { font-size: 20px; font-weight: 700; }
.pomo-sessions .ps-label { color: var(--muted); font-size: 11px; }

/* INLINE SUBTASKS in task list */
.progress.clickable { cursor: pointer; user-select: none; }
.progress.clickable:hover { filter: brightness(1.15); }
.inline-subtasks {
  background: var(--panel-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 8px 12px;
  margin: -4px 0 4px 38px;
  display: flex; flex-direction: column; gap: 2px;
}
.inline-sub {
  display: flex; align-items: center; gap: 8px;
  padding: 3px 4px; border-radius: 5px;
}
.inline-sub:hover { background: rgba(255,255,255,.03); }
.inline-sub .sub-title { flex: 1; font-size: 13px; }
.inline-sub .sub-title.done { text-decoration: line-through; color: var(--muted); }
.inline-sub-add {
  background: transparent !important; border: 0 !important;
  border-top: 1px dashed var(--border) !important;
  border-radius: 0 !important;
  padding: 6px 4px !important; color: var(--text); font-size: 12px;
  margin-top: 4px;
}
.inline-sub-add:focus { border-top-color: var(--primary) !important; box-shadow: none !important; }

/* TIME TRACKING */
.timer-btn {
  background: transparent; border: 1px solid transparent; color: var(--muted);
  padding: 2px 7px; border-radius: 6px; cursor: pointer; font-size: 11px;
  display: inline-flex; gap: 4px; align-items: center;
  font-variant-numeric: tabular-nums;
}
.timer-btn:hover { background: var(--panel-2); color: var(--text); border-color: var(--border); }
.timer-btn.running { background: rgba(239,79,90,.12); color: #ff8c93; border-color: rgba(239,79,90,.3); }
.timer-btn.has-time { color: var(--text); }

.burger { display: none; padding: 6px 12px; font-size: 18px; }

/* FOCUS MODE — subtle dim of sidebar during Pomodoro */
body.focus-mode .sidebar {
  opacity: .45;
  transition: opacity var(--dur-base);
}
body.focus-mode .sidebar:hover { opacity: 1; }
body.focus-mode .topbar {
  background: linear-gradient(180deg, var(--primary-06), transparent),
              color-mix(in oklab, var(--bg), transparent 10%);
  box-shadow: inset 0 -1px 0 var(--primary-20);
}

.streak-chip {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 6px 12px; border-radius: 999px;
  background: linear-gradient(135deg, rgba(245,165,36,.2), rgba(239,79,90,.2));
  border: 1px solid rgba(245,165,36,.4);
  color: var(--text); font-size: 13px;
}
.streak-chip strong { font-size: 14px; }

/* ACCENT PICKER */
.accent-picker { display: flex; gap: 8px; flex-wrap: wrap; }
.accent-swatch {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 6px 12px; border-radius: 999px;
  border: 1.5px solid transparent;
  background: var(--panel-2);
  cursor: pointer; font-size: 12px;
}
.accent-swatch:hover { background: var(--panel); }
.accent-swatch.active { border-color: var(--text); background: var(--panel); }
.accent-swatch .ad { width: 14px; height: 14px; border-radius: 50%; }

/* INLINE TITLE EDIT */
.inline-title-edit {
  background: var(--bg) !important; border: 1px solid var(--primary) !important;
  padding: 4px 8px !important; border-radius: 6px !important;
  color: var(--text); font-weight: 600; width: 100%;
  outline: none; font-size: inherit;
}

/* PRINT */
@media print {
  .sidebar, .topbar, .actions, .filters, .smart-lists, .bulk-bar,
  .page-actions, .toast-host, .ctx-menu, .modal, .sidebar-backdrop, .nav,
  #bulk-bar, .pomo-pill, .palette-modal { display: none !important; }
  body { background: white !important; color: black !important; }
  .main { padding: 0 !important; }
  .view { padding: 0 !important; }
  .card, .task, .kcard, .note-item {
    background: white !important;
    border: 1px solid #ccc !important;
    color: black !important;
    box-shadow: none !important;
    break-inside: avoid;
  }
  .task .check, .icon-btn, .timer-btn { display: none !important; }
  h1, h2, h3 { color: black !important; }
}

/* RESPONSIVE */
@media (max-width: 980px) {
  .app { grid-template-columns: 1fr; }
  .sidebar {
    position: fixed; top: 0; left: 0; height: 100vh; width: 280px; z-index: var(--z-modal); /* shares the modal layer (60) so a modal opened over the drawer still overlays it */
    height: 100dvh; /* keep .sidebar-foot above iPhone home-indicator */
    transform: translateX(-100%); transition: transform .2s ease;
    flex-direction: column; box-shadow: 8px 0 30px rgba(0,0,0,.4);
    padding-top: max(18px, env(safe-area-inset-top));
    padding-bottom: max(18px, env(safe-area-inset-bottom));
  }
  .sidebar.open { transform: translateX(0); }
  .sidebar-foot { display: flex; }
  .nav { flex-direction: column; }
  .nav-item { flex: initial; }
  .burger { display: inline-flex; }
  .grid.kpis { grid-template-columns: repeat(2, 1fr); }
  .grid.two-col { grid-template-columns: 1fr; }
  .kanban { grid-template-columns: 1fr; }
  .kb-layout { grid-template-columns: 1fr; }
  .filters { grid-template-columns: 1fr 1fr; }
  .help-body { grid-template-columns: 1fr; }
  .pomo-phase { display: none; }
  .cal-day { min-height: 64px; }
  .chart-30 { grid-template-columns: repeat(15, 1fr); }
  .heatmap { grid-template-columns: repeat(13, 1fr); }
  .sidebar-backdrop {
    position: fixed; inset: 0; background: rgba(0,0,0,.5); z-index: 55;
    display: none;
  }
  .sidebar-backdrop.show { display: block; }
}

/* Tablet (601–980px): kanban gets 2 columns instead of jumping 3→1.
   The 3rd column wraps onto a second row. This block is placed AFTER the
   max-width:980px rule above so, at equal specificity, source order wins in
   the 601–980 overlap and the single-column rule (L~1893) is overridden. */
@media (min-width: 601px) and (max-width: 980px) {
  .kanban { grid-template-columns: repeat(2, 1fr); }
}

/* ============================================================
   PHONE-SIZE (<=600px) and TOUCH (no hover) tuning
   ============================================================ */
@media (max-width: 600px) {
  /* iOS Safari auto-zooms inputs < 16px — prevent that */
  input, textarea, select { font-size: 16px !important; }
  .view { padding: 14px; }
  .page-head { flex-direction: column; align-items: flex-start; gap: 8px; }
  .page-head h1 { font-size: 22px; }   /* P3B: single mobile heading size (was 20px here, 22px later — unified to 22px) */
  .page-head > div > p.muted { display: none; } /* drop the filler subtitle on phones — content starts higher */
  /* Toolbar scrolls sideways instead of wrapping into a cramped block */
  .page-actions { flex-wrap: nowrap; overflow-x: auto; -webkit-overflow-scrolling: touch; width: 100%; padding-bottom: 4px; scrollbar-width: none; }
  .page-actions::-webkit-scrollbar { display: none; }
  .page-actions .btn { flex-shrink: 0; white-space: nowrap; }
  /* Subtle right-edge fade — affordance that the toolbar scrolls sideways
     (scrollbar is hidden, so otherwise there is zero hint) */
  .page-actions {
    -webkit-mask-image: linear-gradient(90deg, #000 calc(100% - 28px), transparent);
    mask-image: linear-gradient(90deg, #000 calc(100% - 28px), transparent);
  }

  .topbar { gap: 6px; padding: 8px 10px; padding-top: max(8px, env(safe-area-inset-top)); }
  .topbar #btn-cmd, .topbar #btn-help, .topbar #btn-toggle-theme, .topbar .status-dot { display: none; }
  .topbar #btn-quick-add { padding: 8px 10px; font-size: 12px; }
  .pomo-pill { padding: 6px 9px; }

  /* Task row: hide separate priority pill and status text (priority shown as left border) */
  .task {
    grid-template-columns: 24px 1fr auto;
    padding: 10px 12px;
    border-left-width: 3px;
    border-left-style: solid;
    border-left-color: var(--border);
  }
  .task.pri-high { border-left-color: var(--danger); }
  .task.pri-med  { border-left-color: var(--warning); }
  .task.pri-low  { border-left-color: var(--success); }
  .task > .pill, .task > .status { display: none; }
  .task .actions { gap: 6px; }

  /* Bigger touch targets */
  .task .check { width: 22px; height: 22px; border-radius: 7px; }
  /* Invisible hit-area expansion → ~40px effective target. ::after is taken by the
     ✓ checkmark, so ::before carries the expansion (.task .check is already
     position:relative). -9px keeps 5px clear of the title column (12px grid gap). */
  .task .check::before { content: ''; position: absolute; inset: -9px; }
  .icon-btn { width: 36px; height: 36px; font-size: 15px; position: relative; }
  /* Same trick for icon buttons: ~44px effective hit, visuals stay 36px so
     timer + 3 buttons still fit a 320px task row */
  .icon-btn::after { content: ''; position: absolute; inset: -4px; }
  .timer-btn { padding: 7px 11px; min-height: 32px; font-size: 12px; }
  .chip, .chip.smart { padding: 8px 12px; font-size: 12px; }

  /* Filters: stack into single column for clarity */
  .filters { grid-template-columns: 1fr 1fr; }
  .filters select, .filters input { padding: 11px 12px; font-size: 14px; }
  .smart-lists { gap: 6px; overflow-x: auto; flex-wrap: nowrap; padding-bottom: 4px; }
  .smart-lists::-webkit-scrollbar { display: none; }
  .chip.smart { white-space: nowrap; flex-shrink: 0; }

  /* Modals: full-width bottom-sheet */
  .modal-card { width: 100%; max-width: none; border-radius: 14px 14px 0 0; align-self: flex-end; min-height: 50vh; }
  /* Bottom-sheet slide-up entry (replaces desktop popIn on phones). Only transform+opacity
     animate — the keyboard-aware max-height/min-height (--vvh) are untouched, so the sticky
     footer logic is unaffected (animation finishes at translateY(0)/scale(1)). */
  .modal .modal-card { animation: sheetUp var(--dur-base) var(--ease-out) both; }
  @keyframes sheetUp {
    from { opacity: 0; transform: translateY(100%); }
    to   { opacity: 1; transform: translateY(0); }
  }
  /* Keyboard-aware height: --vvh mirrors visualViewport.height (set in app.js).
     dvh does NOT shrink when the on-screen keyboard opens, but --vvh does —
     the sheet stays above the keyboard and the sticky footer remains reachable.
     min-height must yield too: min-height beats max-height, so an unconditional
     50vh floor would override the cap once the keyboard eats > half the screen. */
  .modal-card {
    max-height: min(90dvh, calc(var(--vvh, 100dvh) - 8px));
    min-height: min(50vh, calc(var(--vvh, 100dvh) - 8px));
  }
  .modal { padding: 0; align-items: flex-end !important; }
  .palette-modal .palette { border-radius: 14px 14px 0 0; padding-bottom: max(8px, env(safe-area-inset-bottom)); }
  /* flex:1 inside the 90dvh card handles height — explicit max-height would fight it and leave a gap */
  .modal-body { max-height: none; }
  /* Save/Cancel row clears iPhone home-indicator */
  .modal-foot { padding-bottom: max(14px, calc(14px + env(safe-area-inset-bottom))); }
  .modal-grid { grid-template-columns: 1fr; }
  .modal-grid .span-2 { grid-column: auto; }
  .help-body { grid-template-columns: 1fr; }
  .palette-modal { padding-top: 8vh; align-items: flex-start !important; }
  .palette-modal .palette { align-self: stretch; min-height: 0; max-height: 80vh; }

  /* Calendar: more readable */
  .cal-day { padding: 4px 5px; min-height: 56px; }
  .cal-day .num { font-size: 11px; }
  .cal-tag { font-size: 9.5px; padding: 0 3px; }
  .cal-weekdays span { font-size: 9px; padding: 2px; }

  /* Stats charts */
  .chart-30 { grid-template-columns: repeat(15, 1fr); }
  .heatmap { grid-template-columns: repeat(7, 1fr); }

  /* Quick-add: bigger */
  .quick-add { padding: 4px 12px; }
  #quick-add-input { font-size: 15px; padding: 12px 0 !important; }
  .qa-hint { display: none; }

  /* Bulk-bar: stack */
  .bulk-bar { padding: 10px; }
  .bulk-bar .btn { flex: 1; min-width: 100px; }

  /* Form rows compact */
  .form-row { grid-template-columns: 1fr; gap: 6px; padding: 8px 0; }

  /* Goal row */
  .goal-row { grid-template-columns: 28px 1fr auto; padding: 12px; }

  /* KB list height limited so editor visible */
  .kb-list { max-height: 200px; }
  #note-body { min-height: 240px; }
  .markdown-view { min-height: 240px; }

  /* Toasts: bottom + safe area */
  .toast-host { right: 10px; left: 10px; bottom: max(10px, env(safe-area-inset-bottom)); }
  .toast { max-width: none; }

  /* Pomodoro pill collapsed text */
  .pomo-time { font-size: 12px; }
}

/* TOUCH devices specific (no hover, coarse pointer) */
@media (hover: none) and (pointer: coarse) {
  .icon-btn { min-width: 36px; min-height: 36px; }
  .check { min-width: 22px; min-height: 22px; }
  .timer-btn { min-height: 32px; min-width: 32px; }
  .sub-check { min-width: 20px; min-height: 20px; }
  .switch { width: 44px; height: 26px; }
  .switch::after { width: 22px; height: 22px; }
  .switch:checked::after { left: 20px; }
  .nav-item { padding: 12px 14px; }
  .palette-item { padding: 12px 14px; }
  .ctx-item { padding: 11px 14px; }
}

/* ============================================================
   REDESIGN v22 — type, depth, glass, motion
   (appended so it overrides earlier rules by source order)
   ============================================================ */

/* --- TYPOGRAPHY: display font + tighter, heavier headings --- */
.brand-title,
.page-head h1,
.gate-card h1,
.kpi-value,
.welcome-body h2,
.modal-head h3,
.markdown-view h1,
.markdown-view h2 {
  font-family: var(--font-display);
  font-weight: 600;
}
.page-head h1 {
  font-size: 30px;
  line-height: 1.1;
  letter-spacing: -.02em;   /* negative tracking on large display type */
  font-weight: 700;
  text-wrap: balance;
}
.brand-title { font-size: 17px; letter-spacing: -.01em; }
.kpi-value {
  font-size: 32px;
  letter-spacing: -.02em;
  font-variant-numeric: tabular-nums;
}
.gate-card h1 { font-size: 26px; letter-spacing: -.02em; font-weight: 700; }
.card-head h3 { letter-spacing: -.005em; }
p, .muted, .task .meta { text-wrap: pretty; }

/* ============================================================
   P3B — TYPOGRAPHY POLISH (appended → wins by source order)
   (a) tabular-nums on every numeric display so digits align in columns,
   (b) text-wrap balance on the remaining headings + pretty on more prose,
   (c) a 500-weight tier for subtle label/subtitle hierarchy.
   No sizes/colors change — alignment + wrapping + weight only.
   ============================================================ */

/* (a) tabular-nums — KPI deltas, count badges, calendar day numbers, session
   counters, timestamps, chart labels, project counts. (Big timers/timeline times
   already had it; this covers the spots the inventory flagged as missing.) */
.kpi-sub,
.kpi-trend,
.proj-count,
.badge,
.sl-count,
.cal-day .num,
.hist-time,
.hist-meta,
.sess-meta,
.bar-label,
.pomo-time,
.pomo-sessions .ps-num,
.tl-time {            /* activity-feed relative timestamps ("5 мин назад") */
  font-variant-numeric: tabular-nums;
}

/* (b) text-wrap: balance on the headings that weren't covered (page-head h1 already
   balances at :2066). Keeps ragged-but-even multi-line headings; pretty on more prose. */
.gate-card h1,
.welcome-body h2,
.modal-head h3,
.markdown-view h1,
.markdown-view h2,
.empty-state h3,
.card-head h3 {
  text-wrap: balance;
}
.empty-state p,
.gate-blurb,
.kpi-sub {
  text-wrap: pretty;
}

/* (c) a subtle 500 weight tier — for subtitles/meta labels where 400-vs-700 was too
   binary. Tasteful: card subtitles, KPI sub-labels, section eyebrows, empty-state copy.
   (Elements that are already 600/700 are left alone — this only lifts plain 400 text.) */
.page-head > div > p.muted,
.kpi-label,
.kpi-sub,
.empty-state p {
  font-weight: 500;
}

/* Constrain ultra-wide screens so content doesn't stretch edge-to-edge.
   ~1400px keeps content comfortably readable on 1440+ displays while still
   leaving usable width; centered via margin-inline. Lives on .view (inside
   .main), so the .app sidebar+main grid is untouched. */
.view { max-width: 1400px; margin-inline: auto; width: 100%; }

/* --- DEPTH: layered shadows + tonal card edges --- */
.card { box-shadow: var(--shadow-2); }
.kpi-value.success { color: var(--success); }

/* Tonal (single-hue) gradient for the logo instead of blue→purple rainbow */
.logo, .welcome-emoji, .gate-logo .logo, .msg.ai .av {
  background: linear-gradient(150deg,
    color-mix(in oklab, var(--primary) 92%, #fff 0%),
    color-mix(in oklab, var(--accent) 70%, #000 14%));
  box-shadow: var(--glow);
}

/* --- GLASS: refined frosted surfaces (topbar / modal / palette / context) --- */
.topbar {
  background: color-mix(in oklab, var(--bg), transparent 28%);
  backdrop-filter: blur(16px) saturate(1.4);
  -webkit-backdrop-filter: blur(16px) saturate(1.4);
  box-shadow: inset 0 -1px 0 var(--border);
}
.modal { background: color-mix(in oklab, #07060c, transparent 28%); }
.modal-card, .palette, .ctx-menu, .kanban-popover {
  box-shadow:
    var(--shadow-3),
    inset 0 1px 0 color-mix(in oklab, #fff 8%, transparent);   /* top edge highlight = glass refraction */
  backdrop-filter: blur(8px) saturate(1.2);
  -webkit-backdrop-filter: blur(8px) saturate(1.2);
}

/* --- List stagger entry (view-enter only; gated by .stagger-in class added in JS) --- */
/* Plays once when a list view is freshly entered. Transform+opacity only (GPU). The
   per-item delay is set inline (style.animationDelay) and capped in JS so long lists
   don't lag. animation-fill-mode:backwards keeps items hidden until their delay starts. */
.stagger-in { animation: staggerItem .34s var(--ease-out) backwards; }
@keyframes staggerItem {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: translateY(0); }
}
@media (prefers-reduced-motion: reduce) {
  .stagger-in { animation: none; }
}

/* --- MOTION: view-enter, hover-lift, springy buttons --- */
.view.active { animation: viewIn var(--dur-slow) var(--ease-out) both; }
@keyframes viewIn {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* Swipe-nav: directional horizontal slide on the incoming view. Overrides the
   plain viewIn (same specificity, later source order wins) so swipe gives a
   left/right cue while a bottom-nav tap keeps the vertical fade. The class is
   removed on animationend (JS); reduced-motion is handled by the global rule
   below + JS skips the class add entirely. overflow-x:clip prevents the
   off-screen start frame from flashing a horizontal scrollbar. */
.view.view-swipe-in-right { animation: swipeInRight var(--dur-base) var(--ease-out) both; overflow-x: clip; }
.view.view-swipe-in-left  { animation: swipeInLeft  var(--dur-base) var(--ease-out) both; overflow-x: clip; }
@keyframes swipeInRight {
  from { opacity: 0; transform: translateX(24px); }
  to   { opacity: 1; transform: translateX(0); }
}
@keyframes swipeInLeft {
  from { opacity: 0; transform: translateX(-24px); }
  to   { opacity: 1; transform: translateX(0); }
}

.card, .kcard, .goal-row, .note-item, .project-item {
  transition: transform .18s var(--ease-spring),
              border-color .18s var(--ease-out),
              box-shadow .18s var(--ease-out);
}
/* --- Phase 4B: ONE coherent hover language, gated behind @media(hover:hover) ---
   CARDS lift + shadow + accent edge; ROWS (list-like) get a subtle -1px nudge +
   accent edge so the whole family feels related but cards stay the strongest.
   Gating behind hover:hover means touch devices never get stuck hover states. */
@media (hover: hover) {
  /* Cards — the dominant lift */
  .card:hover  { transform: translateY(-3px); box-shadow: var(--shadow-3); border-color: var(--accent-line); }
  .kcard:hover { transform: translateY(-2px); box-shadow: var(--shadow-2); border-color: var(--accent-line); }
  .cstack-card:hover { transform: translateY(-2px); box-shadow: var(--shadow-2); border-color: var(--accent-line); }
  /* Rows — the lighter, related treatment (were bg-only / inconsistent before).
     .project-item & .note-item already paid the lift-transition cost at the
     group rule above but had no payoff; give them the unified row nudge. */
  .goal-row:hover     { transform: translateY(-1px); border-color: var(--accent-line); }
  .project-item:hover { transform: translateY(-1px); }
  .note-item:hover    { transform: translateY(-1px); }
}

/* --- Phase 5A: SPOTLIGHT BORDER (desktop pointer only) ---
   A faint iris glow that follows the cursor along a card's border. JS (csSpotlight)
   writes --mx/--my (in %) on the hovered .card; the ::after paints a radial-gradient
   that is mask-clipped to a 1px-thick border ring, so only the edge near the cursor
   lights up. pointer-events:none keeps it click-safe; opacity 0→1 on :hover. Gated to
   (hover:hover) + (min-width:981px) so touch + phones/tablets never run it, and the
   whole effect is killed under prefers-reduced-motion below. --mx/--my default to
   50%/0% so a card lit before JS attaches (or via keyboard) glows tastefully at top. */
@media (hover: hover) and (min-width: 981px) {
  .card { --mx: 50%; --my: 0%; }
  .card::after {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: inherit;
    padding: 1px;                 /* ring thickness */
    pointer-events: none;
    opacity: 0;
    transition: opacity .2s var(--ease-out);
    background: radial-gradient(
      180px circle at var(--mx) var(--my),
      color-mix(in oklab, var(--primary) 60%, transparent) 0%,
      color-mix(in oklab, var(--primary) 22%, transparent) 28%,
      transparent 62%);
    /* mask the fill down to just the border ring (border-box minus padding-box) */
    -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
    -webkit-mask-composite: xor;
    mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
    mask-composite: exclude;
    z-index: 2;
  }
  /* base .card has no overflow:hidden, so position it as the spotlight context */
  .card { position: relative; }
  .card:hover::after { opacity: 1; }
  /* KPI cards already use ::before for their accent rail and overflow:hidden; the
     ::after ring sits above content (kpi content is z-index:1) and inside the clip. */
}
@media (prefers-reduced-motion: reduce) {
  .card::after { display: none; }
}

.btn { transition: transform .12s var(--ease-spring), background var(--dur-fast), border-color var(--dur-fast), box-shadow .2s var(--ease-out); }
.btn:active { transform: translateY(1px) scale(.985); }
.btn-primary:hover { box-shadow: var(--glow); transform: translateY(-1px); }
.nav-item { transition: background var(--dur-fast), border-color var(--dur-fast), transform .12s var(--ease-spring); }
.nav-item:active { transform: translateY(1px) scale(.99); }
.nav-item.active { box-shadow: inset 2px 0 0 var(--primary); }

/* --- P3B: BUTTON INTERACTION-STATE UNIFICATION (conservative) ---
   Visuals (padding/radius/bg/border/hover colour) are UNCHANGED per class.
   This only equalises the *feel*: the 4 buttons that had no transition (instant
   hover) and no press feedback now share the same fast transition + a subtle
   :active press, matching .btn / .nav-item. No class is deleted or restyled. */
.icon-btn, .kp-btn, .tpl, .timer-btn {
  transition: background var(--dur-fast), border-color var(--dur-fast),
              color var(--dur-fast), transform .05s;
}
/* Consistent press feedback (same 1px nudge .btn uses; scale kept tiny on the
   square icon buttons so the glyph doesn't shift). */
.icon-btn:active, .kp-btn:active, .tpl:active, .timer-btn:active {
  transform: translateY(1px);
}
/* These 4 + .toast-action aren't in the enumerated global focus-visible list
   (they only matched the bare button:focus-visible). Give them the same ring so
   keyboard focus is consistent across every button variant. */
.icon-btn:focus-visible, .kp-btn:focus-visible, .tpl:focus-visible,
.timer-btn:focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: 2px;
  border-radius: inherit;
}

/* Modal / palette pop with a little spring */
.modal-card { animation: popIn var(--dur-base) var(--ease-spring) both; }
.palette { animation: popIn .22s var(--ease-spring) both; }
@keyframes popIn {
  from { opacity: 0; transform: translateY(12px) scale(.97); }
  to   { opacity: 1; transform: translateY(0) scale(1); }
}

/* Primary CTA gets a soft animated sheen-free glow ring on focus */
.btn-primary:focus-visible { box-shadow: var(--glow), 0 0 0 3px var(--accent-ring); }

/* --- ACCESSIBILITY: respect reduced-motion --- */
@media (prefers-reduced-motion: reduce) {
  body::before { animation: none; }
  .view.active, .view.view-swipe-in-right, .view.view-swipe-in-left,
  .modal-card, .modal .modal-card, .palette { animation: none; }
  .card:hover, .kcard:hover, .cstack-card:hover, .goal-row:hover,
  .project-item:hover, .note-item:hover,
  .btn-primary:hover, .nav-item:active, .btn:active,
  .icon-btn:active, .kp-btn:active, .tpl:active, .timer-btn:active { transform: none; }
  /* Comprehensive fallback: make ALL remaining animation/transition effectively instant
     (preserves final visual states — celebrations, pulses, typing dots, bar fills, hovers). */
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }
}

/* On phones, drop the lift (cards are full-width, lift reads as jitter) */
@media (max-width: 600px) {
  .card:hover, .kcard:hover, .cstack-card:hover, .goal-row:hover,
  .project-item:hover, .note-item:hover { transform: none; }
  .page-head h1 { font-size: 22px; }   /* P3B: canonical mobile h1 size (desktop = 30px @ :2062) */
}

/* ============================================================
   REDESIGN v24 — icons, bento dashboard, richer cards, skeletons
   ============================================================ */

/* --- Inline SVG icons (stroke = currentColor, inherit size) --- */
.nav-icon svg, svg.ic, .logo svg, .es-ico svg, .kpi-ico svg {
  fill: none; stroke: currentColor; stroke-width: 1.7;
  stroke-linecap: round; stroke-linejoin: round;
}
.logo svg { stroke: #fff; }
.nav-icon { display: inline-grid; place-items: center; width: 24px; height: 24px; }
.nav-icon svg { width: 20px; height: 20px; }
.logo svg { width: 22px; height: 22px; }
svg.ic { width: 18px; height: 18px; display: inline-block; vertical-align: -.16em; }
.icon-btn svg.ic, .btn svg.ic { width: 17px; height: 17px; }
.search-icon svg.ic { width: 16px; height: 16px; }
.pomo-ico svg.ic { width: 15px; height: 15px; }
.brand .logo { overflow: hidden; }

/* --- KPI cards: per-metric icon + accent edge --- */
.card.kpi { position: relative; overflow: hidden; }
.card.kpi::before {
  content: ''; position: absolute; left: 0; top: 0; bottom: 0; width: 3px;
  background: var(--primary); opacity: .85;
}
.card.kpi.k-today::before   { background: var(--accent); }
.card.kpi.k-overdue::before { background: var(--danger); }
.card.kpi.k-done::before    { background: var(--success); }
.kpi-ico {
  position: absolute; top: 14px; right: 14px;
  width: 32px; height: 32px; border-radius: 10px;
  display: grid; place-items: center;
  background: var(--accent-soft); color: var(--primary-2);
}
.kpi-ico svg { width: 18px; height: 18px; }
.k-today   .kpi-ico { background: color-mix(in oklab, var(--accent) 16%, transparent); color: var(--accent); }
.k-overdue .kpi-ico { background: rgba(239,79,90,.16);  color: #ff8c93; }
.k-done    .kpi-ico { background: rgba(62,207,142,.16); color: #6ee0a8; }
.kpi-label { position: relative; z-index: 1; }

/* --- Bento dashboard: secondary content below the primary KPI row.
   Focus is the tall left hero, chart + goals stack on the right,
   activity spans full width. --- */
.dash-bento {
  display: grid; gap: var(--space-4); margin-bottom: var(--space-4);
  grid-template-columns: 1.25fr 1fr;
  grid-template-areas:
    "focus chart"
    "focus goals"
    "activity activity";
}
.dash-bento .area-focus    { grid-area: focus; }
.dash-bento .area-chart    { grid-area: chart; }
.dash-bento .area-goals    { grid-area: goals; }
.dash-bento .area-activity { grid-area: activity; }
.dash-bento .area-focus .task-mini-list { max-height: none; }
/* Tablet (601–980px): keep a 2-col bento so the dashboard doesn't collapse
   straight to a single tall column — focus stays the hero, chart/goals stack
   on the right, activity full-width. */
@media (min-width: 601px) and (max-width: 980px) {
  .dash-bento {
    grid-template-columns: 1.1fr 1fr;
    grid-template-areas:
      "focus chart"
      "focus goals"
      "activity activity";
  }
}
@media (max-width: 600px) {
  .dash-bento {
    grid-template-columns: 1fr;
    grid-template-areas: "focus" "chart" "goals" "activity";
  }
}

/* --- Richer kanban cards --- */
.kcard { border-left: 3px solid var(--border); transition: transform .18s var(--ease-spring), border-color .18s, box-shadow .18s; }
.kcard.pri-high { border-left-color: var(--danger); }
.kcard.pri-med  { border-left-color: var(--warning); }
.kcard.pri-low  { border-left-color: var(--success); }
.kcard .kt { display: flex; align-items: center; gap: 8px; }
.kcard .kt .pdot { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; }
.kcard .pdot.high { background: var(--danger); }
.kcard .pdot.med  { background: var(--warning); }
.kcard .pdot.low  { background: var(--success); }
.kcard .kbar { height: 4px; background: var(--border); border-radius: 999px; margin-top: 8px; overflow: hidden; }
.kcard .kbar > i { display: block; height: 100%; background: linear-gradient(90deg, var(--success), var(--primary)); }
.kcard .kproj { display: inline-flex; align-items: center; gap: 4px; }
.kcard .kproj .d { width: 7px; height: 7px; border-radius: 50%; }

/* --- Skeleton shimmer --- */
.skeleton {
  position: relative; overflow: hidden;
  background: var(--panel-2); border-radius: var(--radius-sm);
}
.skeleton::after {
  content: ''; position: absolute; inset: 0;
  background: linear-gradient(90deg, transparent, color-mix(in oklab, var(--text) 7%, transparent), transparent);
  transform: translateX(-100%);
  animation: shimmer 1.3s infinite;
}
@keyframes shimmer { to { transform: translateX(100%); } }
.skeleton-line { height: 12px; margin: 8px 0; }
.skeleton-line.w60 { width: 60%; } .skeleton-line.w40 { width: 40%; } .skeleton-line.w80 { width: 80%; }
@media (prefers-reduced-motion: reduce) { .skeleton::after { animation: none; } }

/* Shaped skeleton variants (JS-built placeholders before first paint) */
/* KPI-card skeleton: shimmer lines injected straight into the existing .card.kpi (keeps the
   card's bg/border/padding); the value-row matches .kpi-value height so there's no jump. */
.card.kpi .sk-label { height: 11px; width: 50%; margin: 0; }
.card.kpi .sk-value { height: 26px; width: 64%; margin: 10px 0 8px; }
.card.kpi .sk-sub   { height: 10px; width: 40%; margin: 0; }
/* Skeleton chart — bars of varying height inside a .card; matches .chart-30 metrics */
.skel-chart { display: grid; grid-template-columns: repeat(30, 1fr); gap: 3px; height: 160px; align-items: end; padding-top: 14px; }
.skel-chart .sk-bar { width: 100%; border-radius: 3px 3px 0 0; min-height: 8px; }
/* AI chat: shimmer placeholder lines inside the pending bubble (alternative to typing dots) */
.bubble .skel-msg { display: flex; flex-direction: column; gap: 8px; min-width: min(160px, 60vw); padding: 2px 0; }
.bubble .skel-msg .skeleton-line { margin: 0; height: 11px; }

/* --- Composed empty states --- */
.empty-state {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 10px; text-align: center; padding: 40px 24px;
  color: var(--muted);
}
.empty-state .es-ico {
  width: 56px; height: 56px; border-radius: 16px;
  display: grid; place-items: center;
  background: var(--accent-softer); color: var(--primary-2);
  margin-bottom: 2px;
}
.empty-state .es-ico svg { width: 26px; height: 26px; }
.empty-state h3 { margin: 0; font-size: 15px; color: var(--text); font-family: var(--font-display); }
.empty-state p { margin: 0; max-width: 320px; font-size: 13px; }
.kanban-body .empty-state { padding: 22px 12px; }
.kanban-body .empty-state .es-ico { width: 40px; height: 40px; border-radius: 12px; }
.kanban-body .empty-state .es-ico svg { width: 18px; height: 18px; }
.kanban-body .empty-state p { font-size: 12px; }
.empty-state .es-action { margin-top: 6px; }
/* Calendar whole-month "no events" hint — subtle, sits under the grid */
.empty-state.cal-empty { padding: 24px; }
.empty-state.cal-empty .es-ico { width: 44px; height: 44px; border-radius: 12px; }
.empty-state.cal-empty .es-ico svg { width: 20px; height: 20px; }
/* Stats view-level "no data" banner — empty-state laid out inside a card */
.empty-state.stats-empty { padding: 28px 24px; }

/* ============================================================
   MORPHING CARD STACK — focus tasks (stack / grid / list)
   vanilla port of the React/framer-motion component
   ============================================================ */
.cstack { display: flex; flex-direction: column; gap: 12px; }
.cstack-head { display: flex; justify-content: center; }
.cstack-toggle {
  display: inline-flex; gap: 2px; padding: 3px;
  background: var(--panel-2); border: 1px solid var(--border); border-radius: 11px;
}
.cstack-toggle button {
  width: 32px; height: 28px; display: grid; place-items: center;
  border: 0; background: transparent; color: var(--muted);
  border-radius: 8px; cursor: pointer; transition: background var(--dur-fast), color var(--dur-fast);
}
.cstack-toggle button svg { width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }
.cstack-toggle button:hover { color: var(--text); }
.cstack-toggle button.active { background: var(--primary); color: #fff; box-shadow: var(--glow); }

.cstack-area { position: relative; }
.cstack-area.is-stack { height: 232px; }
.cstack-area.is-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.cstack-area.is-list { display: flex; flex-direction: column; gap: 8px; }

.cstack-card {
  background: var(--panel-2); border: 1px solid var(--border); border-radius: 14px;
  padding: 14px; cursor: pointer;
  transition: transform var(--dur-slow) var(--ease-spring), opacity .3s var(--ease-out), border-color .18s, box-shadow .18s;
}
.cstack-card:hover { border-color: var(--accent-line); }
.is-stack .cstack-card { position: absolute; inset: 0; will-change: transform; box-shadow: var(--shadow-2); }
/* Let horizontal swipes reach JS (pointer events) while vertical still scrolls the page */
.is-stack .cstack-card.top { cursor: grab; touch-action: pan-y; }
.is-stack .cstack-card.dragging { transition: opacity .3s; cursor: grabbing; }
.is-grid .cstack-card { min-height: 112px; }

.cstack-card .cs-top { display: flex; align-items: flex-start; gap: 10px; }
.cstack-card .cs-ico { width: 38px; height: 38px; border-radius: 11px; flex-shrink: 0; display: grid; place-items: center; background: var(--accent-soft); color: var(--primary-2); }
.cstack-card .cs-ico svg { width: 19px; height: 19px; fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }
.cstack-card .cs-ico.high { background: rgba(239,79,90,.16);  color: #ff8c93; }
.cstack-card .cs-ico.med  { background: color-mix(in oklab, var(--warning) 18%, transparent); color: #ffc266; }
.cstack-card .cs-ico.low  { background: rgba(62,207,142,.16); color: #6ee0a8; }
.cstack-card .cs-body { min-width: 0; flex: 1; }
.cstack-card .cs-ttl { font-weight: 600; font-family: var(--font-display); letter-spacing: -.01em; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cstack-card .cs-desc { color: var(--muted); font-size: 12.5px; margin-top: 4px; }
.is-stack .cs-desc { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.is-list .cs-desc { display: -webkit-box; -webkit-line-clamp: 1; -webkit-box-orient: vertical; overflow: hidden; }
.cstack-card .cs-foot { display: flex; align-items: center; gap: 8px; margin-top: 10px; flex-wrap: wrap; }
.cstack-card .cs-due.overdue { color: var(--danger); }
.cstack-card .cs-check {
  margin-left: auto; appearance: none; width: 20px; height: 20px; border-radius: 6px;
  border: 1.5px solid var(--border); background: var(--panel); cursor: pointer; position: relative; flex-shrink: 0;
}
.cstack-card .cs-check:checked { background: var(--success); border-color: var(--success); }
.cstack-card .cs-check:checked::after { content: "✓"; position: absolute; inset: 0; display: grid; place-items: center; color: #fff; font-size: 12px; font-weight: 700; }

.cstack-dots { display: flex; justify-content: center; gap: 6px; }
.cstack-dots button { height: 6px; width: 6px; border-radius: 999px; border: 0; padding: 0; background: var(--border); cursor: pointer; transition: width .2s var(--ease-out), background .2s; }
.cstack-dots button.active { width: 18px; background: var(--primary); }
.cstack-hint { text-align: center; font-size: 11px; color: var(--muted); opacity: .65; }

@media (prefers-reduced-motion: reduce) {
  .cstack-card { transition: opacity .2s, border-color .18s; }
}

/* ---- AI action cards: SVG icons + staggered entry ---- */
.aa-ico svg { width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }
.ai-action { animation: aaIn .34s var(--ease-out) backwards; }
@keyframes aaIn { from { opacity: 0; transform: translateY(8px) scale(.97); } to { opacity: 1; transform: translateY(0) scale(1); } }
@media (prefers-reduced-motion: reduce) { .ai-action { animation: none; } }

/* ---- Quick-add live preview chips ---- */
.qa-preview { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; margin: -2px 0 10px; padding-left: 6px; }
.qa-preview[hidden] { display: none; }
.qa-preview .qa-pl { color: var(--muted); font-size: 11.5px; }
.qa-pchip { display: inline-flex; align-items: center; gap: 4px; font-size: 11px; padding: 2px 8px; border-radius: 999px; background: var(--accent-soft); color: var(--primary-2); border: 1px solid var(--accent-line); }
.qa-pchip.high { background: rgba(239,79,90,.16); color: #ff8c93; border-color: rgba(239,79,90,.35); }
.qa-pchip.tag { background: var(--panel-2); color: var(--muted); border-color: var(--border); }
.qa-pchip .d { width: 7px; height: 7px; border-radius: 50%; }

/* ---- KPI sparkline (Выполнено: 7-day completions) ---- */
.kpi-spark { margin-top: 10px; height: 26px; }
.kpi-spark svg { width: 100%; height: 100%; display: block; overflow: visible; }
.kpi-spark .spk-line { fill: none; stroke: var(--success); stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.kpi-spark .spk-area { fill: color-mix(in oklab, var(--success) 16%, transparent); stroke: none; }
.kpi-spark .spk-dot { fill: var(--success); }

/* ============================================================
   MOBILE BOTTOM NAVIGATION
   ============================================================ */
.bottom-nav { display: none; }
@media (max-width: 980px) {
  .bottom-nav {
    display: flex; position: fixed; left: 0; right: 0; bottom: 0; z-index: var(--z-bottomnav);
    align-items: center; justify-content: space-around; gap: 2px;
    padding: 6px 8px max(6px, env(safe-area-inset-bottom));
    background: color-mix(in oklab, var(--panel) 90%, transparent);
    -webkit-backdrop-filter: blur(var(--glass-blur)); backdrop-filter: blur(var(--glass-blur));
    border-top: 1px solid var(--border);
    box-shadow: var(--glass-edge);   /* 1px inner top-edge highlight — matches modal/palette glass */
  }
  .bn-item {
    flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px;
    background: none; border: 0; cursor: pointer; color: var(--muted);
    font-size: 10px; font-weight: 500; padding: 4px 2px; min-height: 46px; border-radius: 12px;
    transition: color var(--dur-fast);
  }
  .bn-item svg { width: 22px; height: 22px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
  .bn-item span { line-height: 1; }
  .bn-item.active { color: var(--text); }
  .bn-item:active { background: var(--panel-2); }
  .bn-fab {
    flex: 0 0 auto; width: 50px; height: 50px; border-radius: 50%; margin-top: -18px;
    background: var(--primary); color: #fff; box-shadow: 0 6px 18px rgba(124,92,255,.5);
  }
  .bn-fab svg { width: 24px; height: 24px; stroke-width: 2.2; }
  .bn-fab:active { background: var(--primary-2, var(--primary)); }
  /* Clear the fixed bar so content isn't hidden behind it */
  .main { padding-bottom: calc(66px + env(safe-area-inset-bottom)); }
  .toast-host { bottom: calc(76px + env(safe-area-inset-bottom)) !important; }
}

/* ============================================================
   v36 UX POLISH (a11y, undo, counts, affordances)
   ============================================================ */
/* Toast: message + optional undo action */
.toast { display: flex; align-items: center; gap: 12px; }
.toast-msg { flex: 1; min-width: 0; }
.toast-action { flex: 0 0 auto; background: rgba(255,255,255,.16); color: #fff; border: 1px solid rgba(255,255,255,.28); border-radius: 8px; padding: 5px 11px; font-size: 12px; font-weight: 700; cursor: pointer; white-space: nowrap; }
.toast-action:hover { background: rgba(255,255,255,.28); }
.toast-action:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }

/* Smart-list live count badges */
.sl-count { margin-left: 6px; font-size: 11px; font-weight: 700; color: var(--muted); background: var(--panel-2); border-radius: var(--radius-pill); padding: 0 6px; min-width: 17px; height: 16px; line-height: 16px; display: inline-block; text-align: center; vertical-align: middle; }
.chip.smart.active .sl-count { color: #fff; background: rgba(255,255,255,.22); }

/* Kanban grab affordance */
.kcard { cursor: grab; user-select: none; -webkit-user-select: none; }
.kcard:active, .kcard.dragging { cursor: grabbing; }

/* Pomodoro pill pulses softly while running */
@keyframes pomoPulse { 0%, 100% { box-shadow: 0 0 0 0 rgba(124,92,255,0); } 50% { box-shadow: 0 0 0 4px rgba(124,92,255,.18); } }
.pomo-pill.running { animation: pomoPulse 2.4s ease-in-out infinite; }
@media (prefers-reduced-motion: reduce) { .pomo-pill.running { animation: none; } }

/* Mobile: larger tap targets + roomier bottom nav.
   Visuals stay 36px — the effective ~44px hit comes from the invisible
   ::after expansion (earlier ≤600px block); 40px visuals + gaps overflowed
   320px task rows, and 1px gap made adjacent mis-taps trivial. */
@media (max-width: 600px) {
  .icon-btn { width: 36px; height: 36px; font-size: 15px; }
  .task .actions { gap: 6px; }
}
@media (max-width: 980px) {
  .bn-item { min-height: 50px; min-width: 48px; padding: 6px 4px; }
  .bottom-nav { gap: 4px; }
}

/* ---- v37: quick-add first-focus syntax hint ---- */
.qa-syntax-hint {
  display: flex; flex-wrap: wrap; gap: 6px 14px;
  margin: 6px 2px 0; padding: 9px 12px;
  background: var(--accent-soft); border: 1px solid var(--accent-line);
  border-radius: 10px; font-size: 12px; color: var(--muted);
  animation: slidein .22s ease;
}
.qa-syntax-hint b { color: var(--primary-2, var(--primary)); font-weight: 700; }
.qa-syntax-hint span { white-space: nowrap; }

/* ---- v38: keyboard task navigation focus ring ---- */
.task.kbd-focus { outline: 2px solid var(--primary); outline-offset: -1px; box-shadow: 0 0 0 4px var(--accent-soft); }

/* ---- v39: palette empty-state hints + chat stop button ---- */
.palette-empty-hints { display: flex; flex-direction: column; gap: 6px; padding: 6px 12px 10px; }
.pe-hint { display: flex; align-items: center; gap: 8px; }
.pe-hint kbd { font-family: var(--font-mono, monospace); font-size: 11px; background: var(--panel-2); border: 1px solid var(--border); border-radius: 5px; padding: 2px 6px; white-space: nowrap; }
#btn-stop { color: var(--danger); border-color: var(--border); }

/* ---- v40: delight (KPI hover, streak celebration) ---- */
.card.kpi { transition: border-color .2s, box-shadow .2s; }
.card.kpi:hover { border-color: var(--accent-line); box-shadow: var(--glow); }
.card.kpi::before { transition: width .2s ease, filter .2s ease; }
.card.kpi:hover::before { width: 5px; filter: brightness(1.35); }
@keyframes streakPulse { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.18); box-shadow: 0 0 22px var(--primary); } }
.streak-celebrate { animation: streakPulse .7s var(--ease-spring, ease-out); }
@media (prefers-reduced-motion: reduce) { .streak-celebrate { animation: none; } }

/* ============================================================
   v41: dataviz polish + welcome shortcuts
   ============================================================ */
.heat-legend { display: flex; align-items: center; gap: 12px; margin-bottom: 12px; padding-bottom: 8px; border-bottom: 1px solid var(--border); flex-wrap: wrap; }
.heat-legend-label { white-space: nowrap; }
.heat-legend-item { display: flex; align-items: center; gap: 5px; }
.heat-legend-item .heat-cell { width: 13px; height: 13px; border-radius: 3px; }
.heat-legend-text { font-variant-numeric: tabular-nums; }
/* 7d chart today marker */
.bar-label.today { font-weight: 700; color: var(--text); }
.bar.today { box-shadow: 0 0 0 2px var(--primary); }
.bar-wrap.today { position: relative; }
.bar-wrap.today::after { content: 'сегодня'; position: absolute; bottom: -2px; left: 50%; transform: translateX(-50%); font-size: 9px; color: var(--primary); font-weight: 700; opacity: 0; transition: opacity var(--dur-fast); pointer-events: none; }
.bar-wrap.today:hover::after { opacity: 1; }
/* Sparkline endpoint dots */
.spk-dot { fill: var(--primary); opacity: .85; }
/* Welcome shortcut cards */
.welcome-shortcuts { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 12px; }
.welcome-shortcut { display: inline-flex; align-items: center; gap: 8px; padding: 8px 12px; border-radius: 10px; border: 1px solid var(--border); background: var(--panel-2); color: var(--text); cursor: pointer; font-size: 12px; transition: border-color var(--dur-fast), transform .06s; }
.welcome-shortcut:hover { border-color: var(--primary); }
.welcome-shortcut:active { transform: scale(.97); }
.welcome-shortcut kbd { font-family: var(--font-mono, monospace); font-size: 11px; background: var(--panel); border: 1px solid var(--border); border-radius: 5px; padding: 2px 6px; white-space: nowrap; }

/* ===== v42: chat message controls, KPI trend, button/chip cohesion ===== */
/* Reserve a right gutter on AI messages so the action controls live beside the
   bubble (max-width 80% of the now-narrower content box) and never overlap text. */
.msg.ai { padding-right: 58px; }
.msg-actions {
  position: absolute; top: 4px; right: 4px;
  display: flex; gap: 4px;
  opacity: 0; pointer-events: none;
  transform: translateY(-2px);
  transition: opacity var(--dur-fast) var(--ease-out), transform var(--dur-fast) var(--ease-out);
}
.msg.ai:hover .msg-actions,
.msg.ai .msg-actions:focus-within { opacity: 1; pointer-events: auto; transform: none; }
.msg-act-btn {
  width: 24px; height: 24px; padding: 0;
  display: grid; place-items: center;
  border: 1px solid var(--border); border-radius: 6px;
  background: var(--panel); color: var(--muted);
  cursor: pointer; font-size: 12px; line-height: 1;
  transition: color var(--dur-fast), border-color var(--dur-fast), background var(--dur-fast), transform .05s;
}
.msg-act-btn:hover { color: var(--text); border-color: var(--primary); background: var(--panel-2); }
.msg-act-btn:active { transform: translateY(1px); }
.msg-act-btn:focus-visible { outline: 2px solid var(--primary); outline-offset: 1px; }
/* On touch devices there is no hover — keep the controls gently visible in the gutter */
@media (hover: none) { .msg.ai .msg-actions { opacity: .6; pointer-events: auto; transform: none; } }

/* KPI trend arrow vs yesterday — sits in the 12px subtitle, so set an explicit legible size */
.kpi-trend { font-size: 13px; font-weight: 800; vertical-align: baseline; letter-spacing: 0; }
.kpi-trend.up { color: var(--success); }
.kpi-trend.down { color: var(--danger); }

/* Button & chip vertical-rhythm cohesion (min-height floor only — values match each
   variant's intrinsic height so nothing grows materially; padding untouched) */
.btn { min-height: 36px; }
.btn-sm { min-height: 30px; }
.btn-lg { min-height: 46px; }
.chip { min-height: 32px; }
.chip.smart { min-height: 32px; }
@media (max-width: 768px) {
  .btn { min-height: 42px; }      /* comfortable touch targets */
  .btn-sm, .chip, .chip.smart { min-height: 36px; }
}

/* ============================================================
   «ЕЩЁ» BOTTOM SHEET + BOTTOM-NAV ACTIVE PILL (mobile only)
   ============================================================ */
/* The sheet exists only at the breakpoint where the bottom nav is visible */
.more-sheet, .more-sheet-backdrop { display: none; }

@media (max-width: 980px) {
  /* Active bottom-nav item: visible pill behind icon+label, not just a color change.
     Label keeps high-contrast --text (AA in both themes); only the icon carries the
     accent — mirrors the sidebar .nav-item.active pattern. (--primary as label text
     was 3.6:1 on the soft pill = WCAG AA fail.) */
  .bn-item { transition: color var(--dur-fast), background-color var(--dur-fast); }
  .bn-item.active { color: var(--text); background: var(--accent-soft); }
  .bn-item.active svg { color: var(--primary-2); }

  /* «Ещё» three-dots icon — solid dots, stroke matches .nav-icon (1.7) */
  #bn-more svg { stroke-width: 1.7; }
  #bn-more svg circle { fill: currentColor; }

  .more-sheet-backdrop {
    display: block; position: fixed; inset: 0; z-index: var(--z-sheet-backdrop);
    background: rgba(8, 8, 16, .5);
    opacity: 0; pointer-events: none;
    transition: opacity var(--dur-base) var(--ease-out);
  }
  .more-sheet-backdrop.show { opacity: 1; pointer-events: auto; }

  .more-sheet {
    display: block; position: fixed; left: 0; right: 0; bottom: 0; z-index: var(--z-sheet);
    padding: 8px 10px max(12px, env(safe-area-inset-bottom));
    background: color-mix(in oklab, var(--panel) 90%, transparent);
    -webkit-backdrop-filter: blur(var(--glass-blur)); backdrop-filter: blur(var(--glass-blur));
    border-top: 1px solid rgba(255,255,255,.08);
    border-radius: 14px 14px 0 0;
    box-shadow: 0 -12px 40px rgba(0,0,0,.45), var(--glass-edge);  /* + 1px inner top-edge highlight */
    transform: translateY(100%); opacity: 0; visibility: hidden;
    transition: transform var(--dur-base) var(--ease-out), opacity var(--dur-base) var(--ease-out), visibility var(--dur-base);
  }
  .more-sheet.open { transform: none; opacity: 1; visibility: visible; }

  .more-sheet-handle { width: 36px; height: 4px; border-radius: 999px; background: rgba(255,255,255,.18); margin: 4px auto 10px; }

  .more-sheet-item {
    display: flex; align-items: center; gap: 12px; width: 100%;
    padding: 13px 12px; border: 0; border-radius: 12px;
    background: none; color: var(--text); text-align: left;
    font-size: 14px; font-weight: 500; cursor: pointer;
  }
  .more-sheet-item:active { background: var(--panel-2); }
  .more-sheet-item:focus-visible { outline: 2px solid var(--primary); outline-offset: -2px; }
  .more-sheet-item.active { color: var(--text); background: var(--accent-softer); }
  .more-sheet-item.active .nav-icon { color: var(--primary-2); }

  /* Light theme: the handle + top border are white-on-white otherwise (invisible) */
  [data-theme="light"] .more-sheet-handle { background: rgba(40, 30, 80, .22); }
  [data-theme="light"] .more-sheet { border-top-color: var(--border); }
}

@media (prefers-reduced-motion: reduce) {
  .more-sheet, .more-sheet-backdrop { transition: none; }
}

/* Keyboard-shortcut hints are useless on touch phones */
@media (max-width: 600px) {
  .welcome-shortcuts { display: none; }
}

/* ============================================================
   SCROLL CONTAINMENT — inner scrollers must not chain into the
   page (which would rubber-band / pull-to-refresh on touch).
   Kanban columns are intentionally absent: .kanban-body never
   scrolls itself (columns grow, the page scrolls).
   ============================================================ */
.modal-body, .auth-gate, .chat, .kb-list,
.projects-list, .timeline,
.palette-results, .ctx-menu,
.page-actions, .smart-lists {
  overscroll-behavior: contain;
}

/* ============ v60 PREMIUM — Pedestal: greeting hero + scoped surface ladder (appended → wins) ============ */
/* GOAL: elevate the existing iris/glass identity (NOT a redesign). One bold place — the dashboard
   greeting becomes a lit-from-above, faintly iris-tinted hero plinth — everything else stays quiet
   via a disciplined, dashboard-scoped surface-elevation ladder + a single spacing-rhythm bump.
   CSS-only, attribute-scoped, additive (wins by source order). No new motion / no font / no hue. */

/* 1. SIGNATURE — the dashboard greeting hero (the ONE bold surface).
   `> .page-head` (direct child of the dashboard section) so the ~10 other .page-head views are untouched. */
[data-view="dashboard"] > .page-head {
  position: relative;
  align-items: center;
  padding: var(--space-5) var(--space-5);            /* 20px both axes — real breathing room */
  margin-bottom: var(--space-6);                     /* 24px (was 18px) — masthead air */
  border-radius: var(--radius-lg);                   /* 16px */
  /* tonal iris wash, lit from above — single tasteful gradient surface */
  background: linear-gradient(180deg,
    color-mix(in oklab, var(--primary) 6%, var(--panel)) 0%,
    var(--panel) 72%);
  border: 1px solid color-mix(in oklab, var(--primary) 14%, var(--border));
  box-shadow: var(--shadow-2), var(--glass-edge);    /* elevation reserved for hero + 1px top-edge highlight */
  overflow: hidden;
}
/* faint single-accent rail anchoring the hero to the iris identity (mirrors KPI ::before language). NO animation. */
[data-view="dashboard"] > .page-head::before {
  content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 3px;
  background: linear-gradient(180deg, var(--primary), var(--accent));
  opacity: .9; pointer-events: none; z-index: 0;
}
/* keep content above the rail/wash */
[data-view="dashboard"] > .page-head > * { position: relative; z-index: 1; }
/* the greeting: a small, deliberate size bump + a hair tighter tracking — the editorial first glance.
   Manrope/700 (:2088) + text-wrap:balance (:2093) carry over; no new font/weight. */
[data-view="dashboard"] > .page-head h1 {
  font-size: 34px;                                   /* up from 30px — the ONE size escalation */
  line-height: 1.05;
  letter-spacing: -.025em;                           /* slightly tighter than global -.02em at this scale */
}
[data-view="dashboard"] > .page-head #hello-line {
  font-size: 14px; margin-top: 4px; max-width: 52ch; /* editorial measure on the deck line */
  letter-spacing: .01em;                             /* faint "deck" feel; weight-500 already from P3B :2152 */
}

/* 2. SIGNATURE — mobile guard (MANDATORY): the dashboard hero h1 beats the canonical
   @media(max-width:600px) .page-head h1{22px} (:2358) on specificity (media context adds none),
   so re-pin it for phone and relax the band. Mobile stacking (:1935) + #hello-line hide (:1937) still apply. */
@media (max-width: 600px) {
  [data-view="dashboard"] > .page-head {
    align-items: flex-start;                         /* restore v55 left-aligned stacked head (hero center is desktop-only) */
    padding: var(--space-4) var(--space-4);          /* 16px — quieter on phone */
    border-radius: var(--radius);                    /* 14px */
    margin-bottom: var(--space-5);                   /* 20px */
  }
  [data-view="dashboard"] > .page-head h1 { font-size: 24px; }  /* slightly above 22 baseline — it IS the hero now */
}

/* 3. MATERIAL — scoped recessive content tier ("everything floats" fix).
   Dashboard bento + timeline cards recede below --panel onto --bg-2 with a softer shadow, so they
   stop competing with the KPI band + hero. SCOPED (not global .card) → modals/settings/kanban/notes
   and the v59 spotlight host are protected. KPI cards deliberately left out (they earn emphasis). */
.dash-bento > .card,
[data-view="dashboard"] .day-timeline-card {
  background: var(--bg-2);                            /* below --panel → recedes (dark #110f17 / light #efedf6) */
  border-color: color-mix(in oklab, var(--border) 70%, transparent);
  box-shadow: var(--shadow-1);                        /* softer than --shadow-2 → grounded, not floating */
}
/* Ladder: recessive content (shadow-1/bg-2) < KPI band (shadow-2+rails) < hero (shadow-2+glass-edge+tint)
   < overlays (shadow-3, shipped). Lighter resting tier also widens the existing :hover lift (→shadow-3 @ :2241). */
/* Restore the hover lift on the recessive tier: the rule above ties .card:hover (:2241) on
   specificity (0,2,0) and wins on source order, pinning these cards at shadow-1/no-accent-edge on
   desktop hover. Re-assert the shadow-3 escalation + accent edge so the resting tier rises MORE on
   hover (the stated intent). Gated (hover:hover)+(min-width:981px) → no touch/phone/tablet leak. */
@media (hover: hover) and (min-width: 981px) {
  .dash-bento > .card:hover,
  [data-view="dashboard"] .day-timeline-card:hover {
    box-shadow: var(--shadow-3);
    border-color: var(--accent-line);
  }
}

/* 4. SPATIAL — the ONLY spacing change: a touch more air between the now-recessed bento cards. */
.dash-bento { gap: var(--space-5); }                 /* 16 → 20 */

/* 5. MICRO-TYPOGRAPHY — quiet supporting convention (NOT a second signature). Scoped to KPI cards;
   reuses --muted only (no hue/size escalation). Tightens label→number coupling + faint editorial tracking. */
.kpi-label { letter-spacing: .02em; }                /* stays 12px/500/--muted from P3B */
.kpi-value { margin-top: 6px; }                      /* tighten label→number coupling (was 4px) */
/* ============ end v60 PREMIUM ============ */

/* ============ Legal links (Settings footer) ============
   Small muted line linking to terms.html / privacy.html added to the Settings view.
   No global `a` color rule exists, so scope the iris link colour here to avoid default blue. */
.legal-links {
  margin: 4px 2px 0;
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;
}
.legal-links a {
  color: var(--muted);
  text-decoration: none;
}
.legal-links a:hover { color: var(--text); text-decoration: underline; text-underline-offset: 2px; }
.legal-links a:focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: 2px;
  border-radius: 4px;
}
/* ============ end Legal links ============ */

/* ===================================================================
   BLUEPRINT IDENTITY — v62 (appended → wins by source order)
   Monospace technical look. Canvas/accent/semantics/radius/fonts are set
   in :root + body above so [data-theme=light] still overrides canvas.
   Runtime palette (SCHEMES, app.js) recolors --bg…--muted + --primary/-2/--accent.
   =================================================================== */

/* uppercase technical labels — CHROME ONLY, never user content */
.page-head h1,
.card-head h3,
.kpi-label,
.brand-sub,
.empty-state h3 { text-transform: uppercase; letter-spacing: .08em; }
.page-head h1 { letter-spacing: .02em; }   /* headings: gentler tracking at large size */

/* sharp corners on the literal-999px pill/tag/chip family
   (token-based chips/badges already follow --radius-pill = 3px) */
.pill, .proj-chip, .task .tag, .task .due, .dep-chip, .link-pill,
#account-status, .pomo-pill, .streak-chip, .seg, .kb-toggle { border-radius: 3px; }

/* KPI band: one hero number (the "today" metric) + asymmetric grid */
.grid.kpis { grid-template-columns: 1.7fr 1fr 1fr 1fr; }
.grid.kpis .kpi.k-today { order: -1; }
.grid.kpis .kpi.k-today .kpi-value { font-size: 52px; line-height: .95; }

/* "Фокус на сегодня" becomes the single raised surface in the bento
   (overrides the v60 recession rule at :2900 for this one card) */
.dash-bento > .area-focus {
  background: var(--panel);
  border-color: var(--accent-line);
  box-shadow: var(--shadow-2);
}

/* dashboard 7-day chart bars: solid accent line, not the primary→accent gradient
   (blueprint = monochrome instrument data) */
.chart .bar { background: var(--primary); }

/* flat monoline brand logo (drop the gradient square + glow) */
.brand .logo, .gate-logo .logo {
  background: var(--panel-2);
  border: 1px solid var(--border);
  box-shadow: none;
}
.brand .logo svg { stroke: var(--text); fill: none; stroke-width: 1.75; stroke-linecap: round; stroke-linejoin: round; }
.brand .logo svg .fire { stroke: var(--primary); }

/* custom-colour swatch in the scheme picker */
.accent-custom-input {
  width: 22px; height: 22px; padding: 0;
  border: 1px solid var(--border); border-radius: 3px;
  background: none; cursor: pointer;
}

/* consistency: sharpen large containers that hardcode their own radius (blueprint = hard edges) */
.gate-card, .gate-features, .palette, .welcome-emoji, .empty-state .es-ico { border-radius: 3px; }

/* mono UI + sans PROSE (v62 font decision): long-form reading/writing surfaces use the
   self-hosted Inter (Cyrillic) for comfort; all chrome/labels/data stay monospace = Blueprint.
   Code blocks inside prose stay mono. */
.markdown-view, .bubble, #note-body, #chat-input {
  font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
}
.markdown-view pre, .markdown-view code,
.bubble pre, .bubble code {
  font-family: ui-monospace, "SF Mono", "JetBrains Mono", "Cascadia Code", "DejaVu Sans Mono", Menlo, Consolas, monospace;
}

/* ===================================================================
   v62 — usability + a11y pass (appended)
   =================================================================== */

/* U1 — progressive-disclosure "Дополнительно" block in the task modal */
.modal-advanced { border-top: 1px solid var(--border); margin-top: 6px; padding-top: 4px; }
.modal-advanced > summary {
  cursor: pointer; list-style: none; user-select: none;
  font-size: 12px; letter-spacing: .08em; text-transform: uppercase; color: var(--muted);
  padding: 8px 4px; display: flex; align-items: center; gap: 8px; min-height: 40px;
}
.modal-advanced > summary::-webkit-details-marker { display: none; }
.modal-advanced > summary::before { content: "\25B8"; color: var(--primary); transition: transform .15s var(--ease-out); }
.modal-advanced[open] > summary::before { transform: rotate(90deg); }
.modal-advanced > summary:hover { color: var(--text); }
.modal-advanced > .modal-grid { margin-top: 8px; }

/* A1 — light-theme WCAG contrast: priority pills read ~1.4-1.8:1 without an override; success-as-text ~2:1 */
[data-theme="light"] .pill.high { background: rgba(239,79,90,.16); color: #b3203a; }
[data-theme="light"] .pill.med  { background: rgba(245,165,36,.20); color: #8a5300; }
[data-theme="light"] .pill.low  { background: rgba(62,207,142,.20); color: #136c47; }
[data-theme="light"] { --success: #1a9d68; }

/* A5 — high-contrast + forced-colors (Windows High Contrast) support */
@media (prefers-contrast: more) {
  :root { --border: #3a4a63; }
  [data-theme="light"] { --border: #b9bccb; }
}
@media (forced-colors: active) {
  .btn, .chip, .nav-item, .task, .card, .kpi { border: 1px solid ButtonBorder; }
  .nav-item.active, .chip.smart.active { outline: 2px solid Highlight; }
  :focus-visible { outline: 2px solid Highlight; outline-offset: 2px; }
}

/* v62 icons: baseline-align inline monoline icons (flex/grid contexts ignore this) */
svg.ic { vertical-align: -.16em; }
.chip svg.ic { margin-right: 1px; }

/* ===================================================================
   v62 motion signatures (#6)
   =================================================================== */
/* task-complete: animated strike-through sweep + a brief lift */
.task .title { position: relative; }
.task .title::after {
  content: ''; position: absolute; left: 0; top: 54%; height: 2px; width: 0;
  background: var(--success); border-radius: 2px; pointer-events: none;
}
.task-completing .title::after { animation: taskStrike .4s var(--ease-out) forwards; }
.task-completing { animation: taskLift .5s var(--ease-spring); z-index: 2; }
@keyframes taskStrike { to { width: 100%; } }
@keyframes taskLift { 0% { transform: translateY(0); } 30% { transform: translateY(-3px) scale(1.006); } 100% { transform: translateY(0); } }

/* buttons: subtle hover-lift on precise pointers (uses the existing transform transition) */
@media (hover: hover) {
  .btn:hover { transform: translateY(-1px); }
  .btn-primary:hover { transform: translateY(-1px); box-shadow: 0 6px 20px color-mix(in oklab, var(--primary) 42%, transparent); }
}

/* AI "thinking": brand signal pulse on the topbar status dot while a request is inflight */
.status-dot.thinking { animation: aiPulse 1.3s ease-in-out infinite; }
@keyframes aiPulse {
  0%, 100% { text-shadow: 0 0 0 transparent; filter: brightness(1); }
  50% { text-shadow: 0 0 10px var(--primary); filter: brightness(1.5); }
}

@media (prefers-reduced-motion: reduce) {
  .task-completing, .status-dot.thinking { animation: none; }
  .task-completing .title::after { animation: none; width: 100%; }
}

/* ===================================================================
   v62 Phase A — tinted calendar chips + motion добор (CSS parts)
   =================================================================== */
/* A2 — tinted-rail calendar chips (priority hue) */
.cal-tag { border-left: 3px solid var(--border); padding-left: 6px; }
.cal-tag.high { border-left-color: var(--danger); background: color-mix(in oklab, var(--danger) 12%, var(--panel)); }
.cal-tag.med  { border-left-color: var(--warning); background: color-mix(in oklab, var(--warning) 12%, var(--panel)); }
.cal-tag.low  { border-left-color: var(--success); background: color-mix(in oklab, var(--success) 12%, var(--panel)); }
.cal-tag.overdue { border-left-color: var(--danger); }
.cal-tag.done { opacity: .55; }

/* A5 — streak resting ember (subtle breathe while the chip is shown) */
.streak-chip:not([hidden]) { animation: emberBreathe 4s ease-in-out infinite; }
@keyframes emberBreathe { 0%, 100% { filter: brightness(1); } 50% { filter: brightness(1.18); } }

/* A5 — progress fills get a slight spring overshoot */
.bar-thin > i, .subtasks-progress > i, .goal-row .bar > i { transition: width var(--dur-slow) var(--ease-spring); }

@media (prefers-reduced-motion: reduce) {
  .streak-chip:not([hidden]) { animation: none; }
}

/* ===================================================================
   v62 Phase C/D — toast icons, native FAB, standalone
   =================================================================== */
/* C1 — toast status icon */
.toast-ico { display: inline-flex; align-items: center; margin-right: 7px; flex: 0 0 auto; }
.toast.success .toast-ico { color: var(--success); }
.toast.warn .toast-ico { color: var(--warning); }
.toast.err .toast-ico, .toast.error .toast-ico { color: var(--danger); }

/* D1 — native flush bottom-bar add button (drop the Material raised FAB) */
.bn-fab {
  margin-top: 0;
  width: 44px; height: 44px;
  background: var(--accent-soft);
  border: 1px solid var(--accent-line);
  color: var(--primary-2);
  box-shadow: none;
  border-radius: 3px;
}
.bn-fab:active { transform: scale(.92); }

/* D4-standalone — a touch more top breathing room when installed; keep it app-like */
@media (display-mode: standalone) {
  .topbar { padding-top: max(11px, env(safe-area-inset-top)); }
}

/* ===================================================================
   v62 — final-audit fixes (#3-7)
   =================================================================== */
/* #3 — gate/auth logo: monoline mark, visible in both themes */
.gate-logo .logo svg { stroke: var(--text); fill: none; stroke-width: 1.75; stroke-linecap: round; stroke-linejoin: round; }
.gate-logo .logo svg .fire { stroke: var(--primary); }

/* #4 — keyboard focus ring on the "Дополнительно" disclosure summary */
.modal-advanced > summary:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; border-radius: 3px; }

/* #5 — radii normalization (Blueprint = sharp); circles/dots/switch-knobs left round */
.cstack-toggle, .cstack-toggle button, .cstack-card, .cs-ico, .cs-check,
.bn-item, .msg-act-btn, .qa-pchip, .es-ico, .kb-toggle, .seg,
.link-pill, .dep-chip, .tpl, .ai-action, .hist-item, .sess-row,
.note-item, .project-item, .kcard, .cal-day, .accent-swatch,
.pill, .proj-chip, .cal-tag, .sl-count, .badge { border-radius: var(--radius-sm); }

/* #6 — kill remaining violet-era gradients / flatten instrument bars */
.chart .bar { border-radius: 3px 3px 0 0; }
.welcome-emoji {
  background: var(--accent-soft); color: var(--primary-2); box-shadow: none;
  border: 1px solid var(--accent-line); display: grid; place-items: center;
}
.welcome-emoji svg.ic { width: 28px; height: 28px; }

/* #7 — WCAG: dark ink on the bright accent button (fixes white-on-pale: Лёд / light custom / teal) */
.btn-primary { color: #08131a; }

/* ============================================================
   BLUEPRINT INSTRUMENT CHARTS (#9) — pure-CSS over existing DOM.
   Token-based (color-mix) → tracks all 6 schemes + light/dark.
   prefers-reduced-motion gated. No JS/HTML changes.
   ============================================================ */
:root {
  --instr-grid: color-mix(in oklab, var(--border) 60%, transparent);
  --instr-axis: color-mix(in oklab, var(--border) 100%, transparent);
  --instr-cap:  color-mix(in oklab, var(--primary) 88%, var(--text) 12%);
  --instr-fill: color-mix(in oklab, var(--primary) 42%, transparent);
  --instr-glow: color-mix(in oklab, var(--primary) 45%, transparent);
}
/* 7-day + 30-day plotting frame: horizontal gridlines every 25% behind the
   bars (align-items:end → drawn behind, no DOM change) + inset L-axis. */
.chart,
.chart-30 {
  position: relative;
  background-image:
    repeating-linear-gradient(to top,
      transparent 0, transparent calc(25% - 1px),
      var(--instr-grid) calc(25% - 1px), var(--instr-grid) 25%);
  background-position: left bottom;
  background-repeat: no-repeat;
  box-shadow: inset 1px 0 0 0 var(--instr-axis), inset 0 -1px 0 0 var(--instr-axis);
}
/* denser 30-day trace gets faint vertical sampling ticks too */
.chart-30 {
  background-image:
    repeating-linear-gradient(to top,
      transparent 0, transparent calc(25% - 1px),
      var(--instr-grid) calc(25% - 1px), var(--instr-grid) 25%),
    repeating-linear-gradient(to right,
      transparent 0, transparent calc(10% - 1px),
      color-mix(in oklab, var(--border) 30%, transparent) calc(10% - 1px),
      color-mix(in oklab, var(--border) 30%, transparent) 10%);
  background-position: left bottom, left bottom;
  background-repeat: no-repeat, no-repeat;
}
/* bars = measured columns: half-toned fill + bright signal cap */
.chart .bar,
.chart-30 .bar {
  background: var(--instr-fill);
  border-top: 2px solid var(--instr-cap);
  border-radius: 0;
  box-shadow: 0 -1px 6px -1px var(--instr-glow);
}
.chart .bar.today {
  background: color-mix(in oklab, var(--primary) 55%, transparent);
  border-top-color: var(--primary);
  box-shadow: 0 -1px 9px -1px var(--instr-glow);
}
.chart .bar-label {
  font-family: var(--font-display, ui-monospace, monospace);
  font-size: 10px; letter-spacing: .04em;
  font-variant-numeric: tabular-nums; text-transform: uppercase;
}
/* heatmap: crisp 1px engineering grid, square cells */
.heatmap { gap: 1px; }
.heatmap .heat-week { gap: 1px; }
.heat-cell { border-radius: 0; border-color: color-mix(in oklab, var(--border) 70%, transparent); }
/* priority hbars: flat track + bright leading edge (semantic tokens) */
.hb-track { border-radius: 0; border: 1px solid var(--border); background: var(--panel-2); }
.hb-fill { border-radius: 0; }
.hb-fill.high { box-shadow: inset 2px 0 0 0 color-mix(in oklab, var(--danger) 70%, #fff),  0 0 5px color-mix(in oklab, var(--danger) 35%, transparent); }
.hb-fill.med  { box-shadow: inset 2px 0 0 0 color-mix(in oklab, var(--warning) 70%, #fff), 0 0 5px color-mix(in oklab, var(--warning) 35%, transparent); }
.hb-fill.low  { box-shadow: inset 2px 0 0 0 color-mix(in oklab, var(--success) 70%, #fff), 0 0 5px color-mix(in oklab, var(--success) 35%, transparent); }
/* sparkline: mini frame + glowing leading vertex (logo "spike" motif) */
.kpi-spark {
  position: relative; padding: 2px 0 0 1px;
  background-image:
    repeating-linear-gradient(to top,
      transparent 0, transparent calc(50% - 1px),
      var(--instr-grid) calc(50% - 1px), var(--instr-grid) 50%);
  background-position: left bottom; background-repeat: no-repeat;
  box-shadow: inset 1px 0 0 0 var(--instr-axis), inset 0 -1px 0 0 var(--instr-axis);
}
.kpi-spark .spk-line { filter: drop-shadow(0 0 1.5px color-mix(in oklab, var(--success) 55%, transparent)); }
.kpi-spark .spk-dot { fill: color-mix(in oklab, var(--success) 55%, transparent); }
.kpi-spark .spk-dot:last-of-type { fill: var(--success); filter: drop-shadow(0 0 3px var(--success)); }
@media (prefers-reduced-motion: no-preference) {
  .kpi-spark .spk-dot:last-of-type { animation: instr-pulse 2.4s ease-in-out infinite; }
  @keyframes instr-pulse { 0%, 100% { filter: drop-shadow(0 0 2px var(--success)); } 50% { filter: drop-shadow(0 0 5px var(--success)); } }
}
@media (prefers-reduced-motion: reduce) {
  .chart .bar { transition: none; }
  .kpi-spark .spk-dot:last-of-type { animation: none; }
}

/* #13c — gauge "settle": count-up number lands with a brief overshoot pop */
.kpi-value.kpi-settled { animation: kpiSettle .34s var(--ease-spring); }
@keyframes kpiSettle { 0% { transform: scale(1); } 42% { transform: scale(1.07); } 100% { transform: scale(1); } }
@media (prefers-reduced-motion: reduce) { .kpi-value.kpi-settled { animation: none; } }

/* ============================================================================
   DAY-LOAD READOUT (#11) — instrument-style booked-vs-capacity gauge atop the
   focus card. Token-based, Blueprint (mono, sharp corners, signal-cap bar).
   ========================================================================= */
.day-load {
  margin: 4px 0 12px;
  padding: 8px 10px;
  border: 1px solid var(--border);
  border-radius: 3px;
  background: var(--panel-2);
}
.day-load-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
  font-family: var(--mono, ui-monospace, monospace);
  font-size: 11px;
  letter-spacing: .08em;
  text-transform: uppercase;
}
.day-load-title { color: var(--muted); }
.day-load-figures { color: var(--text); white-space: nowrap; }
.day-load-figures strong { color: var(--primary); font-weight: 600; }
.day-load-sep { color: var(--muted); margin: 0 1px; }
/* thin capacity bar — flat instrument track + signal-cap fill */
.day-load-bar {
  position: relative;
  height: 4px;
  margin-top: 7px;
  border: 1px solid var(--border);
  border-radius: 3px;
  background: var(--bg-2);
  overflow: hidden;
}
.day-load-fill {
  height: 100%;
  width: 0;
  background: var(--primary);
  border-radius: 2px;
  transition: width .4s ease, background-color .2s ease;
}
/* state escalation: near-full → warning, over capacity → danger */
.day-load[data-load="ok"]   .day-load-figures strong { color: var(--primary); }
.day-load[data-load="warn"] .day-load-fill { background: var(--warning); }
.day-load[data-load="warn"] .day-load-figures strong { color: var(--warning); }
.day-load[data-load="over"] .day-load-fill { background: var(--danger); }
.day-load[data-load="over"] .day-load-figures strong { color: var(--danger); }
@media (prefers-reduced-motion: reduce) {
  .day-load-fill { transition: none; }
}

/* ============================================================================
   AI ASSISTANT — Cluster A: signal-trace "thinking", '/'-command menu, undo
   ============================================================================ */

/* (1) SIGNAL-TRACE thinking indicator — oscilloscope/EEG sweep echoing the logo spike.
   Replaces the 3-dot typing bubble; the .thinking status-dot pulse is untouched. */
.signal-trace { display: block; width: 120px; height: 24px; }
.signal-trace svg { display: block; width: 100%; height: 100%; overflow: visible; }
.signal-trace .st-base {
  fill: none; stroke: var(--border); stroke-width: 1;
  vector-effect: non-scaling-stroke;
}
.signal-trace .st-wave {
  fill: none; stroke: var(--primary); stroke-width: 2;
  stroke-linecap: round; stroke-linejoin: round;
  vector-effect: non-scaling-stroke;
  filter: drop-shadow(0 0 3px var(--primary-50));
  /* Reveal-then-erase sweep: a bright segment travels the length of the trace. */
  stroke-dasharray: 34 260;
  stroke-dashoffset: 294;
  animation: signalSweep 1.5s linear infinite;
}
@keyframes signalSweep {
  from { stroke-dashoffset: 294; }
  to   { stroke-dashoffset: -34; }
}
/* Reduced motion → static full trace, no sweep (still tinted --primary). */
@media (prefers-reduced-motion: reduce) {
  .signal-trace .st-wave {
    stroke-dasharray: none;
    stroke-dashoffset: 0;
    animation: none;
    opacity: .8;
  }
}

/* (2) '/'-COMMAND autocomplete menu. Anchored above the composer, palette-flavoured. */
.composer-shell { position: relative; }
.slash-menu {
  position: absolute; left: 0; right: 0; bottom: calc(100% + 6px);
  z-index: 40;
  background: var(--panel); border: 1px solid var(--border);
  border-radius: var(--radius); box-shadow: 0 12px 40px rgba(0,0,0,.45);
  overflow: hidden; max-height: 46vh; overflow-y: auto;
  padding: 6px;
}
.slash-item {
  display: flex; align-items: baseline; gap: 10px;
  padding: 8px 10px; border-radius: var(--radius-sm); cursor: pointer;
  border: 1px solid transparent;
}
.slash-item.active { background: var(--panel-2); border-color: var(--primary-35); }
.slash-item:hover { background: var(--panel-2); }
.slash-item .slash-name {
  font-family: var(--mono, monospace); font-weight: 600;
  color: var(--primary); flex-shrink: 0; min-width: 90px;
}
.slash-item .slash-desc {
  color: var(--muted); font-size: 12px;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* (3) UNDO on reversible AI action cards. */
.ai-action .aa-undo {
  justify-self: end;
  background: transparent; border: 1px solid var(--border);
  color: var(--muted); cursor: pointer;
  font: inherit; font-size: 11px;
  padding: 3px 9px; border-radius: 3px;
  transition: border-color .15s, color .15s;
}
.ai-action .aa-undo:hover { border-color: var(--primary); color: var(--primary); }
.ai-action.undone { opacity: .5; }
.ai-action.undone .aa-title { text-decoration: line-through; }

/* TASK-COMPLETE SPIKE FLOURISH (#13, Cluster C) — logo motif, one-shot.
   Uses the FREE .task::after (avoids the mobile .check::before hit-area collision). */
@media (prefers-reduced-motion: no-preference) {
  .task-completing::after {
    content: ''; position: absolute; left: 40px; top: 50%;
    width: 34px; height: 18px; transform: translateY(-50%);
    pointer-events: none; z-index: 3;
    background: var(--success);
    filter: drop-shadow(0 0 4px var(--success));
    clip-path: polygon(0 60%, 34% 60%, 44% 56%, 50% 0, 56% 56%, 66% 60%, 100% 60%, 100% 72%, 66% 72%, 55% 68%, 50% 22%, 45% 68%, 34% 72%, 0 72%);
    -webkit-mask: linear-gradient(90deg, #000 0 100%) left center / 0% 100% no-repeat;
            mask: linear-gradient(90deg, #000 0 100%) left center / 0% 100% no-repeat;
    animation: spikeBlip .5s var(--ease-out) forwards;
  }
}
@keyframes spikeBlip {
  0%   { -webkit-mask-size: 0% 100%;   mask-size: 0% 100%;   opacity: 1; }
  55%  { -webkit-mask-size: 100% 100%; mask-size: 100% 100%; opacity: 1; }
  100% { -webkit-mask-size: 100% 100%; mask-size: 100% 100%; opacity: 0; }
}
