/* Tender Radar dashboard styles.
   Colours are CSS variables. The page is light by default because
   index.html starts with <html data-theme="light">; the theme toggle
   (js/main.js) switches it to "dark" and remembers the choice. */

:root {
  --bg: #0B1420;
  --surface: #111C2B;
  --surface-2: #172538;
  --border: #223249;
  --text: #E6EEF7;
  --text-dim: #8CA3BD;
  --accent: #7DD3FC;
  --accent-dim: #1F4E73;
  --accent-ink: #7DD3FC;
  --on-accent: #062033;
  --warn: #F5B542;
  --danger: #EF5D5D;
  --focus: #7DD3FC;
}
:root:not([data-theme="light"]) { color-scheme: dark; }
:root[data-theme="light"] {
  --bg: #F3F8FD;
  --surface: #FFFFFF;
  --surface-2: #EAF2FA;
  --border: #D6E4F2;
  --text: #0F1B2A;
  --text-dim: #566A80;
  --accent: #38BDF8;
  --accent-dim: #DDF1FD;
  --accent-ink: #0B7DB8;
  --on-accent: #062033;
  --warn: #B5790A;
  --danger: #C43A3A;
  color-scheme: light;
}
@media (prefers-color-scheme: light) {
  :root:not([data-theme="dark"]) {
    --bg: #F3F8FD; --surface: #FFFFFF; --surface-2: #EAF2FA; --border: #D6E4F2;
    --text: #0F1B2A; --text-dim: #566A80; --accent: #38BDF8; --accent-dim: #DDF1FD; --accent-ink: #0B7DB8; --on-accent: #062033; --warn: #B5790A; --danger: #C43A3A;
    color-scheme: light;
  }
}

* { box-sizing: border-box; }
html { scrollbar-gutter: stable; } /* the page keeps its width when a short list removes the scrollbar */
html, body { margin: 0; padding: 0; }
body {
  background: var(--bg);
  color: var(--text);
  font-family: 'IBM Plex Sans', system-ui, sans-serif;
  min-height: 100vh;
  -webkit-font-smoothing: antialiased;
}
h1, h2, h3, .display { font-family: 'Space Grotesk', system-ui, sans-serif; }
.mono { font-family: 'IBM Plex Mono', monospace; }

a { color: var(--accent-ink); }
button:focus-visible, input:focus-visible, select:focus-visible, [tabindex]:focus-visible {
  outline: 2px solid var(--focus); outline-offset: 2px;
}

.shell { max-width: 1180px; margin: 0 auto; padding: 28px 20px 80px; }

/* Header */
header.top {
  display: flex; justify-content: space-between; align-items: flex-start;
  gap: 16px; flex-wrap: wrap; margin-bottom: 22px;
}
.brand { display: flex; align-items: center; gap: 12px; }
.brand-mark {
  width: 40px; height: 40px; border-radius: 10px;
  background: linear-gradient(155deg, var(--accent), var(--accent-dim));
  display: flex; align-items: center; justify-content: center;
  flex-shrink: 0;
}
.brand-mark svg { width: 22px; height: 22px; }
.brand h1 { font-size: 21px; margin: 0; letter-spacing: -0.01em; }
.brand .sub { font-size: 12.5px; color: var(--text-dim); margin-top: 2px; }
.top-actions { display: flex; gap: 8px; align-items: center; }
.icon-btn {
  background: var(--surface); border: 1px solid var(--border); color: var(--text-dim);
  width: 36px; height: 36px; border-radius: 9px; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  transition: border-color .15s, color .15s;
}
.icon-btn:hover { border-color: var(--accent); color: var(--accent-ink); }

/* Stat strip */
.stats { display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px; margin-bottom: 22px; }
.stat {
  background: var(--surface); border: 1px solid var(--border); border-radius: 12px;
  padding: 14px 16px;
}
.stat .num { font-family: 'Space Grotesk', sans-serif; font-size: 26px; font-weight: 600; line-height: 1; }
.stat .lbl { font-size: 12px; color: var(--text-dim); margin-top: 6px; }
.stat.urgent .num { color: var(--danger); }
.stat.new .num { color: var(--accent-ink); }
.stat.has-tip { position: relative; cursor: help; }
.stat .tip {
  display: none; position: absolute; left: 0; top: calc(100% + 6px); z-index: 20;
  min-width: 100%; max-width: 280px; padding: 8px 12px; border-radius: 10px;
  background: var(--surface); border: 1px solid var(--accent-dim); box-shadow: 0 6px 18px rgba(0,0,0,.18);
  font-size: 12.5px; line-height: 1.7; color: var(--text); white-space: nowrap;
}
.stat .tip::before { content: ''; position: absolute; left: 0; right: 0; top: -8px; height: 8px; } /* no gap to lose hover in */
.stat .tip a, .stat .tip span { display: block; }
.stat .tip a { color: var(--accent-ink); text-decoration: none; }
.stat .tip a:hover { text-decoration: underline; }
.stat.has-tip:hover .tip, .stat.has-tip:focus .tip, .stat.has-tip:focus-within .tip { display: block; }

