/* Brand numeral face — bundled locally (no network dependency) and applied
   only to display numerals: the timer clock, stat values, and the donut
   center. Body text stays on the system stack. */
@font-face {
  font-family: "Space Mono";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("fonts/space-mono-700.woff2") format("woff2");
}

:root {
  color-scheme: light;

  --surface-1: #fcfcfb;
  --page-plane: #f9f9f7;
  --text-primary: #0b0b0b;
  --text-secondary: #52514e;
  --muted: #898781;
  --gridline: #e1e0d9;
  --baseline: #c3c2b7;
  --border: rgba(11, 11, 11, 0.1);

  /* Signature accent: deep teal, deliberately distinct from every hue in
     topic slots 1-8 so UI chrome (buttons, nav, timeline bars, selections)
     never masquerades as a topic's color. cat-1 keeps the old blue — that
     one belongs to topics. */
  --series-accent: #0f766e;

  --cat-1: #2a78d6;
  --cat-2: #1baf7a;
  --cat-3: #eda100;
  --cat-4: #008300;
  --cat-5: #4a3aa7;
  --cat-6: #e34948;
  --cat-7: #e87ba4;
  --cat-8: #eb6834;
  /* 9-16 exist so topic colors stop repeating until 17+ simultaneous topics;
     includes two muted earth tones (15, 16) rather than 16 straight vivid
     hues, to keep the larger set from reading as a rainbow. */
  --cat-9: #25979d;
  --cat-10: #ad9a1f;
  --cat-11: #5e9130;
  --cat-12: #4e57bc;
  --cat-13: #9243b1;
  --cat-14: #be3798;
  --cat-15: #9b5e3b;
  --cat-16: #547083;

  /* Soft tints of the categorical hues — same hue order (so each topic keeps
     its identity), gentler saturation for the topic-distribution donut. */
  --cat-soft-1: #7db0ea;
  --cat-soft-2: #66c9a6;
  --cat-soft-3: #f0c65f;
  --cat-soft-4: #6fb86f;
  --cat-soft-5: #a99ce0;
  --cat-soft-6: #ef9a99;
  --cat-soft-7: #f0aecb;
  --cat-soft-8: #f0a17f;
  --cat-soft-9: #89ced2;
  --cat-soft-10: #d7ca75;
  --cat-soft-11: #9cc577;
  --cat-soft-12: #a6aad9;
  --cat-soft-13: #caa6d9;
  --cat-soft-14: #d897c6;
  --cat-soft-15: #c59d87;
  --cat-soft-16: #9db1be;

  /* Display numerals only — everything else stays system-ui. */
  --font-display: "Space Mono", ui-monospace, "SF Mono", Menlo, monospace;

  /* Type scale — every font-size in the app draws from this list. Tiers are
     named by role (2xs = tiny meta labels) rather than raw px, since the
     role is what a new component actually needs to match. */
  --font-2xs: 11px;
  --font-xs: 12px;
  --font-sm: 13px;
  --font-base: 14px;
  --font-md: 15px;
  --font-lg: 16px;
  --font-xl: 18px;
  --font-2xl: 20px;
  --font-3xl: 22px;
  --font-4xl: 28px;
  --font-hero: 56px;

  /* Spacing scale — every padding/margin/gap draws from this list. Named by
     literal px value (spacing is interchangeable, unlike type sizes, so the
     number itself is the useful label). */
  --space-1: 1px;
  --space-2: 2px;
  --space-3: 3px;
  --space-4: 4px;
  --space-6: 6px;
  --space-7: 7px;
  --space-8: 8px;
  --space-10: 10px;
  --space-12: 12px;
  --space-14: 14px;
  --space-16: 16px;
  --space-18: 18px;
  --space-20: 20px;
  --space-22: 22px;
  --space-24: 24px;
  --space-28: 28px;
  --space-30: 30px;
  --space-32: 32px;
  --space-48: 48px;
  --space-64: 64px;
}

/* Applied by theme.js — either because the system is in dark mode and the
   user hasn't overridden it, or because they explicitly chose dark. Class-
   based (not @media) so an explicit choice can win over the system setting
   in either direction; see theme.js for the resolution order. */
:root.theme-dark {
  color-scheme: dark;

  --surface-1: #1a1a19;
  --page-plane: #0d0d0d;
  --text-primary: #ffffff;
  --text-secondary: #c3c2b7;
  --muted: #898781;
  --gridline: #2c2c2a;
  --baseline: #383835;
  --border: rgba(255, 255, 255, 0.1);

  --series-accent: #0d9488;

  --cat-1: #3987e5;
  --cat-2: #199e70;
  --cat-3: #c98500;
  --cat-4: #008300;
  --cat-5: #9085e9;
  --cat-6: #e66767;
  --cat-7: #d55181;
  --cat-8: #d95926;
  --cat-9: #2bc2ca;
  --cat-10: #e0c829;
  --cat-11: #76b83d;
  --cat-12: #7981d8;
  --cat-13: #b36ecf;
  --cat-14: #d65cb4;
  --cat-15: #bc7f5c;
  --cat-16: #7192a8;

  --cat-soft-1: #5a92d0;
  --cat-soft-2: #4bae8c;
  --cat-soft-3: #d4a94a;
  --cat-soft-4: #5a9e5a;
  --cat-soft-5: #8f82c9;
  --cat-soft-6: #d47f7e;
  --cat-soft-7: #cf8fb0;
  --cat-soft-8: #d38868;
  --cat-soft-9: #4b979b;
  --cat-soft-10: #aea047;
  --cat-soft-11: #6e944c;
  --cat-soft-12: #646bb4;
  --cat-soft-13: #9861ae;
  --cat-soft-14: #af5a97;
  --cat-soft-15: #9d7158;
  --cat-soft-16: #647f90;
}

* {
  box-sizing: border-box;
}

html {
  /* Paint the canvas opaquely in the theme color. The native web view is
     made non-opaque (see desktop_app.py) so blank navigation frames reveal
     the dark window instead of a white flash; this keeps every normally
     rendered frame fully opaque so nothing bleeds through during use. */
  background: var(--page-plane);
}

body {
  margin: 0;
  font-family: system-ui, -apple-system, "Segoe UI", sans-serif;
  background: var(--page-plane);
  color: var(--text-primary);
}

.topnav {
  display: flex;
  align-items: center;
  gap: var(--space-24);
  padding: var(--space-16) var(--space-24);
  border-bottom: 1px solid var(--border);
  background: var(--surface-1);
}

.topnav .brand {
  font-family: var(--font-display);
  font-size: var(--font-xl);
  font-weight: 700;
  letter-spacing: -0.02em;
  margin-right: auto;
  color: var(--text-primary);
  text-decoration: none;
}

