/* ─────────────────────────────────────────────────────────────────
  OrbitTrack – Pane motion (Windows 11)
  The default interface style's motion, after WinUI 3 / Fluent 2: "fast out,
  slow in" for everything entering or moving, short quiet exits, durations on
  WinUI's 83 / 167 / 250 / 333 ms grid. The first part gives the transitions
  of style.css's own selectors; "Win11 behaviours" below adds the page,
  dialog, flyout and expander transitions and the Win11-only touches (tab
  pill, toggle stretch, check draw, ProgressRing).
  Active when Settings → Style is Pane; see js/ui-style.js.
  ───────────────────────────────────────────────────────────────── */

:root {
  --win-ease-decel: cubic-bezier(0, 0, 0, 1);    /* fast out, slow in: enter, move */
  --win-ease-accel: cubic-bezier(1, 0, 1, 1);    /* slow out, fast in: exit */
  --win-ease-easy: cubic-bezier(.33, 0, .67, 1); /* loops */
  --win-dur-faster: 83ms;
  --win-dur-fast: 167ms;
  --win-dur-normal: 250ms;
  --win-dur-slow: 333ms;
  --transition: var(--win-dur-fast) var(--win-ease-decel);
  /* Lets height animate to and from auto (expanders). */
  interpolate-size: allow-keywords;
}

input, select, textarea, .select {
  transition:
    border-color var(--win-dur-faster) var(--win-ease-decel),
    box-shadow var(--win-dur-faster) var(--win-ease-decel),
    transform var(--win-dur-normal) var(--win-ease-decel);
}

.toggle-slider {
  transition: var(--transition);
}

.toggle-slider::before {
  transition: var(--transition);
}

.btn {
  transition:
    background-color var(--win-dur-faster) var(--win-ease-decel),
    border-color var(--win-dur-faster) var(--win-ease-decel),
    color var(--win-dur-faster) var(--win-ease-decel),
    transform var(--win-dur-normal) var(--win-ease-decel),
    box-shadow var(--win-dur-faster) var(--win-ease-decel);
}

.spinner {
  animation: spin .6s linear infinite;
}

@keyframes spin { to { transform: rotate(360deg); } }

.tab-btn {
  transition:
    color var(--win-dur-faster) var(--win-ease-decel),
    background-color var(--win-dur-faster) var(--win-ease-decel),
    transform var(--win-dur-normal) var(--win-ease-decel);
}

.timer-fullscreen-progress-bar {
  transition: width var(--win-dur-slow) var(--win-ease-decel);
}

.timer-adjust-btn {
  transition:
    background-color var(--win-dur-faster) var(--win-ease-decel),
    transform var(--win-dur-normal) var(--win-ease-decel),
    border-color var(--win-dur-faster) var(--win-ease-decel);
}

.group-toggle-btn {
  transition: all var(--transition);
}

.task-item {
  transition:
    background-color var(--win-dur-faster) var(--win-ease-decel),
    transform var(--win-dur-normal) var(--win-ease-decel),
    box-shadow var(--win-dur-faster) var(--win-ease-decel);
}

.task-status-btn {
  transition:
    color var(--win-dur-faster) var(--win-ease-decel),
    transform var(--win-dur-normal) var(--win-ease-decel);
}

.today-item {
  transition:
    background-color var(--win-dur-faster) var(--win-ease-decel),
    transform var(--win-dur-normal) var(--win-ease-decel);
}

.tab-btn,
.group-toggle-btn {
  transition:
    color var(--win-dur-faster) var(--win-ease-decel),
    background-color var(--win-dur-faster) var(--win-ease-decel),
    box-shadow var(--win-dur-faster) var(--win-ease-decel),
    transform var(--win-dur-normal) var(--win-ease-decel);
}

.today-section {
  transition:
    background-color var(--win-dur-faster) var(--win-ease-decel),
    border-color var(--win-dur-faster) var(--win-ease-decel),
    box-shadow var(--win-dur-faster) var(--win-ease-decel),
    transform var(--win-dur-normal) var(--win-ease-decel);
}

.today-item,
.task-item {
  transition:
    background-color var(--win-dur-faster) var(--win-ease-decel),
    border-color var(--win-dur-faster) var(--win-ease-decel),
    box-shadow var(--win-dur-faster) var(--win-ease-decel),
    transform var(--win-dur-normal) var(--win-ease-decel),
    opacity var(--win-dur-fast) var(--win-ease-decel);
}