/* New tenders banner */
.new-banner {
  display: none;
  background: var(--surface-2); border: 1px solid var(--accent-dim);
  border-left: 3px solid var(--accent);
  border-radius: 10px; padding: 12px 16px; margin-bottom: 18px;
  font-size: 13.5px; align-items: center; justify-content: space-between; gap: 12px;
}
.new-banner.show { display: flex; }
.new-banner button {
  background: none; border: 1px solid var(--border); color: var(--text-dim);
  border-radius: 7px; padding: 6px 10px; font-size: 12px; cursor: pointer;
}
.new-banner button:hover { color: var(--text); border-color: var(--text-dim); }
.new-toolbar {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  margin-bottom: 14px; font-size: 13px; color: var(--text-dim);
}
.new-toolbar button {
  background: var(--accent); color: var(--on-accent); border: 0; border-radius: 7px;
  padding: 7px 12px; font-size: 12.5px; font-weight: 600; cursor: pointer;
}
.new-toolbar button:hover { opacity: .85; }

/* Controls */
.controls {
  display: flex; gap: 10px; flex-wrap: wrap; margin-bottom: 18px; align-items: center;
}
.controls input[type="search"] {
  flex: 1; min-width: 180px;
  background: var(--surface); border: 1px solid var(--border); color: var(--text);
  padding: 9px 12px; border-radius: 9px; font-size: 13.5px; font-family: inherit;
}
.pills { display: flex; gap: 6px; flex-wrap: wrap; }
.pill {
  background: var(--surface); border: 1px solid var(--border); color: var(--text-dim);
  padding: 7px 12px; border-radius: 20px; font-size: 12.5px; cursor: pointer;
  white-space: nowrap; transition: all .15s;
}
.pill.active { background: var(--accent-dim); border-color: var(--accent); color: var(--text); }
/* "New": not a category but the unseen tenders, so it's set apart in the accent colour. */
.pill-new { color: var(--accent-ink); border-color: var(--accent-dim); font-weight: 600; }
.stat.clickable { cursor: pointer; transition: border-color .15s; }
.stat.clickable:hover { border-color: var(--accent); }
.sortsel {
  background: var(--surface); border: 1px solid var(--border); color: var(--text);
  padding: 8px 10px; border-radius: 9px; font-size: 12.5px; font-family: inherit; cursor: pointer;
}

/* Value row: the label and a minimum-value slider, shown only while sorting by value. */
.value-row { margin-top: 28px; gap: 12px; justify-content: flex-end; } /* right-aligned, with room below the category pills */
.value-row[hidden] { display: none; }
.vf-label { font-size: 12.5px; color: var(--text-dim); }
.vf-slider {
  display: flex; align-items: center; gap: 12px; box-sizing: border-box; height: 36px; width: 300px;
  padding: 0 14px; background: var(--surface); border: 1px solid var(--border); border-radius: 9px;
}
.vf-slider input[type="range"] { flex: 1; min-width: 0; margin: 0; accent-color: var(--accent); cursor: pointer; }
.vf-slider output { width: 84px; text-align: right; font-size: 12.5px; font-weight: 600; color: var(--text); white-space: nowrap; }

/* Groups & cards */
.group { margin-bottom: 28px; }
.group-head {
  display: flex; align-items: baseline; gap: 10px; margin-bottom: 12px;
  padding-bottom: 8px; border-bottom: 1px solid var(--border);
}
.group-head h2 { font-size: 15px; margin: 0; }
.group-head .count { font-size: 12px; color: var(--text-dim); }

.card-grid { display: grid; grid-template-columns: 1fr; gap: 14px; }
.card {
  --cat: var(--accent);
  position: relative; overflow: visible;
  display: grid; grid-template-columns: 44px 1fr auto; column-gap: 14px; row-gap: 8px; align-items: start;
  background: var(--surface); border: 1px solid var(--border); border-radius: 14px;
  padding: 13px 18px 10px;
}
.card.urgent { border-left: 3px solid var(--danger); }
.card.soon { border-left: 3px solid var(--warn); }
.card.isnew::before {
  content: 'NEW'; position: absolute; top: -1px; left: 16px; transform: translateY(-50%);
  background: var(--accent); color: var(--on-accent); font-size: 10px; font-weight: 700;
  letter-spacing: .05em; padding: 2px 8px; border-radius: 6px;
}