/* The ring standing in for the "o" in "Focus" — the app's actual mark
   folded into the wordmark itself, rather than a separate icon tile sitting
   next to plain text. Colored with the brand accent (unlike the surrounding
   ink-colored letters) so it reads as the one deliberate brand moment. */
.brand-o {
  display: inline-block;
  width: 0.6em;
  height: 0.6em;
  margin: 0 0.02em;
  vertical-align: 0.04em;
  color: var(--series-accent);
}

/* Resting state is fully drawn (matches the static ring everywhere else).
   On page load the arc draws itself in once ("backwards" fill keeps it
   hidden through the short delay). Hover/focus replays the tare gesture —
   unwind to zero, then re-draw — but that runs through brand.js, not CSS
   :hover: a hover-triggered CSS animation restarts from zero on every
   re-entry, which reads as flicker when the pointer crosses repeatedly.
   brand.js starts a pass only when none is running, so each pass always
   completes and lands back on this same fully-drawn rest state. */
.brand-o-arc {
  stroke-dashoffset: 0;
}

@media (prefers-reduced-motion: no-preference) {
  .brand-o-arc {
    animation: brand-o-draw 0.7s 0.15s cubic-bezier(0.22, 1, 0.36, 1) backwards;
  }
}

@keyframes brand-o-draw {
  from {
    stroke-dashoffset: 1;
  }
  to {
    stroke-dashoffset: 0;
  }
}

.topnav a {
  color: var(--text-secondary);
  text-decoration: none;
  font-size: var(--font-base);
  padding: var(--space-6) var(--space-2);
  border-bottom: 2px solid transparent;
}

.topnav a.active {
  color: var(--text-primary);
  border-bottom-color: var(--series-accent);
}

.theme-toggle {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  border-radius: 7px;
  border: none;
  background: transparent;
  color: var(--text-secondary);
  cursor: pointer;
  transition: background 0.15s ease, color 0.15s ease;
}

.theme-toggle:hover {
  background: var(--page-plane);
  color: var(--text-primary);
}

.theme-toggle svg {
  width: 17px;
  height: 17px;
}

/* Only one of the two icons is shown at a time; theme.js toggles this
   attribute rather than swapping DOM nodes, so there's nothing to flash. */
.theme-toggle .icon-moon {
  display: none;
}

:root.theme-dark .theme-toggle .icon-sun {
  display: none;
}

:root.theme-dark .theme-toggle .icon-moon {
  display: block;
}

.topnav a:focus-visible,
.bar-group:focus-visible,
button:focus-visible,
select:focus-visible,
input:focus-visible {
  outline: 2px solid var(--series-accent);
  outline-offset: 2px;
}

main {
  max-width: 900px;
  margin: 0 auto;
  padding: var(--space-32) var(--space-24) var(--space-64);
}

/* Timer page */

.timer-card {
  background: var(--surface-1);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: var(--space-48) var(--space-32);
  text-align: center;
  max-width: 480px;
  margin: var(--space-48) auto 0;
  animation: card-in 0.4s cubic-bezier(0.22, 1, 0.36, 1) both;
}

@keyframes card-in {
  from {
    opacity: 0;
    transform: translateY(12px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.timer-label {
  color: var(--text-secondary);
  font-size: var(--font-base);
  margin-bottom: var(--space-8);
}

.timer-topic {
  font-size: var(--font-3xl);
  font-weight: 600;
  margin-bottom: var(--space-16);
  overflow-wrap: anywhere; /* unbroken topic names wrap, never escape the card */
}

.topic-icon-inline {
  display: inline-flex;
  vertical-align: -4px;
  margin-right: var(--space-8);
}

/* The focus ring: a slim progress circle that fills once per hour in the
   active topic's color, wrapped around the clock — the app's visual
   signature, echoing the donut chart and the favicon. */
.timer-ring {
  position: relative;
  width: 280px;
  height: 280px;
  margin: var(--space-8) auto var(--space-20);
  animation: clock-in 0.5s cubic-bezier(0.22, 1, 0.36, 1) both;
}

.timer-ring svg {
  width: 100%;
  height: 100%;
  transform: rotate(-90deg); /* progress starts at 12 o'clock */
}

.ring-track {
  fill: none;
  stroke: var(--gridline);
  stroke-width: 6;
}

.ring-progress {
  fill: none;
  stroke: var(--ring-color, var(--series-accent));
  stroke-width: 6;
  stroke-linecap: round;
  transition: stroke-dashoffset 1s linear, opacity 0.15s ease;
}

.timer-ring.is-paused .ring-progress {
  opacity: 0.35;
}

.timer-ring-content {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}

.timer-clock {
  font-family: var(--font-display);
  font-size: 40px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.02em;
  margin-bottom: var(--space-4);
  transition: opacity 0.15s ease;
}

.timer-clock.is-paused {
  opacity: 0.5;
}

@keyframes clock-in {
  from {
    opacity: 0;
    transform: scale(0.94);
  }
  to {
    opacity: 1;
    transform: scale(1);
  }
}

.timer-meta {
  color: var(--muted);
  font-size: var(--font-xs);
}

/* The session's stated intention, tucked under the topic name while running.
   One ellipsized line — a long intention (even an unbroken string, which has
   no wrap points at all) must never widen the card; the full text is on
   hover via the app tooltip. */
.timer-intention {
  max-width: 100%;
  margin: -8px 0 var(--space-16);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: var(--font-sm);
  color: var(--text-secondary);
}

/* Micro-label + input pair in the start form, mirroring .edit-form label. */
.intention-field {
  display: flex;
  flex-direction: column;
  gap: var(--space-6);
  text-align: left;
}

.status-dot {
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  margin-right: var(--space-6);
  vertical-align: 1px;
}

.status-dot--live {
  background: var(--cat-2);
  animation: pulse 2s ease-out infinite;
}

.status-dot--paused {
  background: var(--cat-3);
}

@keyframes pulse {
  0% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--cat-2) 45%, transparent); }
  70% { box-shadow: 0 0 0 8px transparent; }
  100% { box-shadow: 0 0 0 0 transparent; }
}

/* Inline prompts on the running timer (away-time resolution, long-session
   check-in). Left-aligned inside the centered card so they read as a
   message, not a headline; quiet page-plane surface so they never compete
   with the clock. */
.timer-notice {
  display: flex;
  flex-direction: column;
  gap: var(--space-10);
  padding: var(--space-12) var(--space-14);
  margin-bottom: var(--space-16);
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--page-plane);
  text-align: left;
  animation: dropdown-in 0.16s cubic-bezier(0.22, 1, 0.36, 1);
}