.btn,
.group-header-main,
.task-status-btn,
.timer-adjust-btn {
  transition:
    background-color var(--win-dur-faster) var(--win-ease-decel),
    border-color var(--win-dur-faster) var(--win-ease-decel),
    color var(--win-dur-faster) var(--win-ease-decel),
    box-shadow var(--win-dur-faster) var(--win-ease-decel),
    transform var(--win-dur-normal) var(--win-ease-decel);
}

input,
select,
textarea,
.select {
  transition:
    background-color var(--win-dur-faster) var(--win-ease-decel),
    border-color var(--win-dur-faster) var(--win-ease-decel),
    box-shadow var(--win-dur-faster) var(--win-ease-decel),
    transform var(--win-dur-normal) var(--win-ease-decel);
}

.adw-combo-button,
.adw-date-button {
  transition:
    background-color var(--win-dur-faster) var(--win-ease-decel),
    border-color var(--win-dur-faster) var(--win-ease-decel),
    box-shadow var(--win-dur-faster) var(--win-ease-decel),
    transform var(--win-dur-normal) var(--win-ease-decel);
}

.adw-combo-button svg,
.adw-date-button svg {
  transition:
    transform var(--win-dur-normal) var(--win-ease-decel),
    color var(--win-dur-faster) var(--win-ease-decel);
}

.adw-combo-option {
  transition:
    background-color var(--win-dur-faster) var(--win-ease-decel),
    color var(--win-dur-faster) var(--win-ease-decel),
    transform var(--win-dur-normal) var(--win-ease-decel);
}

.adw-date-nav {
  transition:
    background-color var(--win-dur-faster) var(--win-ease-decel),
    transform var(--win-dur-normal) var(--win-ease-decel);
}

.adw-date-nav svg {
  transition: transform var(--win-dur-normal) var(--win-ease-decel);
}

.adw-date-day {
  transition:
    background-color var(--win-dur-faster) var(--win-ease-decel),
    border-color var(--win-dur-faster) var(--win-ease-decel),
    color var(--win-dur-faster) var(--win-ease-decel),
    transform var(--win-dur-normal) var(--win-ease-decel),
    box-shadow var(--win-dur-faster) var(--win-ease-decel);
}

.adw-date-link {
  transition:
    background-color var(--win-dur-faster) var(--win-ease-decel),
    transform var(--win-dur-normal) var(--win-ease-decel);
}

.plan-nav-btn {
  transition:
    background-color var(--win-dur-faster) var(--win-ease-decel),
    color var(--win-dur-faster) var(--win-ease-decel),
    transform var(--win-dur-normal) var(--win-ease-decel);
}

.plan-headerbar-title {
  transition: background-color var(--win-dur-faster) var(--win-ease-decel);
}

.plan-entry-row {
  transition:
    border-color var(--win-dur-faster) var(--win-ease-decel),
    box-shadow var(--win-dur-faster) var(--win-ease-decel);
}

.plan-entry-add {
  transition:
    background-color var(--win-dur-faster) var(--win-ease-decel),
    color var(--win-dur-faster) var(--win-ease-decel),
    transform var(--win-dur-normal) var(--win-ease-decel);
}

.plan-row-group {
  transition: background-color var(--win-dur-faster) var(--win-ease-decel);
}

.plan-row-accent {
  transition: background-color var(--win-dur-faster) var(--win-ease-decel);
}

.plan-target-progress-bar {
  transition: width var(--win-dur-slow) var(--win-ease-decel);
}

.plan-icon-btn {
  transition:
    background-color var(--win-dur-faster) var(--win-ease-decel),
    color var(--win-dur-faster) var(--win-ease-decel),
    transform var(--win-dur-normal) var(--win-ease-decel);
}

.adw-menu-item {
  transition:
    background-color var(--win-dur-faster) var(--win-ease-decel),
    color var(--win-dur-faster) var(--win-ease-decel);
}

.plan-row-detail {
  /* `backwards`, never `both`. With `both` the final keyframe's `transform:
     none` is retained as an animated value, and Chrome resolves that to
     matrix(1,0,0,1,0,0) — a transform that is not `none`, so the element keeps
     a stacking context forever. That traps the attach popover inside it at
     z=0, and any later sibling row paints straight over the open dropdown.
     `backwards` drops the animated values once the run finishes, so the
     computed transform goes back to `none` and z-index 650 reaches the root. */
  animation:
    win-fade-in var(--win-dur-fast) linear backwards,
    win-rise-in var(--win-dur-slow) var(--win-ease-decel) backwards;
  --win-rise: -8px;
}