/* Category icon tile, tinted with the category's own hue */
.card-icon {
  width: 44px; height: 44px; border-radius: 13px; display: flex; align-items: center; justify-content: center;
  color: var(--cat);
  background: linear-gradient(145deg, color-mix(in srgb, var(--cat) 22%, transparent), color-mix(in srgb, var(--cat) 6%, transparent));
  border: 1px solid color-mix(in srgb, var(--cat) 30%, transparent);
  box-shadow: inset 0 1px 0 color-mix(in srgb, #fff 18%, transparent);
}
.card-main { min-width: 0; }
.card-top-row { display: flex; align-items: center; gap: 8px; margin-bottom: 5px; flex-wrap: wrap; }
.cat-badge {
  font-size: 10.5px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; white-space: nowrap;
  color: color-mix(in srgb, var(--cat) 62%, var(--text));
  background: color-mix(in srgb, var(--cat) 14%, transparent);
  border: 1px solid color-mix(in srgb, var(--cat) 24%, transparent);
  border-radius: 20px; padding: 2px 10px;
}
/* Titles are clamped to 3 lines so every card has the same shape,
   whatever the source's title length; the full title is in the tooltip. */
.card-desc {
  font-size: 14.5px; font-weight: 500; line-height: 1.45; margin-bottom: 8px;
  display: -webkit-box; -webkit-line-clamp: 3; line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden;
}
.card-meta { display: flex; gap: 8px; flex-wrap: wrap; }
.chip {
  display: inline-flex; align-items: center; gap: 6px; padding: 2px 10px 2px 8px; border-radius: 20px;
  background: var(--surface-2); border: 1px solid var(--border); font-size: 12px; color: var(--text-dim);
}
.chip svg { flex-shrink: 0; opacity: .8; }

/* Due date block (right) */
.card-due { text-align: right; white-space: nowrap; min-width: 92px; }
.due-badge {
  display: inline-block; font-size: 12.5px; font-weight: 600; padding: 5px 11px; border-radius: 9px;
  background: var(--surface-2); border: 1px solid var(--border);
}
.due-badge.urgent { background: rgba(239,93,93,0.12); border-color: var(--danger); color: var(--danger); }
.due-badge.soon { background: rgba(245,181,66,0.12); border-color: var(--warn); color: var(--warn); }
.due-days { font-size: 11.5px; color: var(--text-dim); margin-top: 4px; }
.due-bar { height: 4px; margin: 5px 0 0 auto; width: 84px; border-radius: 4px; background: var(--border); overflow: hidden; }
.due-bar i { display: block; height: 100%; border-radius: 4px; background: var(--accent); transition: width .8s var(--ease, ease); }
.due-bar.urgent i { background: var(--danger); }
.due-bar.soon i { background: var(--warn); }

/* Footer: value on the left, the action on the right */
.card-foot {
  grid-column: 1 / -1; display: flex; align-items: center; justify-content: space-between; gap: 14px;
  padding-top: 8px; border-top: 1px dashed var(--border);
}
.card-value { display: flex; align-items: baseline; gap: 8px; min-width: 0; }
.cv-label { font-size: 10.5px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase; color: var(--text-dim); }
.cv-amt { font-family: 'Space Grotesk', system-ui, sans-serif; font-size: 16px; font-weight: 600; letter-spacing: -.01em; }
.cv-amt.nd { font-family: inherit; font-size: 13.5px; font-weight: 500; color: var(--text-dim); }
.card-action-btn {
  display: inline-flex; align-items: center; gap: 8px; margin-left: auto;
  background: var(--accent-dim); border: 1px solid transparent; color: var(--accent-ink);
  padding: 6px 13px; border-radius: 9px; font-size: 12.5px; font-weight: 600;
  cursor: pointer; white-space: nowrap; font-family: inherit;
}
.card-action-btn .arrow { display: inline-block; transition: transform .25s var(--ease, ease); }
.card:hover .card-action-btn .arrow { transform: translate(2px, -2px); }
.card:hover .card-action-btn, .card-action-btn:focus-visible { border-color: var(--accent); }

@media (max-width: 640px) {
  .card { grid-template-columns: 44px minmax(0, 1fr); column-gap: 12px; padding: 13px 14px 10px; }
  .card-icon { width: 44px; height: 44px; }
  .card-due { grid-column: 2; text-align: left; display: flex; align-items: center; gap: 10px; min-width: 0; flex-wrap: wrap; }
  .due-days, .due-bar { margin: 0; }
  .card-foot { flex-wrap: wrap; }
}

.empty { text-align: center; padding: 50px 20px; color: var(--text-dim); font-size: 13.5px; }

footer.note {
  margin-top: 30px; padding-top: 18px; border-top: 1px solid var(--border);
  font-size: 12px; color: var(--text-dim); line-height: 1.6;
}

@media (max-width: 640px) {
  .stats { grid-template-columns: repeat(2, 1fr); }
}

/* Toasts */
.toast-stack {
  position: fixed; top: 18px; right: 18px; z-index: 100;
  display: flex; flex-direction: column; gap: 10px;
  width: min(340px, calc(100vw - 36px));
}
.toast {
  position: relative; background: var(--surface); border: 1px solid var(--border);
  border-left: 3px solid var(--accent); border-radius: 10px;
  padding: 12px 26px 12px 14px; box-shadow: 0 8px 24px rgba(0,0,0,.28);
  animation: toast-in .18s ease-out;
}
.toast.due { border-left-color: var(--warn); }
.toast.error { border-left-color: var(--danger); }
.toast strong { display: block; margin-bottom: 4px; font-size: 13px; }
.toast p { margin: 0; color: var(--text-dim); font-size: 12.5px; line-height: 1.4; }
.toast-list { list-style: none; margin: 8px 0 0; padding: 0; max-height: 50vh; overflow-y: auto; }
.toast-list li {
  display: flex; flex-direction: column; gap: 2px;
  padding: 7px 0; border-top: 1px solid var(--border);
  color: var(--text-dim); font-size: 12.5px; line-height: 1.4;
}
.toast-list li:first-child { border-top: none; padding-top: 0; }
.toast-item-title { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; color: var(--text); }
.toast-meta { font-size: 11.5px; color: var(--warn); }
.toast-list .toast-more { font-style: italic; }
.toast-close {
  position: absolute; top: 8px; right: 8px; background: none; border: none;
  color: var(--text-dim); font-size: 16px; line-height: 1; cursor: pointer; padding: 2px;
}
.toast-close:hover { color: var(--text); }
@keyframes toast-in { from { opacity: 0; transform: translateY(-6px); } to { opacity: 1; transform: translateY(0); } }

.icon-btn.active { border-color: var(--accent); color: var(--accent-ink); }
.icon-btn.spinning svg { animation: icon-spin .8s linear infinite; }
@keyframes icon-spin { to { transform: rotate(360deg); } }

/* ===========================================================================
   Polish: ambient background, depth and motion.
   Everything below moves things with transform / opacity / shadow only, so no
   animation or hover ever changes the size or position of anything else on the
   page. It all switches off for visitors who ask for reduced motion (last rule).
   =========================================================================== */
:root {
  --ease: cubic-bezier(.2, .8, .2, 1);
  --glow: color-mix(in srgb, var(--accent) 24%, transparent);
  --shadow: 0 1px 2px rgba(15, 27, 42, .05), 0 8px 24px rgba(15, 27, 42, .06);
  --shadow-up: 0 2px 4px rgba(15, 27, 42, .06), 0 16px 36px color-mix(in srgb, var(--accent) 16%, rgba(15, 27, 42, .1));
}
:root:not([data-theme="light"]) {
  --shadow: 0 1px 2px rgba(0, 0, 0, .3), 0 10px 28px rgba(0, 0, 0, .28);
  --shadow-up: 0 2px 4px rgba(0, 0, 0, .35), 0 18px 40px color-mix(in srgb, var(--accent) 14%, rgba(0, 0, 0, .4));
}

/* Ambient background: two soft accent glows behind the page */
body {
  background:
    radial-gradient(900px 440px at 6% -10%, color-mix(in srgb, var(--accent) 15%, transparent), transparent 70%),
    radial-gradient(760px 420px at 104% 2%, color-mix(in srgb, var(--accent) 9%, transparent), transparent 70%),
    var(--bg);
  background-attachment: fixed;
}

/* Smooth theme switch */
body, .stat, .card, .pill, .sortsel, .icon-btn, .controls input[type="search"], .vf-slider, .toast, .due-badge, .cat-badge {
  transition: background-color .3s var(--ease), border-color .25s var(--ease), color .25s var(--ease),
              box-shadow .25s var(--ease), transform .25s var(--ease), opacity .25s var(--ease);
}

@keyframes rise { from { opacity: 0; transform: translateY(14px); } to { opacity: 1; transform: translateY(0); } }
@keyframes pulse-dot { 0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--danger) 55%, transparent); } 50% { box-shadow: 0 0 0 6px transparent; } }
@keyframes ring-out { 0% { opacity: .55; transform: scale(.92); } 70%, 100% { opacity: 0; transform: scale(1.3); } }
@keyframes bolt-beat { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.14); } }
@keyframes shimmer { to { background-position: -200% 0; } }
@keyframes badge-pulse { 0%, 100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--danger) 35%, transparent); } 50% { box-shadow: 0 0 0 5px transparent; } }