.timer-notice[hidden] {
  display: none;
}

.timer-notice-text {
  margin: 0;
  font-size: var(--font-sm);
  color: var(--text-secondary);
  line-height: 1.5;
}

.timer-notice-text strong {
  color: var(--text-primary);
}

.timer-notice-actions {
  display: flex;
  gap: var(--space-8);
}

.timer-notice-actions .btn {
  flex: 1;
  margin-top: 0;
  padding: var(--space-6) var(--space-12);
  font-size: var(--font-sm);
}

.rating-hint a {
  color: var(--series-accent);
  text-decoration: none;
}

.rating-hint a:hover {
  text-decoration: underline;
}

.timer-actions {
  display: flex;
  gap: var(--space-10);
}

.timer-actions .action-form {
  flex: 1;
}

.timer-actions .btn {
  width: 100%;
}

.kbd-hint {
  color: var(--muted);
  font-size: var(--font-xs);
  margin-top: var(--space-14);
}

.kbd-hint kbd {
  font-family: inherit;
  font-size: var(--font-2xs);
  padding: var(--space-1) var(--space-6);
  border: 1px solid var(--border);
  border-bottom-width: 2px;
  border-radius: 5px;
  background: var(--page-plane);
  color: var(--text-secondary);
}

.start-form {
  display: flex;
  flex-direction: column;
  gap: var(--space-10);
  align-items: stretch;
}

.today-summary {
  color: var(--text-secondary);
  font-size: var(--font-sm);
  margin: -2px 0 var(--space-18);
}

.today-summary strong {
  color: var(--text-primary);
}

.welcome-blurb {
  color: var(--text-secondary);
  font-size: var(--font-base);
  line-height: 1.5;
  margin: 0 0 var(--space-4);
}

.link-toggle {
  background: none;
  border: none;
  padding: var(--space-2) var(--space-4);
  color: var(--series-accent);
  font-size: var(--font-sm);
  font-family: inherit;
  cursor: pointer;
  align-self: center;
}

.link-toggle:hover {
  text-decoration: underline;
}

/* Clicking Start with no topic chosen never leaves the timer page (no
   server round-trip, no reload) — the dropdown popping open (or the empty
   text field shaking, focused and ready) already communicates what's needed,
   so no accompanying error text on top of it. */
.is-shaking {
  animation: shake 0.4s ease;
}

@keyframes shake {
  10%, 90% {
    transform: translateX(-1px);
  }
  20%, 80% {
    transform: translateX(2px);
  }
  30%, 50%, 70% {
    transform: translateX(-4px);
  }
  40%, 60% {
    transform: translateX(4px);
  }
}

select,
input[type="text"],
input[type="date"],
input[type="time"] {
  padding: var(--space-10) var(--space-12);
  border-radius: 8px;
  border: 1px solid var(--border);
  background: var(--page-plane);
  color: var(--text-primary);
  font-size: var(--font-base);
  font-family: inherit;
  color-scheme: light dark;
  transition: border-color 0.15s ease;
}

select:focus,
input[type="text"]:focus,
input[type="date"]:focus,
input[type="time"]:focus {
  border-color: var(--series-accent);
}

/* Custom topic picker — replaces a native <select> so each option can show
   an icon in the topic's color, which <option> elements can't render. */

.topic-combobox {
  position: relative;
}

.combobox-trigger {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-8);
  padding: var(--space-10) var(--space-12);
  border-radius: 8px;
  border: 1px solid var(--border);
  background: var(--page-plane);
  color: var(--text-primary);
  font-size: var(--font-base);
  font-family: inherit;
  text-align: left;
  cursor: pointer;
  transition: border-color 0.15s ease;
}

.combobox-trigger:focus-visible,
.combobox-trigger.is-open {
  outline: none;
  border-color: var(--series-accent);
}

.combobox-trigger-content {
  display: flex;
  align-items: center;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.combobox-trigger-content.is-placeholder {
  color: var(--muted);
}

.combobox-caret {
  flex-shrink: 0;
  color: var(--muted);
  transition: transform 0.15s ease;
}

.combobox-trigger.is-open .combobox-caret {
  transform: rotate(180deg);
}

.combobox-listbox {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  right: 0;
  max-height: 240px;
  overflow-y: auto;
  margin: 0;
  padding: var(--space-6);
  list-style: none;
  background: var(--surface-1);
  border: 1px solid var(--border);
  border-radius: 10px;
  box-shadow: 0 10px 28px rgba(0, 0, 0, 0.3);
  z-index: 20;
}

.combobox-listbox[hidden] {
  display: none;
}

.combobox-option {
  display: flex;
  align-items: center;
  padding: var(--space-8) var(--space-10);
  border-radius: 6px;
  font-size: var(--font-base);
  cursor: pointer;
  text-decoration: none;
  color: var(--text-primary);
}

.combobox-option.is-active {
  background: var(--page-plane);
}

.combobox-option.is-selected {
  font-weight: 600;
}

/* Dashboard scope filter — a multi-select checklist (any mix of groups and
   individual topics can be checked at once) rather than a single-select
   listbox, so the panel needs its own positioned wrapper plus a pinned
   Apply footer, mirroring how .range-filter-panel wraps .range-filter-listbox
   and .range-calendar as alternating siblings. */

.scope-filter {
  position: relative;
}

.scope-filter-trigger {
  width: auto;
  padding: var(--space-7) var(--space-10);
  font-size: var(--font-sm);
}

/* The panel itself is the visual card (background/border/shadow/radius) —
   the listbox and the Apply footer inside it are flat, so they read as one
   continuous surface instead of the list looking like a separate floating
   card from the button beneath it. overflow:hidden clips the listbox's
   square corners to the panel's rounded ones. */
.scope-filter-panel {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  z-index: 20;
  background: var(--surface-1);
  border: 1px solid var(--border);
  border-radius: 10px;
  box-shadow: 0 10px 28px rgba(0, 0, 0, 0.3);
  overflow: hidden;
}

.scope-filter-listbox {
  position: static;
  min-width: 220px;
  background: none;
  border: none;
  box-shadow: none;
  border-radius: 0;
}

.scope-option {
  cursor: pointer;
}

.scope-option:hover {
  background: var(--page-plane);
}

/* Non-interactive divider before the leftover "Ungrouped" topics — same
   border-top-as-separator pattern used for .card-menu-group-new. */
.scope-filter-section-label {
  padding: var(--space-8) var(--space-10) var(--space-4);
  margin-top: var(--space-4);
  border-top: 1px solid var(--border);
  font-size: var(--font-2xs);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--muted);
}

/* A topic nested under its group in the scope filter — indented so the
   hierarchy (group -> its topics) reads at a glance, without duplicating the
   topic in a separate flat list once it already belongs to a group. */