.plan-skeleton-row {
  animation: plan-shimmer 1.6s var(--win-ease-easy) infinite;
}

@keyframes plan-shimmer {
  from { background-position: 120% 0; }
  to   { background-position: -120% 0; }
}

.repeat-day {
  transition:
    background-color var(--win-dur-faster) var(--win-ease-decel),
    color var(--win-dur-faster) var(--win-ease-decel),
    border-color var(--win-dur-faster) var(--win-ease-decel);
}

.timer-minimize-btn {
  transition:
    color var(--win-dur-faster) var(--win-ease-decel),
    background-color var(--win-dur-faster) var(--win-ease-decel);
}

/* ── Win11 behaviours ──────────────────────────────────────────────
   The PWA runs in a Windows 11 window, so this style moves the way WinUI 3 /
   Fluent 2 does rather than the way Libadwaita does (motion-adwaita.css: an
   easeOutCubic rise on every chip, row, header and icon at once):
   - entering and moving: "fast out, slow in", cubic-bezier(0,0,0,1). The
     element leaves at once and spends the rest of its time settling;
   - leaving: short and quiet — an 83–167 ms fade, "slow out, fast in" if it
     moves at all;
   - durations on WinUI's grid, 83 / 167 / 250 / 333 ms; hover and press
     colors switch in 83 ms like a WinUI BrushTransition;
   - opacity alone runs linear, as WinUI's own fades do;
   - nothing animates by itself at launch. Motion answers a navigation or an
     action: page refresh, a horizontal slide between tabs, the dialog
     settling from 1.05, flyouts unfolding from their anchor, expanders.
   Keyframes give only `from`, so they land on the element's own value (a
   completed row's .55 opacity, a transform set elsewhere). */

@keyframes win-fade-in { from { opacity: 0; } }
@keyframes win-rise-in { from { transform: translateY(var(--win-rise, 12px)); } }

/* Login ⇄ app: page refresh — the incoming page slides up and fades in. */
.app-fade-enter-active {
  transition:
    opacity var(--win-dur-fast) linear,
    transform var(--win-dur-slow) var(--win-ease-decel);
}
.app-fade-leave-active { transition: opacity var(--win-dur-faster) linear; }
.app-fade-enter-from { opacity: 0; transform: translateY(40px); }
.app-fade-leave-to { opacity: 0; }

/* Tabs are peers: the new page slides in from the side of the tab that was
   picked (WinUI's SlideNavigationTransitionInfo) and the old one just fades.
   The direction arrives on .app-shell as data-tab-dir. */
.tab-panel-enter-active {
  transition:
    opacity var(--win-dur-fast) linear,
    transform var(--win-dur-slow) var(--win-ease-decel);
}
.tab-panel-leave-active { transition: opacity var(--win-dur-faster) linear; }
.tab-panel-enter-from { opacity: 0; transform: translateX(40px); }
.app-shell[data-tab-dir="back"] .tab-panel-enter-from { transform: translateX(-40px); }
.tab-panel-leave-to { opacity: 0; }

/* One selection pill slides between the tabs. Its leading edge leaves first
   and the trailing edge follows, so it stretches toward the new tab and
   settles there — the indicator of WinUI's NavigationView / SelectorBar.
   The script measures the active tab and adds .has-indicator; until then the
   active tab paints its own fill. */
.topbar-tabs { position: relative; }
.tab-btn { position: relative; z-index: 1; }
.tab-indicator {
  display: block;
  position: absolute;
  top: var(--tab-ind-top, 4px);
  left: var(--tab-ind-left, 0);
  right: var(--tab-ind-right, 100%);
  height: var(--tab-ind-height, 38px);
  border-radius: 10px;
  background: var(--primary);
  box-shadow: 0 8px 22px rgba(92,114,136,.26);
  opacity: 0;
  pointer-events: none;
  transition:
    left var(--win-dur-slow) var(--win-ease-decel),
    right var(--win-dur-slow) var(--win-ease-decel);
}
.topbar-tabs.has-indicator .tab-indicator { opacity: 1; }
.topbar-tabs.has-indicator .tab-btn.active { background: transparent; box-shadow: none; }
.app-shell[data-tab-dir="forward"] .tab-indicator { transition-delay: 60ms, 0s; }
.app-shell[data-tab-dir="back"] .tab-indicator { transition-delay: 0s, 60ms; }
.topbar-tabs.tabs-instant .tab-indicator { transition: none; }