/* Header */
.brand-mark { position: relative; box-shadow: 0 6px 18px var(--glow); }
.brand-mark::after {
  content: ''; position: absolute; inset: -4px; border-radius: 14px;
  border: 1.5px solid var(--accent); opacity: 0; animation: ring-out 3s var(--ease) infinite;
}
.brand-mark svg { animation: bolt-beat 3s ease-in-out infinite; }
.brand h1 {
  background: linear-gradient(90deg, var(--text) 35%, var(--accent));
  -webkit-background-clip: text; background-clip: text; color: transparent;
}
.icon-btn { box-shadow: var(--shadow); }
.icon-btn:hover { transform: translateY(-2px); box-shadow: 0 6px 16px var(--glow); }
.icon-btn:active { transform: scale(.94); }
.icon-btn svg { transition: transform .45s var(--ease); }
#themeToggle:hover svg { transform: rotate(60deg); }
#notifyToggle:hover svg { transform: rotate(14deg); }

/* Stat tiles */
.stat { position: relative; box-shadow: var(--shadow); animation: rise .55s var(--ease) backwards; }
.stat:nth-child(2) { animation-delay: .06s; }
.stat:nth-child(3) { animation-delay: .12s; }
.stat:nth-child(4) { animation-delay: .18s; }
.stat::before {
  content: ''; position: absolute; left: 16px; right: 16px; top: -1px; height: 2px; border-radius: 2px;
  background: linear-gradient(90deg, var(--accent), transparent);
  transform: scaleX(.22); transform-origin: left; transition: transform .5s var(--ease);
}
.stat:hover { transform: translateY(-3px); border-color: color-mix(in srgb, var(--accent) 45%, var(--border)); box-shadow: var(--shadow-up); }
.stat:hover::before { transform: scaleX(1); }
.stat.urgent::before { background: linear-gradient(90deg, var(--danger), transparent); }
.stat.urgent .num::after {
  content: ''; display: inline-block; width: 7px; height: 7px; border-radius: 50%; background: var(--danger);
  margin-left: 9px; vertical-align: middle; animation: pulse-dot 1.8s infinite;
}
.stat .num { font-variant-numeric: tabular-nums; }