.combobox-option--nested {
  padding-left: var(--space-30);
}

/* Each group's topics collapse behind their own chevron, off by default —
   a handful of group rows reads far lighter than every topic spelled out.
   The chevron toggles independently of the group's own checkbox, which is
   why it's a separate button rather than baked into the label's click area. */
.scope-group-row {
  display: flex;
  align-items: center;
}

.scope-group-label {
  flex: 1;
  min-width: 0;
}

.scope-group-toggle {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  margin-right: var(--space-6);
  border: none;
  border-radius: 6px;
  background: none;
  color: var(--muted);
  cursor: pointer;
}

.scope-group-toggle:hover {
  background: var(--page-plane);
  color: var(--text-primary);
}

.scope-group-toggle .combobox-caret {
  transition: transform 0.15s ease;
  transform: rotate(-90deg);
}

.scope-group-toggle.is-open .combobox-caret {
  transform: rotate(0deg);
}

.scope-group-topics {
  list-style: none;
  margin: 0;
  padding: 0;
}

/* Visually-hidden-but-functional native checkbox: kept in the accessibility
   tree and fully operable (unlike display:none), with a custom box drawn via
   its sibling so it matches the app's own visual language instead of the
   browser's native checkbox chrome. */
.scope-checkbox {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

.scope-checkbox-box {
  width: 14px;
  height: 14px;
  border: 1px solid var(--border);
  border-radius: 4px;
  margin-right: var(--space-8);
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition: background 0.12s ease, border-color 0.12s ease;
}

.scope-checkbox:checked + .scope-checkbox-box {
  background: var(--series-accent);
  border-color: var(--series-accent);
}

.scope-checkbox:checked + .scope-checkbox-box::after {
  content: "";
  width: 4px;
  height: 7px;
  border: solid #fff;
  border-width: 0 2px 2px 0;
  transform: rotate(45deg) translate(-1px, -1px);
}

.scope-checkbox:focus-visible + .scope-checkbox-box {
  outline: 2px solid var(--series-accent);
  outline-offset: 2px;
}

.scope-filter-actions {
  display: flex;
  justify-content: flex-end;
  padding: var(--space-8) var(--space-10);
  border-top: 1px solid var(--border);
}

.scope-filter-apply {
  padding: var(--space-6) var(--space-16);
  font-size: var(--font-sm);
  margin-top: 0;
}

.scope-filter-apply:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.group-swatch {
  display: inline-flex;
  align-items: center;
  gap: var(--space-3);
  margin-right: var(--space-6);
}

.group-swatch-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  flex-shrink: 0;
}

.group-swatch-extra {
  font-size: var(--font-2xs);
  color: var(--muted);
  margin-left: var(--space-1);
}

.btn {
  padding: var(--space-12) var(--space-20);
  border-radius: 8px;
  border: 1px solid transparent;
  font-size: var(--font-md);
  font-weight: 600;
  cursor: pointer;
  margin-top: var(--space-4);
  transition: transform 0.12s ease, background 0.15s ease,
    border-color 0.15s ease, color 0.15s ease;
}

.btn:hover {
  transform: translateY(-1px);
}

.btn:active {
  transform: translateY(0);
}

.btn-start {
  background: var(--series-accent);
  color: #ffffff;
}

.btn-stop {
  background: transparent;
  border-color: var(--cat-6);
  color: var(--cat-6);
  width: 100%;
}

.btn-stop:hover {
  background: var(--cat-6);
  color: #ffffff;
}

.btn-pause {
  background: var(--cat-3);
  color: #ffffff;
  width: 100%;
}

.btn-resume {
  background: var(--series-accent);
  color: #ffffff;
  width: 100%;
}

/* Post-stop rating prompt */

.rate-prompt {
  border-bottom: 1px solid var(--border);
  padding-bottom: var(--space-20);
  margin-bottom: var(--space-20);
}

.rating-buttons {
  display: flex;
  justify-content: center;
  gap: var(--space-8);
  margin-top: var(--space-8);
}

.rating-btn {
  width: 36px;
  height: 36px;
  border-radius: 50%;
  border: 1px solid var(--border);
  background: var(--page-plane);
  color: var(--text-primary);
  font-size: var(--font-base);
  font-weight: 600;
  cursor: pointer;
  transition: border-color 0.15s ease, transform 0.12s ease;
}

.rating-btn:hover {
  border-color: var(--series-accent);
  transform: scale(1.08);
}

.rating-skip {
  width: auto;
  border-radius: 8px;
  padding: 0 var(--space-12);
  color: var(--text-secondary);
  font-weight: 500;
}

.rating-hint {
  color: var(--muted);
  font-size: var(--font-xs);
  margin-top: var(--space-8);
}

/* Dashboard */

/* Hidden until charts.js has rendered its content and plays the entrance
   cascade (see revealDashboard). Kept invisible rather than reflowing means
   nothing pops in before the coordinated animation. JS always removes this. */
.dash-preload {
  opacity: 0;
}

/* Filter dropdowns get a quick fade-and-drop as they open, so the panel feels
   like it descends from its trigger rather than snapping into place. Replays
   each open because display:none (via [hidden]) resets CSS animations. */
.range-filter-panel:not([hidden]),
.scope-filter-panel:not([hidden]),
.combobox-listbox:not([hidden]) {
  animation: dropdown-in 0.16s cubic-bezier(0.22, 1, 0.36, 1);
}

@keyframes dropdown-in {
  from {
    opacity: 0;
    transform: translateY(-6px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.range-nav {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-16);
  margin-bottom: var(--space-24);
}

/* Dashboard date-range filter — a single combobox (Week/Month/Year/All
   time/Custom) replaces what used to be a row of separate tabs, so adding
   more presets later doesn't crowd the header. Picking "Custom" swaps the
   listbox out for an inline drill-down calendar in the same popover. */

.range-filter {
  position: relative;
}

.range-filter-trigger {
  width: auto;
  padding: var(--space-7) var(--space-10);
  font-size: var(--font-sm);
}

.range-filter-panel {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  z-index: 20;
}

.range-filter-listbox {
  position: static;
  min-width: 160px;
}

.range-filter-custom-btn {
  width: 100%;
  border: none;
  background: none;
  font: inherit;
  text-align: left;
}

.range-calendar {
  width: 260px;
  padding: var(--space-12);
  background: var(--surface-1);
  border: 1px solid var(--border);
  border-radius: 10px;
  box-shadow: 0 10px 28px rgba(0, 0, 0, 0.3);
}

.range-calendar-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: var(--space-10);
}

.range-calendar-nav {
  padding: var(--space-4) var(--space-8);
  border: none;
  border-radius: 6px;
  background: none;
  color: var(--text-secondary);
  font-size: var(--font-lg);
  line-height: 1;
  cursor: pointer;
}

.range-calendar-nav:hover {
  background: var(--page-plane);
  color: var(--text-primary);
}

.range-calendar-title {
  padding: var(--space-4) var(--space-8);
  border: none;
  border-radius: 6px;
  background: none;
  color: var(--text-primary);
  font-size: var(--font-base);
  font-weight: 600;
  cursor: pointer;
}

.range-calendar-title:hover:not(:disabled) {
  background: var(--page-plane);
}

.range-calendar-title:disabled {
  cursor: default;
}

.range-calendar-weekdays {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  margin-bottom: var(--space-4);
}

.range-calendar-weekdays span {
  text-align: center;
  font-size: var(--font-2xs);
  color: var(--muted);
}

.range-calendar-grid {
  display: grid;
}

.range-calendar-grid--days {
  grid-template-columns: repeat(7, 1fr);
  gap: var(--space-2);
}

.range-calendar-grid--months,
.range-calendar-grid--years {
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-6);
}