/* Expanders (settings panel, calendar groups): the height opens to auto and
   the content drops in from under the header, like WinUI's Expander;
   closing is quicker. */
.settings-slide-enter-active,
.settings-slide-leave-active,
.group-collapse-enter-active,
.group-collapse-leave-active { overflow: hidden; }
.settings-slide-enter-active,
.group-collapse-enter-active {
  transition:
    height var(--win-dur-slow) var(--win-ease-decel),
    padding var(--win-dur-slow) var(--win-ease-decel),
    opacity var(--win-dur-fast) linear;
}
.settings-slide-leave-active,
.group-collapse-leave-active {
  transition:
    height var(--win-dur-fast) var(--win-ease-decel),
    padding var(--win-dur-fast) var(--win-ease-decel),
    opacity var(--win-dur-faster) linear;
}
.settings-slide-enter-from,
.settings-slide-leave-to,
.group-collapse-enter-from,
.group-collapse-leave-to {
  height: 0;
  padding-top: 0;
  padding-bottom: 0;
  opacity: 0;
}
.settings-slide-enter-active > *,
.group-collapse-enter-active > * {
  transition: transform var(--win-dur-slow) var(--win-ease-decel);
}
.settings-slide-enter-from > *,
.group-collapse-enter-from > * { transform: translateY(-16px); }

/* Dialogs settle the way WinUI's ContentDialog does: in from 1.05 over a
   smoke layer that fades underneath, out back toward 1.05 and quicker. The
   template gives these transitions explicit durations so the overlay stays
   until the card is done. */
.modal-pop-enter-active { transition: opacity var(--win-dur-faster) linear; }
.modal-pop-leave-active { transition: opacity var(--win-dur-fast) linear; }
.modal-pop-enter-from,
.modal-pop-leave-to { opacity: 0; }
.modal-pop-enter-active .modal-card {
  transition:
    opacity var(--win-dur-faster) linear,
    transform var(--win-dur-normal) var(--win-ease-decel);
}
.modal-pop-leave-active .modal-card {
  transition:
    opacity var(--win-dur-faster) linear,
    transform var(--win-dur-fast) var(--win-ease-decel);
}
.modal-pop-enter-from .modal-card,
.modal-pop-leave-to .modal-card { opacity: 0; transform: scale(1.05); }

/* Flyouts (menus, dropdowns, the date picker) unfold from their anchor: the
   frame is revealed edge-first while it slides into place, then closes with
   a quick fade — WinUI's MenuFlyout. The clip leaves room for the shadow, so
   nothing pops when it is released. */
.flyout-enter-active {
  transition:
    opacity var(--win-dur-faster) linear,
    transform var(--win-dur-normal) var(--win-ease-decel),
    clip-path var(--win-dur-normal) var(--win-ease-decel);
}
.flyout-leave-active { transition: opacity var(--win-dur-faster) linear; }
.flyout-enter-from {
  opacity: 0;
  transform: translateY(-12px);
  clip-path: inset(-80px -80px 100% -80px);
}
.flyout-enter-to { clip-path: inset(-80px); }
.flyout-leave-to { opacity: 0; }
/* The ones measured to open upward unfold the other way. */
.plan-row-group.popover-up .adw-menu.flyout-enter-from,
.plan-row-group.popover-up .plan-attach .adw-combo-popover.flyout-enter-from,
.task-item.popover-up .adw-menu.flyout-enter-from,
.today-item.popover-up .adw-menu.flyout-enter-from {
  transform: translateY(12px);
  clip-path: inset(100% -80px -80px -80px);
}

/* Toasts come up from the bottom edge (down from the top while the timer
   card holds the corner) and leave as a short fade. */
.toast-enter-active {
  transition:
    opacity var(--win-dur-fast) linear,
    transform var(--win-dur-slow) var(--win-ease-decel);
}
.toast-leave-active {
  transition:
    opacity var(--win-dur-fast) linear,
    transform var(--win-dur-fast) var(--win-ease-accel);
}
.toast-enter-from { opacity: 0; transform: translateX(-50%) translateY(24px); }
.toast-leave-to { opacity: 0; transform: translateX(-50%) translateY(8px); }
:root.timer-floating .toast-enter-from { transform: translateX(-50%) translateY(-24px); }
:root.timer-floating .toast-leave-to { transform: translateX(-50%) translateY(-8px); }

/* The full-screen timer drills in from slightly smaller. Minimizing folds it
   into the corner card, the way a window minimizes to the taskbar, and
   opening the card grows it back out of that corner (.timer-from-float is
   set by expandTimer for the length of the transition). */