/* Controls */
.controls input[type="search"], .sortsel { box-shadow: var(--shadow); }
.controls input[type="search"]:hover, .sortsel:hover { border-color: color-mix(in srgb, var(--accent) 40%, var(--border)); }
.controls input[type="search"]:focus, .sortsel:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 4px var(--glow); }

/* Pills */
.pill:hover { transform: translateY(-2px); border-color: color-mix(in srgb, var(--accent) 50%, var(--border)); color: var(--text); box-shadow: 0 6px 14px var(--glow); }
.pill:active { transform: scale(.95); }
.pill.active {
  background: linear-gradient(135deg, color-mix(in srgb, var(--accent) 24%, var(--surface)), var(--accent-dim));
  box-shadow: 0 5px 16px var(--glow); font-weight: 600;
}

/* Value slider: custom track (filled up to the thumb, set from js/main.js) and thumb */
.value-row:not([hidden]) { animation: rise .4s var(--ease) backwards; }
.vf-slider { box-shadow: var(--shadow); }
.vf-slider:hover { border-color: color-mix(in srgb, var(--accent) 45%, var(--border)); }
.vf-slider input[type="range"] { -webkit-appearance: none; appearance: none; height: 22px; background: transparent; }
.vf-slider input[type="range"]::-webkit-slider-runnable-track {
  height: 6px; border-radius: 6px;
  background: linear-gradient(90deg, var(--accent) var(--p, 0%), color-mix(in srgb, var(--text-dim) 26%, transparent) var(--p, 0%));
}
.vf-slider input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none; width: 18px; height: 18px; margin-top: -6px; border-radius: 50%;
  background: #fff; border: 3px solid var(--accent); box-shadow: 0 2px 10px var(--glow); transition: transform .15s var(--ease);
}
.vf-slider input[type="range"]::-webkit-slider-thumb:hover { transform: scale(1.18); }
.vf-slider input[type="range"]:active::-webkit-slider-thumb { transform: scale(1.28); }
.vf-slider input[type="range"]::-moz-range-track { height: 6px; border-radius: 6px; background: color-mix(in srgb, var(--text-dim) 26%, transparent); }
.vf-slider input[type="range"]::-moz-range-progress { height: 6px; border-radius: 6px; background: var(--accent); }
.vf-slider input[type="range"]::-moz-range-thumb {
  width: 12px; height: 12px; border-radius: 50%; background: #fff; border: 3px solid var(--accent); box-shadow: 0 2px 10px var(--glow);
}
.vf-slider input[type="range"]:focus-visible { outline: none; }
.vf-slider input[type="range"]:focus-visible::-webkit-slider-thumb { box-shadow: 0 0 0 5px var(--glow); }

/* Group headings */
.group-head h2::before {
  content: ''; display: inline-block; width: 4px; height: 15px; margin-right: 9px; vertical-align: -2px;
  border-radius: 2px; background: linear-gradient(180deg, var(--accent), var(--accent-dim));
}
.group-head .count { background: var(--surface-2); border: 1px solid var(--border); border-radius: 20px; padding: 2px 10px; }

/* Cards: rise in (when the list was just changed), lift on hover, accent bar sweeps in */
.card { box-shadow: var(--shadow); }
#groups.enter .card { animation: rise .5s var(--ease) backwards; animation-delay: calc(var(--i, 0) * 32ms); }
.card::after {
  content: ''; position: absolute; left: -1px; top: 12px; bottom: 12px; width: 3px; border-radius: 3px;
  background: var(--cat, var(--accent)); transform: scaleY(0); transition: transform .3s var(--ease); pointer-events: none;
}
.card.urgent::after, .card.soon::after { display: none; }
.card.clickable { transition: background-color .3s var(--ease), border-color .25s var(--ease), box-shadow .3s var(--ease), transform .3s var(--ease); }
.card.clickable:hover { transform: translateY(-3px); box-shadow: var(--shadow-up); }
.card.clickable:hover::after { transform: scaleY(1); }
.card.clickable:active { transform: translateY(-1px) scale(.995); }
.card.isnew::before {
  background: linear-gradient(110deg, var(--accent) 30%, color-mix(in srgb, var(--accent) 45%, #fff) 50%, var(--accent) 70%);
  background-size: 200% 100%; animation: shimmer 2.6s linear infinite;
}
.card.urgent .due-badge { animation: badge-pulse 2s infinite; }
.cat-badge { transition: transform .25s var(--ease); }
.card:hover .card-icon { transform: scale(1.06) rotate(-4deg); }
.card-icon { transition: transform .35s var(--ease); }
.card-action-btn { transition: background-color .25s var(--ease), color .25s var(--ease), border-color .25s var(--ease), box-shadow .25s var(--ease), transform .2s var(--ease); }
.card:hover .card-action-btn, .card-action-btn:hover { background: var(--accent); color: var(--on-accent); box-shadow: 0 6px 16px var(--glow); }
.card-action-btn:active { transform: scale(.95); }

/* Loading skeleton (replaced by the real list as soon as data arrives) */
.skeleton { height: 96px; border-radius: 12px; margin-bottom: 10px; border: 1px solid var(--border);
  background: linear-gradient(100deg, var(--surface) 30%, var(--surface-2) 50%, var(--surface) 70%);
  background-size: 200% 100%; animation: shimmer 1.4s linear infinite; }

/* Toasts slide in from the right */
@keyframes toast-in { from { opacity: 0; transform: translateX(28px) scale(.97); } to { opacity: 1; transform: translateX(0) scale(1); } }
.toast { animation: toast-in .4s var(--ease); }

/* Back to top */
.to-top {
  position: fixed; right: 20px; bottom: 22px; z-index: 40; width: 42px; height: 42px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center; cursor: pointer; font-size: 18px; line-height: 1;
  background: var(--accent); color: var(--on-accent); border: 0; box-shadow: 0 8px 22px var(--glow);
  opacity: 0; transform: translateY(14px) scale(.9); pointer-events: none;
  transition: opacity .3s var(--ease), transform .3s var(--ease), box-shadow .25s var(--ease);
}
.to-top.show { opacity: 1; transform: none; pointer-events: auto; }
.to-top.show:hover { transform: translateY(-3px); box-shadow: 0 12px 28px var(--glow); }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important; animation-iteration-count: 1 !important;
    transition-duration: .001ms !important; scroll-behavior: auto !important;
  }
}