.range-calendar-day {
  aspect-ratio: 1;
  border: none;
  background: none;
  border-radius: 50%;
  font-size: var(--font-sm);
  color: var(--text-primary);
  cursor: pointer;
}

.range-calendar-day:hover {
  background: var(--page-plane);
}

.range-calendar-day.is-today {
  color: var(--series-accent);
  font-weight: 700;
}

.range-calendar-day.is-in-range {
  background: color-mix(in srgb, var(--series-accent) 18%, transparent);
  border-radius: 0;
}

.range-calendar-day.is-range-start,
.range-calendar-day.is-range-end {
  background: var(--series-accent);
  color: #ffffff;
  border-radius: 50%;
}

.range-calendar-cell {
  padding: var(--space-10) var(--space-4);
  border: none;
  border-radius: 8px;
  background: none;
  color: var(--text-primary);
  font-size: var(--font-sm);
  cursor: pointer;
}

.range-calendar-cell:hover {
  background: var(--page-plane);
}

.range-calendar-cell.is-today {
  color: var(--series-accent);
  font-weight: 600;
}

.range-calendar-actions {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-top: var(--space-12);
  padding-top: var(--space-10);
  border-top: 1px solid var(--border);
}

.range-calendar-back {
  padding: var(--space-4) var(--space-6);
  border: none;
  background: none;
  color: var(--text-secondary);
  font-size: var(--font-xs);
  cursor: pointer;
}

.range-calendar-back:hover {
  color: var(--text-primary);
}

.range-calendar-apply {
  padding: var(--space-6) var(--space-16);
  font-size: var(--font-sm);
  margin-top: 0;
}

.range-calendar-apply:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.period-nav {
  display: flex;
  align-items: center;
  gap: var(--space-10);
}

.nav-arrow {
  color: var(--text-secondary);
  text-decoration: none;
  font-size: var(--font-xl);
  line-height: 1;
  padding: var(--space-4) var(--space-8);
  border-radius: 6px;
}

.nav-arrow:hover {
  background: var(--surface-1);
}

.period-label {
  font-size: var(--font-base);
  font-weight: 600;
  min-width: 160px;
  text-align: center;
}

/* Only ever rendered when navigating the prev/next arrows has actually moved
   you off the period containing today, so its appearance is itself a signal
   worth noticing — a pill (rather than plain text) plus a pop-in animation,
   echoing the same accent dot used to mark "today" in the week chart. */
.today-link {
  margin-left: auto;
  display: inline-flex;
  align-items: center;
  gap: var(--space-6);
  padding: var(--space-6) var(--space-12);
  border-radius: 999px;
  font-size: var(--font-sm);
  font-weight: 600;
  color: var(--series-accent);
  background: color-mix(in srgb, var(--series-accent) 12%, transparent);
  border: 1px solid color-mix(in srgb, var(--series-accent) 30%, transparent);
  text-decoration: none;
  transition: background 0.15s ease, border-color 0.15s ease, transform 0.1s ease;
  animation: today-pop 0.3s cubic-bezier(0.34, 1.56, 0.64, 1) both;
}

.today-link::before {
  content: "";
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--series-accent);
  flex-shrink: 0;
}

.today-link:hover {
  background: color-mix(in srgb, var(--series-accent) 20%, transparent);
  border-color: color-mix(in srgb, var(--series-accent) 45%, transparent);
}

.today-link:active {
  transform: scale(0.96);
}

@keyframes today-pop {
  from {
    opacity: 0;
    transform: scale(0.85);
  }
  to {
    opacity: 1;
    transform: scale(1);
  }
}

.chart-hint {
  color: var(--muted);
  font-size: var(--font-xs);
  margin: -8px 0 var(--space-12);
}

.stat-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: var(--space-16);
  margin-bottom: var(--space-32);
}

.stat-tile {
  background: var(--surface-1);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: var(--space-20);
}

.stat-value {
  font-family: var(--font-display);
  font-size: 24px;
  font-weight: 700;
  letter-spacing: -0.02em;
}

.stat-label {
  color: var(--text-secondary);
  font-size: var(--font-sm);
  margin-top: var(--space-4);
}

.chart-card {
  background: var(--surface-1);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: var(--space-20) var(--space-20) var(--space-8);
  margin-bottom: var(--space-24);
}

.chart-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-24);
}

.chart-row .chart-card {
  margin-bottom: var(--space-24);
  min-width: 0;
}

@media (max-width: 760px) {
  .chart-row {
    grid-template-columns: 1fr;
    gap: 0;
  }
}

.chart-card h2 {
  font-size: var(--font-md);
  font-weight: 600;
  margin: 0 0 var(--space-12);
}

.chart svg {
  width: 100%;
  height: auto;
  display: block;
  overflow: visible;
}

/* Topic-distribution donut */

.donut-wrap {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-16);
  padding-bottom: var(--space-12);
}

.chart--donut svg {
  max-width: 220px;
  margin: 0 auto;
}

.donut-slice {
  stroke: var(--surface-1);
  stroke-width: 2.5;
  transition: opacity 0.15s ease;
  cursor: default;
  outline: none;
}

.donut-svg:hover .donut-slice {
  opacity: 0.45;
}

.donut-svg .donut-slice:hover,
.donut-svg .donut-slice:focus-visible {
  opacity: 1;
}

.donut-center-value {
  fill: var(--text-primary);
  font-family: var(--font-display);
  font-size: var(--font-2xl);
  font-weight: 700;
  letter-spacing: -0.02em;
}

.donut-center-label {
  fill: var(--muted);
  font-size: var(--font-2xs);
}