.timer-overlay-enter-active {
  transition:
    opacity var(--win-dur-fast) linear,
    transform var(--win-dur-slow) var(--win-ease-decel);
}
.timer-overlay-leave-active {
  transition:
    opacity var(--win-dur-fast) linear,
    transform var(--win-dur-normal) var(--win-ease-decel);
}
.timer-overlay-enter-from { opacity: 0; transform: scale(.94); }
.timer-overlay-leave-to { opacity: 0; transform: scale(.97); }
:root.timer-floating .timer-overlay-leave-active,
:root.timer-from-float .timer-overlay-enter-active {
  transform-origin: calc(100% - 126px) calc(100% - 80px);
}
:root.timer-floating .timer-overlay-leave-to,
:root.timer-from-float .timer-overlay-enter-from { transform: scale(.6); }

/* The card lands as the page folds into it, then leaves as a quick fade
   toward the edge it sits on. */
.timer-float-enter-active {
  transform-origin: 100% 100%;
  transition:
    opacity var(--win-dur-fast) linear var(--win-dur-faster),
    transform var(--win-dur-normal) var(--win-ease-decel) var(--win-dur-faster);
}
.timer-float-leave-active {
  transition:
    opacity var(--win-dur-fast) linear,
    transform var(--win-dur-fast) var(--win-ease-accel);
}
.timer-float-enter-from { opacity: 0; transform: scale(.9); }
.timer-float-leave-to { opacity: 0; transform: translateX(24px); }

/* Toggle switch: the knob travels on the decelerate curve and stretches
   while pressed (WinUI ToggleSwitch). */
.toggle-slider { transition: background-color var(--win-dur-faster) var(--win-ease-decel); }
.toggle-slider::before {
  transition:
    transform var(--win-dur-normal) var(--win-ease-decel),
    width var(--win-dur-normal) var(--win-ease-decel);
}
.toggle:active .toggle-slider::before { width: 24px; }
.toggle:active input:checked + .toggle-slider::before { transform: translateX(16px); }

/* Pressed controls dim slightly and at once, as WinUI controls do; nothing
   scales. A dropdown's chevron nudges down while pressed. */
.btn:active:not(:disabled),
.tab-btn:active,
.plan-icon-btn:active:not(:disabled),
.plan-nav-btn:active:not(:disabled),
.adw-menu-item:active:not(:disabled),
.adw-combo-option:active,
.adw-date-day:active,
.adw-date-nav:active,
.task-status-btn:active,
.timer-adjust-btn:active { opacity: .78; }
.adw-combo-button:active:not(:disabled) svg { transform: translateY(2px); }

/* A task that was just ticked draws its check, short stroke first. */
.task-status-btn.just-done svg path {
  stroke-dasharray: 23;
  animation: win-check-draw var(--win-dur-normal) var(--win-ease-decel) backwards;
}
@keyframes win-check-draw { from { stroke-dashoffset: -23; } }

/* Lists fade in when their rows arrive (a finished load, a new task) — no
   slide, so they never fight the page transition they often arrive with. */
.task-groups,
.today-grid,
.task-item,
.today-item,
.empty-state,
.task-group-empty { animation: win-fade-in var(--win-dur-fast) linear backwards; }

/* Spinners are WinUI's indeterminate ProgressRing: an arc whose head runs
   ahead and whose tail catches up while the ring turns. */
@property --ring-head { syntax: '<angle>'; inherits: false; initial-value: 0deg; }
@property --ring-tail { syntax: '<angle>'; inherits: false; initial-value: 0deg; }
.spinner {
  border: 2px solid currentColor;
  -webkit-mask: conic-gradient(from var(--ring-tail), #000 calc(var(--ring-head) - var(--ring-tail) + 14deg), #0000 0);
  mask: conic-gradient(from var(--ring-tail), #000 calc(var(--ring-head) - var(--ring-tail) + 14deg), #0000 0);
  animation:
    spin 2s linear infinite,
    win-ring-head 1.2s cubic-bezier(.33, 0, .2, 1) infinite,
    win-ring-tail 1.2s cubic-bezier(.8, 0, .67, 1) infinite;
}
.spinner-lg { border-width: 3px; }
.loading-state .spinner { color: var(--primary); }
@keyframes win-ring-head { from { --ring-head: 0deg; } to { --ring-head: 360deg; } }
@keyframes win-ring-tail { from { --ring-tail: 0deg; } to { --ring-tail: 360deg; } }