/* ===========================================================================
   More effects: drifting aurora, cursor glow, spotlight + tilt, ripples,
   scroll progress and reveal, radar empty state, theme-switch reveal.
   Again transform / opacity / shadow only: nothing here moves the layout.
   =========================================================================== */

/* Drifting aurora behind everything */
body::before {
  content: ''; position: fixed; inset: -25%; z-index: -1; pointer-events: none;
  background:
    radial-gradient(34% 30% at 22% 28%, color-mix(in srgb, var(--accent) 16%, transparent), transparent 70%),
    radial-gradient(30% 34% at 78% 24%, color-mix(in srgb, var(--accent) 10%, transparent), transparent 70%),
    radial-gradient(36% 30% at 56% 82%, color-mix(in srgb, var(--accent) 9%, transparent), transparent 70%);
  filter: blur(30px);
  animation: aurora 26s ease-in-out infinite alternate;
}
@keyframes aurora {
  0%   { transform: translate3d(0, 0, 0) rotate(0deg) scale(1); }
  50%  { transform: translate3d(3%, 4%, 0) rotate(6deg) scale(1.08); }
  100% { transform: translate3d(-4%, 2%, 0) rotate(-5deg) scale(1.02); }
}

/* Soft glow that trails the cursor (moved by js/fx.js) */
.cursor-glow {
  position: fixed; left: 0; top: 0; z-index: 0; width: 520px; height: 520px; border-radius: 50%;
  pointer-events: none; opacity: 0; transition: opacity .5s var(--ease);
  background: radial-gradient(closest-side, color-mix(in srgb, var(--accent) 28%, transparent), transparent);
  will-change: transform;
}
.cursor-glow.on { opacity: 1; }
.shell { position: relative; z-index: 1; }

/* Scroll progress bar */
.scroll-progress {
  position: fixed; left: 0; top: 0; right: 0; height: 3px; z-index: 120; pointer-events: none;
  background: linear-gradient(90deg, var(--accent-dim), var(--accent)); transform: scaleX(0); transform-origin: left;
  box-shadow: 0 0 10px var(--glow);
}

/* Header drops in */
header.top { animation: rise .7s var(--ease) backwards; }

/* Spotlight under the cursor on cards and stat tiles; slight tilt on cards */
.card.clickable:hover, .stat:hover {
  background-image: radial-gradient(320px circle at var(--mx, 50%) var(--my, 0%), color-mix(in srgb, var(--accent) 24%, transparent), transparent 62%);
}
.card.clickable { transform-style: preserve-3d; }
.card.clickable:hover {
  transform: translateY(-3px) perspective(1000px) rotateX(var(--rx, 0deg)) rotateY(var(--ry, 0deg));
}
.card.clickable:hover .card-action-btn { transform: translateZ(0); }

/* Header buttons lean towards the cursor */
.icon-btn:hover { transform: translate(var(--tx, 0px), calc(var(--ty, 0px) - 2px)); }

/* Ripples */
.pill, .icon-btn, .card-action-btn, .new-toolbar button, .to-top { position: relative; overflow: hidden; }
.to-top { position: fixed; }
.ripple {
  position: absolute; border-radius: 50%; pointer-events: none;
  background: color-mix(in srgb, currentColor 35%, transparent); transform: scale(0); opacity: .55;
  animation: ripple .65s var(--ease) forwards;
}
@keyframes ripple { to { transform: scale(1); opacity: 0; } }

/* Cards below the first screen fade up as they scroll into view */
#groups.enter .card.reveal { animation: none; }
.card.reveal { opacity: 0; transform: translateY(22px); }
.card.reveal.in { opacity: 1; transform: none; transition: opacity .55s var(--ease), transform .55s var(--ease); }
.card.reveal.in.clickable:hover { transform: translateY(-3px) perspective(1000px) rotateX(var(--rx, 0deg)) rotateY(var(--ry, 0deg)); }