.donut-legend {
  width: 100%;
  display: flex;
  flex-direction: column;
  gap: var(--space-8);
}

.legend-row {
  display: flex;
  align-items: center;
  gap: var(--space-8);
  font-size: var(--font-sm);
}

.legend-swatch {
  width: 10px;
  height: 10px;
  border-radius: 3px;
  flex-shrink: 0;
}

.legend-name {
  color: var(--text-primary);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.legend-value {
  color: var(--text-secondary);
  margin-left: auto;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.gridline {
  stroke: var(--gridline);
  stroke-width: 1;
}

.baseline {
  stroke: var(--baseline);
  stroke-width: 1;
}

.axis-label {
  fill: var(--muted);
  font-size: var(--font-2xs);
}

/* "Today" anchor in the week view: its date label goes accent + bold with a
   small dot beneath, so the current day reads at a glance without touching the
   bars themselves. */
.axis-label--today {
  fill: var(--series-accent);
  font-weight: 700;
}

.today-dot {
  fill: var(--series-accent);
}

.value-label {
  fill: var(--text-secondary);
  font-size: var(--font-2xs);
  font-weight: 600;
}

.bar {
  transition: filter 0.1s ease;
}

.bar-base {
  transition: filter 0.1s ease;
}

.hit-area {
  fill: transparent;
}

.bar-group:hover .bar,
.bar-group:hover .bar-base,
.bar-group:focus .bar,
.bar-group:focus .bar-base {
  filter: brightness(1.1);
}

.bar-group--clickable {
  cursor: pointer;
}

.bar-group--clickable .bar,
.bar-group--clickable .bar-base {
  transition: filter 0.15s ease, transform 0.15s ease;
}

.bar-group--clickable:hover .bar,
.bar-group--clickable:focus-visible .bar,
.bar-group--clickable:hover .bar-base,
.bar-group--clickable:focus-visible .bar-base {
  filter: brightness(1.3);
  transform: translateY(-3px);
}

.bar-group--clickable:hover .axis-label,
.bar-group--clickable:focus-visible .axis-label {
  fill: var(--text-primary);
}

.bar-group--clickable:hover .axis-label--today,
.bar-group--clickable:focus-visible .axis-label--today {
  fill: var(--series-accent);
}

.empty-state {
  color: var(--muted);
  font-size: var(--font-base);
  padding: var(--space-32) 0;
  text-align: center;
}

.tooltip {
  position: fixed;
  z-index: 20;
  background: var(--text-primary);
  color: var(--surface-1);
  padding: var(--space-6) var(--space-10);
  border-radius: 6px;
  font-size: var(--font-xs);
  pointer-events: none;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
}

.tooltip[hidden] {
  display: none;
}

/* The generic variant driven by tooltip.js ([data-tooltip] elements) — same
   bubble as the chart tooltips, but sized for sentences: wraps instead of
   growing one long line. */
.app-tooltip {
  display: block;
  max-width: 280px;
  line-height: 1.45;
  overflow-wrap: anywhere; /* unbroken strings wrap too */
}

.tooltip-value {
  font-weight: 700;
}

.tooltip-label {
  opacity: 0.8;
}

/* Day detail page */

.day-page h1 {
  font-size: var(--font-2xl);
  margin: var(--space-8) 0 var(--space-20);
}

.back-link {
  color: var(--text-secondary);
  text-decoration: none;
  font-size: var(--font-sm);
}

.session-table-wrap {
  overflow-x: auto;
  background: var(--surface-1);
  border: 1px solid var(--border);
  border-radius: 12px;
}

.session-table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--font-sm);
}

.session-table th,
.session-table td {
  text-align: left;
  padding: var(--space-12) var(--space-16);
  white-space: nowrap;
}

/* Center cells vertically so two-line rows (topic + intention) keep their
   times/actions aligned with the row, not with the first text baseline. */
.session-table td {
  vertical-align: middle;
}

.session-table thead th {
  color: var(--text-secondary);
  font-weight: 600;
  font-size: var(--font-xs);
  border-bottom: 1px solid var(--border);
}

.session-table tbody tr:not(:last-child) td {
  border-bottom: 1px solid var(--border);
}

/* One-line intention under the topic name; ellipsized so a long note can't
   stretch the table (full text on hover via title). */
.session-intention {
  max-width: 240px;
  margin-top: var(--space-2);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: var(--font-xs);
  color: var(--muted);
}

.row-actions {
  display: flex;
  gap: var(--space-12);
  align-items: center;
}

.row-actions a {
  color: var(--series-accent);
  text-decoration: none;
  font-size: var(--font-sm);
}

.inline-form {
  display: inline;
}

.link-button {
  background: none;
  border: none;
  padding: 0;
  color: var(--cat-6);
  font-size: var(--font-sm);
  cursor: pointer;
  font-family: inherit;
}

/* Topics management page */

.topics-header {
  display: flex;
  align-items: flex-start;
  gap: var(--space-8);
  margin: var(--space-8) 0 var(--space-20);
}

.topics-heading {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}

.topics-header h1 {
  margin: 0;
}

.topics-subtitle {
  margin: 0;
  font-size: var(--font-sm);
  color: var(--text-secondary);
}

.topics-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  gap: var(--space-16);
}

.topic-card {
  position: relative;
  background: var(--surface-1);
  border: 1px solid var(--border);
  border-radius: 12px;
  transition: opacity 0.2s ease, border-color 0.15s ease;
  animation: card-in 0.4s cubic-bezier(0.22, 1, 0.36, 1) both;
  cursor: grab;
  user-select: none;
  touch-action: none;
}

.topic-card:hover {
  border-color: var(--baseline);
}

.topic-card.menu-open {
  z-index: 5;
}

/* The card being carried by the pointer: lifted off the page, following the
   cursor via fixed positioning set inline in JS. */
.topic-card.dragging {
  z-index: 1000;
  cursor: grabbing;
  pointer-events: none;
  box-shadow: 0 16px 40px rgba(0, 0, 0, 0.35);
  border-color: var(--baseline);
}

/* Holds the dragged card's grid slot open so the layout doesn't collapse. */
.topic-card-placeholder {
  border: 2px dashed var(--border);
  border-radius: 12px;
  background: color-mix(in srgb, var(--series-accent) 7%, transparent);
}

body.is-reordering {
  cursor: grabbing;
}

.topic-card--hidden {
  display: none;
  opacity: 0.5;
  filter: grayscale(0.7);
  border-style: dashed;
}

.topics-grid.show-hidden .topic-card--hidden {
  display: block;
}

/* Right-side header actions (Export CSV, Show hidden) — grouped so either
   one aligns right whether or not the other is rendered. */
.topics-header-actions {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: var(--space-16);
}

.export-link {
  text-decoration: none;
}

.hidden-toggle {
  display: inline-flex;
  align-items: center;
  gap: var(--space-6);
}

.hidden-toggle .icon-eye-off {
  display: none;
}

.hidden-toggle.is-active .icon-eye {
  display: none;
}

.hidden-toggle.is-active .icon-eye-off {
  display: inline;
}

.topic-card-body {
  padding: var(--space-18) var(--space-18) var(--space-20);
}

.topic-card-top {
  display: flex;
  align-items: center;
  gap: var(--space-8);
  margin-bottom: var(--space-12);
  /* keep the right-aligned group pill clear of the absolute ⋮ menu button */
  margin-right: var(--space-24);
}

.topic-icon-badge {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  flex-shrink: 0;
}

/* overflow-wrap so an unbroken name wraps inside the card instead of
   escaping it — names are meant to be read in full, so they wrap rather
   than ellipsize. */
.topic-card-name {
  font-size: var(--font-md);
  font-weight: 600;
  margin: 0 0 var(--space-16);
  overflow-wrap: anywhere;
}

/* The topic's group, as a quiet pill on the right of the icon row — a fixed,
   scannable spot instead of a floating line between name and stats. Bounded
   and ellipsized; long names get the full text via the app tooltip. */
.topic-card-group-label {
  margin-left: auto;
  max-width: 110px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  padding: var(--space-2) var(--space-8);
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--page-plane);
  font-size: var(--font-2xs);
  font-weight: 600;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.card-menu-btn {
  position: absolute;
  top: 12px;
  right: 10px;
  width: 26px;
  height: 26px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 6px;
  border: none;
  background: transparent;
  color: var(--muted);
  cursor: pointer;
  transition: background 0.15s ease, color 0.15s ease;
}

.card-menu-btn:hover,
.card-menu-btn.is-open {
  background: var(--page-plane);
  color: var(--text-primary);
}

.card-menu-dropdown {
  position: absolute;
  top: 42px;
  right: 10px;
  min-width: 130px;
  /* Bounded so a long group name can't stretch the menu — without a max
     the flex row grows to the name's intrinsic width and shoves the
     rename/delete actions out of view; with it, the name's ellipsis
     engages instead. */
  max-width: 250px;
  background: var(--surface-1);
  border: 1px solid var(--border);
  border-radius: 10px;
  box-shadow: 0 10px 28px rgba(0, 0, 0, 0.3);
  padding: var(--space-6);
  z-index: 10;
  display: flex;
  flex-direction: column;
}

.card-menu-dropdown[hidden] {
  display: none;
}

.card-menu-item {
  display: block;
  width: 100%;
  text-align: left;
  padding: var(--space-8) var(--space-10);
  border-radius: 6px;
  border: none;
  background: none;
  color: var(--text-primary);
  font-size: var(--font-sm);
  font-family: inherit;
  cursor: pointer;
}

.card-menu-item:hover {
  background: var(--page-plane);
}

.card-menu-item--danger {
  color: var(--cat-6);
}

.card-menu-color-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--space-8);
  padding: var(--space-8);
}

.card-menu-color-grid[hidden] {
  display: none;
}

.color-swatch-btn {
  width: 22px;
  height: 22px;
  border-radius: 50%;
  border: 2px solid transparent;
  padding: 0;
  cursor: pointer;
  transition: transform 0.1s ease;
}

.color-swatch-btn:hover {
  transform: scale(1.15);
}

.color-swatch-btn.is-selected {
  border-color: var(--text-primary);
}

.card-menu-icon-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--space-4);
  padding: var(--space-8);
}

.card-menu-icon-grid[hidden] {
  display: none;
}

.card-menu-group-list {
  padding: var(--space-4) 0;
}

.group-option.is-selected {
  font-weight: 600;
  color: var(--series-accent);
}

/* Each group's row in the "Group" picker: the name button (click = assign to
   this topic) plus small rename/delete actions, the same CRUD-in-one-place
   pattern as the topic card's own menu, one level deeper. */
.group-row {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}

.group-row .group-option {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.group-rename-input {
  flex: 1;
  min-width: 0;
  padding: var(--space-6) var(--space-8);
  font-size: var(--font-sm);
  font-family: inherit;
  border-radius: 6px;
  border: 1px solid var(--series-accent);
  background: var(--page-plane);
  color: var(--text-primary);
}

.group-row-action {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 24px;
  height: 24px;
  padding: 0;
  border: none;
  border-radius: 5px;
  background: none;
  color: var(--muted);
  cursor: pointer;
}

.group-row-action:hover {
  background: var(--page-plane);
  color: var(--text-primary);
}

.group-row-action--danger:hover {
  color: var(--cat-6);
}

.card-menu-group-new {
  padding: var(--space-6) var(--space-10) var(--space-4);
  margin-top: var(--space-4);
  border-top: 1px solid var(--border);
}

.group-new-input {
  width: 100%;
  padding: var(--space-6) var(--space-8);
  font-size: var(--font-sm);
  border-radius: 6px;
  border: 1px solid var(--border);
  background: var(--page-plane);
  color: var(--text-primary);
}

.icon-swatch-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  border-radius: 6px;
  border: 1px solid transparent;
  background: none;
  color: var(--text-secondary);
  cursor: pointer;
  padding: 0;
  transition: background 0.1s ease, color 0.1s ease;
}

.icon-swatch-btn:hover {
  background: var(--page-plane);
  color: var(--text-primary);
}

.icon-swatch-btn.is-selected {
  background: var(--page-plane);
  border-color: var(--text-primary);
  color: var(--text-primary);
}

.topic-card-stats {
  display: flex;
  gap: var(--space-24);
}

.topic-card-stat-value {
  font-family: var(--font-display);
  font-size: var(--font-lg);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.02em;
}

.topic-card-stat-label {
  font-size: var(--font-2xs);
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  margin-top: var(--space-2);
}

.add-topic-form {
  display: flex;
  gap: var(--space-10);
  margin-bottom: var(--space-20);
}

.add-topic-form input[type="text"] {
  flex: 1;
}

.add-topic-form .btn {
  margin-top: 0;
  white-space: nowrap;
}

/* Shared centered "hero" pattern for first-run empty states (Timer + Topics) */

.hero-block {
  max-width: 380px;
  margin: var(--space-64) auto 0;
  text-align: center;
  animation: card-in 0.5s cubic-bezier(0.22, 1, 0.36, 1) both;
}

.hero-icon {
  width: 60px;
  height: 60px;
  margin: 0 auto var(--space-22);
  border-radius: 50%;
  background: color-mix(in srgb, var(--series-accent) 14%, transparent);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--series-accent);
  animation: icon-pop 0.5s 0.15s cubic-bezier(0.34, 1.56, 0.64, 1) both;
}