/* Urgent cards: the red edge glows when you hover */
.card.urgent.clickable:hover { box-shadow: var(--shadow-up), -6px 0 18px -6px color-mix(in srgb, var(--danger) 60%, transparent); }

/* Live "last synced" dot */
#syncTime::before {
  content: ''; display: inline-block; width: 7px; height: 7px; margin-right: 8px; border-radius: 50%;
  background: var(--accent); vertical-align: 1px; animation: live-dot 2.2s ease-out infinite;
}
@keyframes live-dot { 0% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--accent) 60%, transparent); } 100% { box-shadow: 0 0 0 9px transparent; } }

/* Empty state: a radar that sweeps */
.radar {
  position: relative; width: 96px; height: 96px; margin: 0 auto 18px; border-radius: 50%;
  border: 1.5px solid color-mix(in srgb, var(--accent) 55%, transparent);
  background:
    radial-gradient(circle, color-mix(in srgb, var(--accent) 80%, transparent) 0 2px, transparent 3px),
    repeating-radial-gradient(circle, transparent 0 15px, color-mix(in srgb, var(--accent) 30%, transparent) 15px 16px);
  box-shadow: 0 0 28px var(--glow);
  overflow: hidden;
}
.radar::before {
  content: ''; position: absolute; inset: 0; border-radius: 50%;
  background: conic-gradient(from 0deg, transparent 0 292deg, color-mix(in srgb, var(--accent) 55%, transparent) 360deg);
  animation: radar-sweep 2.8s linear infinite;
}
.radar::after {
  content: ''; position: absolute; left: 64%; top: 30%; width: 6px; height: 6px; border-radius: 50%;
  background: var(--accent); box-shadow: 0 0 10px var(--accent); animation: blip 2.8s ease-out infinite;
}
@keyframes radar-sweep { to { transform: rotate(360deg); } }
@keyframes blip { 0%, 30% { opacity: 0; transform: scale(.4); } 45% { opacity: 1; transform: scale(1.2); } 100% { opacity: 0; transform: scale(1); } }
.empty p { margin: 0; }

/* Theme switch: the new theme grows out of the toggle button (js/fx.js drives the clip) */
::view-transition-old(root), ::view-transition-new(root) { animation: none; mix-blend-mode: normal; }
::view-transition-old(root) { z-index: 1; }
::view-transition-new(root) { z-index: 2; }

@media (prefers-reduced-motion: reduce) {
  body::before, .cursor-glow, .radar::before, .radar::after, #syncTime::before { animation: none !important; }
  .card.reveal { opacity: 1; transform: none; }
}
@media (hover: none), (pointer: coarse) { .cursor-glow { display: none; } }

/* The source-portals list pops out under its tile: lift the hovered tile above the controls and
   pills below it. (Pills and buttons became positioned for their click ripples, so without this
   they painted over the list.) */
.stat:hover, .stat:focus-within { z-index: 30; }

/* Stat tile icons */
.stat-ic {
  position: absolute; right: 14px; top: 14px; width: 34px; height: 34px; border-radius: 11px;
  display: flex; align-items: center; justify-content: center; color: var(--ic, var(--accent-ink));
  background: color-mix(in srgb, var(--ic, var(--accent)) 14%, transparent);
  border: 1px solid color-mix(in srgb, var(--ic, var(--accent)) 22%, transparent);
  transition: transform .35s var(--ease);
}
.stat:hover .stat-ic { transform: scale(1.1) rotate(-6deg); }
.stat.urgent .stat-ic { --ic: var(--danger); }

/* ===========================================================================
   Even more: particle network, cursor ring, click sparks, animated borders,
   idle motion on icons and badges, scrollbar and selection polish.
   Still transform / opacity / shadow only; off for reduced motion and touch.
   =========================================================================== */

/* Particle network canvas (drawn by js/fx.js) */
.fx-canvas { position: fixed; inset: 0; width: 100%; height: 100%; z-index: 0; pointer-events: none; }

/* Cursor ring + dot */
.cursor-dot {
  position: fixed; left: 0; top: 0; z-index: 300; pointer-events: none; border-radius: 50%; opacity: 0;
  transition: opacity .3s var(--ease), width .25s var(--ease), height .25s var(--ease), background-color .25s var(--ease), border-color .25s var(--ease);
}
.cursor-dot { width: 6px; height: 6px; background: var(--accent); }
.cursor-dot.on { opacity: 1; }

/* Click sparks */
.spark {
  position: fixed; z-index: 310; width: 5px; height: 5px; margin: -2.5px 0 0 -2.5px; border-radius: 50%; pointer-events: none;
  background: var(--accent); box-shadow: 0 0 8px var(--accent); animation: spark .6s var(--ease) forwards;
}
@keyframes spark { to { transform: translate(var(--dx), var(--dy)) scale(.2); opacity: 0; } }