@keyframes icon-pop {
  from {
    opacity: 0;
    transform: scale(0.6);
  }
  to {
    opacity: 1;
    transform: scale(1);
  }
}

.hero-block h2 {
  font-size: var(--font-xl);
  margin: 0 0 var(--space-8);
}

.hero-block p {
  color: var(--text-secondary);
  font-size: var(--font-base);
  line-height: 1.5;
  margin: 0 0 var(--space-28);
}

.form-hero {
  flex-direction: column;
}

.form-hero input[type="text"] {
  text-align: center;
  padding: var(--space-14) var(--space-16);
  font-size: var(--font-md);
}

.form-hero .btn {
  width: 100%;
  margin-top: 0;
}

/* Landing page (web mode, anonymous) */

.landing {
  max-width: 720px;
  margin: 0 auto;
}

.landing-hero {
  text-align: center;
  padding: var(--space-48) 0 var(--space-32);
  animation: card-in 0.5s cubic-bezier(0.22, 1, 0.36, 1) both;
}

.landing-ring {
  color: var(--series-accent);
  margin-bottom: var(--space-20);
}

.landing-hero h1 {
  font-size: var(--font-4xl);
  margin: 0 0 var(--space-12);
}

.landing-sub {
  font-size: var(--font-lg);
  line-height: 1.6;
  color: var(--text-secondary);
  max-width: 34em;
  margin: 0 auto var(--space-28);
}

.landing-cta {
  display: flex;
  gap: var(--space-12);
  justify-content: center;
}

.landing-cta .btn {
  margin-top: 0;
  padding: var(--space-12) var(--space-24);
  text-decoration: none;
  display: inline-block;
}

.landing-features {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: var(--space-16);
  padding: var(--space-32) 0 var(--space-48);
}

.landing-feature {
  background: var(--surface-1);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: var(--space-20);
}

.landing-feature h2 {
  font-size: var(--font-md);
  margin: 0 0 var(--space-8);
}

.landing-feature p {
  font-size: var(--font-sm);
  line-height: 1.6;
  color: var(--text-secondary);
  margin: 0;
}

/* Auth pages (web mode) */

.auth-alt {
  margin-top: var(--space-20);
  font-size: var(--font-sm);
  color: var(--text-secondary);
}

.auth-alt a {
  color: var(--series-accent);
  text-decoration: none;
}

.auth-alt a:hover {
  text-decoration: underline;
}

.nav-logout {
  font-size: var(--font-base);
  color: var(--text-secondary);
}

/* Confirmation modal (replaces native confirm() dialogs) */

.modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.5);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 100;
  padding: var(--space-20);
}

.modal-overlay[hidden] {
  display: none;
}

.modal {
  background: var(--surface-1);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: var(--space-24);
  max-width: 380px;
  width: 100%;
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.3);
}

.modal h2 {
  font-size: var(--font-lg);
  margin: 0 0 var(--space-10);
}

.modal p {
  font-size: var(--font-sm);
  color: var(--text-secondary);
  line-height: 1.5;
  margin: 0 0 var(--space-20);
}

.modal-actions {
  display: flex;
  justify-content: flex-end;
  gap: var(--space-10);
}

.modal-actions .btn {
  margin-top: 0;
  padding: var(--space-10) var(--space-16);
  font-size: var(--font-base);
}

.btn-secondary {
  background: transparent;
  border-color: var(--border);
  color: var(--text-primary);
}

.btn-secondary:hover {
  background: var(--page-plane);
}

.btn-danger {
  background: var(--cat-6);
  color: #ffffff;
}


/* Edit session page */

.edit-card {
  background: var(--surface-1);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: var(--space-32);
  max-width: 480px;
  margin: var(--space-24) auto 0;
}

.edit-card h1 {
  font-size: var(--font-xl);
  margin: 0 0 var(--space-20);
}

.form-error {
  border: 1px solid var(--cat-6);
  color: var(--cat-6);
  border-radius: 8px;
  padding: var(--space-10) var(--space-14);
  font-size: var(--font-sm);
  margin-bottom: var(--space-16);
}

.edit-form {
  display: flex;
  flex-direction: column;
  gap: var(--space-16);
}

.edit-form label {
  display: flex;
  flex-direction: column;
  gap: var(--space-6);
  font-size: var(--font-sm);
  color: var(--text-secondary);
}

/* Date and time as separate native inputs — a single <input type="datetime-
   local"> opens one combined picker for both, so clicking in to adjust just
   the time still surfaces a full calendar. Splitting them gives each control
   its own focused picker (a calendar for the date, an hour/minute-only
   control for the time), which is what people actually reach for. */
.datetime-field {
  display: flex;
  flex-direction: column;
  gap: var(--space-6);
  font-size: var(--font-sm);
  color: var(--text-secondary);
}

.datetime-inputs {
  display: flex;
  gap: var(--space-8);
}

.datetime-inputs input[type="date"] {
  flex: 3;
}

.datetime-inputs input[type="time"] {
  flex: 2;
}

.field-label {
  font-size: var(--font-sm);
  color: var(--text-secondary);
}

.rating-picker {
  display: flex;
  gap: var(--space-12);
  margin-top: -8px;
}

.rating-option {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  font-size: var(--font-sm);
  color: var(--text-secondary);
}

@media (prefers-reduced-motion: reduce) {
  .ring-progress {
    transition: opacity 0.15s ease; /* progress steps instead of sweeping */
  }

  .status-dot--live,
  .timer-card,
  .timer-ring,
  .hero-block,
  .hero-icon,
  .topic-card,
  .range-filter-panel:not([hidden]),
  .scope-filter-panel:not([hidden]),
  .combobox-listbox:not([hidden]),
  .today-link,
  .is-shaking,
  .timer-notice {
    animation: none;
  }

  .today-link {
    transition: none;
  }

  .today-link:active {
    transform: none;
  }

  /* JS still removes .dash-preload; this is a safety net so the dashboard is
     never left hidden if the entrance is skipped for reduced motion. */
  .dash-preload {
    opacity: 1;
  }

  .btn,
  .rating-btn,
  .donut-slice,
  .bar-group--clickable .bar,
  .bar-group--clickable .bar-base,
  .topic-card {
    transition: none;
  }

  .btn:hover,
  .rating-btn:hover,
  .bar-group--clickable:hover .bar,
  .bar-group--clickable:focus-visible .bar,
  .bar-group--clickable:hover .bar-base,
  .bar-group--clickable:focus-visible .bar-base {
    transform: none;
  }
}