/* Active pill: a light that circles its border */
@property --ang { syntax: '<angle>'; inherits: false; initial-value: 0deg; }
@keyframes spin-ang { to { --ang: 360deg; } }
.pill.active {
  border: 1px solid transparent;
  background:
    linear-gradient(var(--surface), var(--surface)) padding-box,
    linear-gradient(135deg, color-mix(in srgb, var(--accent) 24%, var(--surface)), var(--accent-dim)) padding-box,
    conic-gradient(from var(--ang), var(--accent), transparent 28%, var(--accent) 55%, transparent 80%, var(--accent)) border-box;
  animation: spin-ang 4s linear infinite;
}

/* Title: the gradient slowly flows */
.brand h1 { background-size: 220% 100%; animation: title-flow 8s ease-in-out infinite alternate; }
@keyframes title-flow { from { background-position: 0% 0; } to { background-position: 100% 0; } }

/* Header fades slightly as the page scrolls */
header.top { opacity: max(.35, calc(1 - var(--scroll, 0) / 900)); }

/* Idle motion: stat icons float, the urgent clock wiggles now and then, the sparkle twinkles */
@keyframes bob { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-3px); } }
@keyframes wiggle { 0%, 82%, 100% { transform: rotate(0); } 86% { transform: rotate(-14deg); } 90% { transform: rotate(12deg); } 94% { transform: rotate(-8deg); } 97% { transform: rotate(4deg); } }
@keyframes twinkle { 0%, 100% { transform: scale(1) rotate(0); opacity: 1; } 50% { transform: scale(1.18) rotate(12deg); opacity: .75; } }
.stat-ic { animation: bob 4s ease-in-out infinite; }
.stat:nth-child(2) .stat-ic { animation-delay: -1s; }
.stat:nth-child(3) .stat-ic { animation-delay: -2s; }
.stat:nth-child(4) .stat-ic { animation-delay: -3s; }
.stat:hover .stat-ic { animation: none; }
.stat.urgent .stat-ic svg { animation: wiggle 5s ease-in-out infinite; transform-origin: 50% 20%; }
.stat.new .stat-ic svg { animation: twinkle 2.6s ease-in-out infinite; }

/* Stat tiles: a slow sheen sweeps across on hover */
.stat { overflow: visible; }
.stat::after {
  content: ''; position: absolute; inset: 0; border-radius: inherit; pointer-events: none; opacity: 0;
  background: linear-gradient(105deg, transparent 35%, color-mix(in srgb, #fff 22%, transparent) 50%, transparent 65%);
  background-size: 250% 100%; background-position: 120% 0;
}
.stat:hover::after { opacity: 1; background-position: -60% 0; transition: background-position .9s var(--ease), opacity .2s; }

/* Group headings and counts */
.group-head h2::before { animation: bar-grow .6s var(--ease) backwards; transform-origin: bottom; }
@keyframes bar-grow { from { transform: scaleY(0); } }
.group-head .count { transition: transform .25s var(--ease), border-color .25s var(--ease); }
.group-head:hover .count { transform: scale(1.08); border-color: var(--accent); }

/* Cards: category badge hops, icon glows, action arrow nudges */
.card.clickable:hover .cat-badge { transform: translateY(-2px); }
.card:hover .card-icon { box-shadow: 0 0 18px var(--glow); }
.card-action-btn svg, .card-action-btn span { transition: transform .25s var(--ease); }
.card:hover .card-action-btn svg { transform: translateX(3px); }

/* Search box: a glowing underline grows when focused */
.controls input[type="search"]:focus { animation: focus-pop .35s var(--ease); }
@keyframes focus-pop { 0% { transform: scale(1); } 50% { transform: scale(1.012); } 100% { transform: scale(1); } }

/* Back-to-top arrow bobs */
.to-top.show { animation: bob 2.4s ease-in-out infinite; }
.to-top.show:hover { animation: none; }

/* Footer */
footer.note { animation: rise .8s var(--ease) .4s backwards; }

/* Polish: accent scrollbar, text selection, keyboard focus ring */
html { scrollbar-color: color-mix(in srgb, var(--accent) 55%, transparent) transparent; scrollbar-width: thin; }
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-thumb { background: color-mix(in srgb, var(--accent) 50%, transparent); border-radius: 10px; border: 2px solid transparent; background-clip: padding-box; }
::-webkit-scrollbar-thumb:hover { background: var(--accent); background-clip: padding-box; border: 2px solid transparent; }
::selection { background: color-mix(in srgb, var(--accent) 35%, transparent); }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; transition: outline-offset .2s var(--ease); }

@media (prefers-reduced-motion: reduce) {
  .fx-canvas, .cursor-dot, .spark { display: none !important; }
  .pill.active, .brand h1, .stat-ic, .stat-ic svg, .to-top.show { animation: none !important; }
}
@media (hover: none), (pointer: coarse) { .cursor-dot { display: none; } }

/* The dot replaces the arrow (class set by js/fx.js once a mouse moves) */
html.no-cursor, html.no-cursor * { cursor: none !important; }
.cursor-dot { width: 6px; height: 6px; box-shadow: 0 0 6px var(--glow); }

/* A filter or sort change fades the cards in gently (no rise, no stagger), so it never feels like a reload */
#groups.enter .card { animation: soft-in .22s ease-out backwards; animation-delay: 0s; }
@keyframes soft-in { from { opacity: 0; } to { opacity: 1; } }
