// ==WindhawkMod==
// @id              window-animation-customizer
// @name            Window Animation Customizer
// @description     Customizable 3D animations without modifying theme files.
// @version         0.5.0
// @author          Lockframe
// @github          https://github.com/Lockframe
// @include         *
// @include         dwm.exe
// @compilerOptions -ldcomp -ld3d11 -ldxgi -lgdi32 -luser32 -ladvapi32 -ldwmapi -lcomctl32 -lwinmm -luxtheme -lole32 -lwevtapi
// ==/WindhawkMod==

// ==WindhawkModReadme==
/*

# Window Animation Customizer

Customizable 3D animations for Windows 10/11 without touching any theme files.

## Contributors
[Kieldbg](https://github.com/kieldbg)
[AromaKitsune](https://github.com/AromaKitsune)
[Lolstijl]
[Xalejandro](https://github.com/tetawaves)

*/
// ==WindhawkModReadme==

// ==WindhawkModSettings==
/*
- preset: ""
  $name: "Preset"
  $description: "Predefined animation style. Selecting 'Windows 7' applies classic 3D Aero animations."
  $options:
  - "": "Custom / None"
  - "win7": "Windows 7"
- OpenAnimation:
    - enable_open: true
      $name: "Enable"
    - duration_open: 250
      $name: "Base Duration (ms)"
    - open_scale: "1, 1"
      $name: "Scale (X, Y)"
    - open_pivot_preset: "1"
      $name: "Pivot Preset"
      $options:
      - "1": "Center"
      - "2": "Top Left"
      - "3": "Top"
      - "4": "Top Right"
      - "5": "Left"
      - "6": "Right"
      - "7": "Bottom Left"
      - "8": "Bottom"
      - "9": "Bottom Right"
    - Transform:
        - open_offset: "0, 0"
          $name: "Offset (X, Y)"
        - open_pitch: '5'
          $name: "Pitch"
        - open_yaw: '0'
          $name: "Yaw"
        - open_roll: '0'
          $name: "Roll"
        - open_z: '0'
          $name: "Z-Depth"
      $name: "Transform"
    - Appearance:
        - open_opacity: '0'
          $name: "Opacity"
        - open_blur: '0'
          $name: "Blur"
      $name: "Appearance"
    - Physics:
        - open_spring: false
          $name: "Enable Spring"
        - open_mass: '1'
          $name: "Mass"
        - open_stiffness: '200'
          $name: "Stiffness"
        - open_damping: '28'
          $name: "Damping"
      $name: "Physics"
    - open_bezier: "0, 0, 0, 1"
      $name: "Base Bezier (X1, Y1, X2, Y2)"
    - Overrides:
        - open_adv_scale:
            - enable: false
              $name: "Enable"
            - duration: '350'
              $name: "Duration (ms)"
            - delay: '0'
              $name: "Delay (ms)"
            - bezier: "0, 0, 0, 1"
              $name: "Bezier (X1, Y1, X2, Y2)"
          $name: "Scale"
        - open_adv_opacity:
            - enable: false
              $name: "Enable"
            - duration: '200'
              $name: "Duration (ms)"
            - delay: '0'
              $name: "Delay (ms)"
            - bezier: "0.3, 0, 0.8, 0.15"
              $name: "Bezier (X1, Y1, X2, Y2)"
          $name: "Opacity"
        - open_adv_blur:
            - enable: false
              $name: "Enable"
            - duration: '300'
              $name: "Duration (ms)"
            - delay: '0'
              $name: "Delay (ms)"
            - bezier: "0, 0, 0, 1"
              $name: "Bezier (X1, Y1, X2, Y2)"
          $name: "Blur"
        - open_adv_pitch:
            - enable: false
              $name: "Enable"
            - duration: '400'
              $name: "Duration (ms)"
            - delay: '0'
              $name: "Delay (ms)"
            - bezier: "0, 0, 0, 1"
              $name: "Bezier (X1, Y1, X2, Y2)"
          $name: "Pitch"
        - open_adv_yaw:
            - enable: false
              $name: "Enable"
            - duration: '400'
              $name: "Duration (ms)"
            - delay: '0'
              $name: "Delay (ms)"
            - bezier: "0, 0, 0, 1"
              $name: "Bezier (X1, Y1, X2, Y2)"
          $name: "Yaw"
        - open_adv_roll:
            - enable: false
              $name: "Enable"
            - duration: '400'
              $name: "Duration (ms)"
            - delay: '0'
              $name: "Delay (ms)"
            - bezier: "0, 0, 0, 1"
              $name: "Bezier (X1, Y1, X2, Y2)"
          $name: "Roll"
      $name: "Overrides"
  $name: "Open Animation"
- CloseAnimation:
    - enable_close: true
      $name: "Enable"
    - duration_close: '166'
      $name: "Base Duration (ms)"
    - close_scale: "1, 1"
      $name: "Scale (X, Y)"
    - close_pivot_preset: "1"
      $name: "Pivot Preset"
      $options:
      - "1": "Center"
      - "2": "Top Left"
      - "3": "Top"
      - "4": "Top Right"
      - "5": "Left"
      - "6": "Right"
      - "7": "Bottom Left"
      - "8": "Bottom"
      - "9": "Bottom Right"
    - Transform:
        - close_offset: "0, 0"
          $name: "Offset (X, Y)"
        - close_pitch: '5'
          $name: "Pitch"
        - close_yaw: '8'
          $name: "Yaw"
        - close_roll: '0'
          $name: "Roll"
        - close_z: '0'
          $name: "Z-Depth"
      $name: "Transform"
    - Appearance:
        - close_opacity: '0'
          $name: "Opacity"
        - close_blur: '0'
          $name: "Blur"
      $name: "Appearance"
    - Physics:
        - close_spring: false
          $name: "Enable Spring"
        - close_mass: '1'
          $name: "Mass"
        - close_stiffness: '200'
          $name: "Stiffness"
        - close_damping: '28'
          $name: "Damping"
      $name: "Physics"
    - close_bezier: "0.3, 0, 0.8, 0.15"
      $name: "Base Bezier (X1, Y1, X2, Y2)"
    - Overrides:
        - close_adv_scale:
            - enable: false
              $name: "Enable"
            - duration: '200'
              $name: "Duration (ms)"
            - delay: '0'
              $name: "Delay (ms)"
            - bezier: "0.3, 0, 0.8, 0.15"
              $name: "Bezier (X1, Y1, X2, Y2)"
          $name: "Scale"
        - close_adv_opacity:
            - enable: false
              $name: "Enable"
            - duration: '150'
              $name: "Duration (ms)"
            - delay: '0'
              $name: "Delay (ms)"
            - bezier: "0.3, 0, 0.8, 0.15"
              $name: "Bezier (X1, Y1, X2, Y2)"
          $name: "Opacity"
        - close_adv_blur:
            - enable: false
              $name: "Enable"
            - duration: '150'
              $name: "Duration (ms)"
            - delay: '0'
              $name: "Delay (ms)"
            - bezier: "0.3, 0, 0.8, 0.15"
              $name: "Bezier (X1, Y1, X2, Y2)"
          $name: "Blur"
        - close_adv_pitch:
            - enable: false
              $name: "Enable"
            - duration: '250'
              $name: "Duration (ms)"
            - delay: '0'
              $name: "Delay (ms)"
            - bezier: "0.3, 0, 0.8, 0.15"
              $name: "Bezier (X1, Y1, X2, Y2)"
          $name: "Pitch"
        - close_adv_yaw:
            - enable: false
              $name: "Enable"
            - duration: '250'
              $name: "Duration (ms)"
            - delay: 0
              $name: "Delay (ms)"
            - bezier: "0.3, 0, 0.8, 0.15"
              $name: "Bezier (X1, Y1, X2, Y2)"
          $name: "Yaw"
        - close_adv_roll:
            - enable: false
              $name: "Enable"
            - duration: '250'
              $name: "Duration (ms)"
            - delay: '0'
              $name: "Delay (ms)"
            - bezier: "0.3, 0, 0.8, 0.15"
              $name: "Bezier (X1, Y1, X2, Y2)"
          $name: "Roll"
      $name: "Overrides"
  $name: "Close Animation"
- MinimizeAnimation:
    - enable_minimize: true
      $name: "Enable"
    - duration_minimize: '250'
      $name: "Base Duration (ms)"
    - minimize_scale: "1, 1"
      $name: "Scale (X, Y)"
    - min_ignore_taskbar: false
      $name: "Ignore Taskbar"
    - min_track_taskbar: true
      $name: "Accurate Taskbar Tracking Trick"
    - min_target_width: '0.6'
      $name: "Target Width Ratio"
      $description: "Ratio of taskbar button width used as the minimize target width. Range 0.1–1.0. Lower = window shrinks smaller into the taskbar."
    - minimize_pivot_preset: "1"
      $name: "Pivot Preset"
      $options:
      - "1": "Center"
      - "2": "Top Left"
      - "3": "Top"
      - "4": "Top Right"
      - "5": "Left"
      - "6": "Right"
      - "7": "Bottom Left"
      - "8": "Bottom"
      - "9": "Bottom Right"
      - "10": "Smart (Taskbar-aware)"
    - Transform:
        - minimize_offset: "0, 0"
          $name: "Offset (X, Y)"
        - minimize_pitch: '0'
          $name: "Pitch"
        - minimize_yaw: '0'
          $name: "Yaw"
        - minimize_roll: '1'
          $name: "Roll"
        - minimize_z: '0'
          $name: "Z-Depth"
      $name: "Transform"
    - Appearance:
        - minimize_opacity: '0'
          $name: "Opacity"
        - minimize_blur: '0'
          $name: "Blur"
      $name: "Appearance"
    - Physics:
        - minimize_spring: false
          $name: "Enable Spring"
        - minimize_mass: '1'
          $name: "Mass"
        - minimize_stiffness: '200'
          $name: "Stiffness"
        - minimize_damping: '28'
          $name: "Damping"
      $name: "Physics"
    - minimize_bezier: "0.3, 0, 0.8, 0.15"
      $name: "Base Bezier (X1, Y1, X2, Y2)"
    - Overrides:
        - min_adv_scale:
            - enable: false
              $name: "Enable"
            - duration: '250'
              $name: "Duration (ms)"
            - delay: '0'
              $name: "Delay (ms)"
            - bezier: "0.3, 0, 0.8, 0.15"
              $name: "Bezier (X1, Y1, X2, Y2)"
          $name: "Scale"
        - min_adv_opacity:
            - enable: false
              $name: "Enable"
            - duration: '200'
              $name: "Duration (ms)"
            - delay: '0'
              $name: "Delay (ms)"
            - bezier: "0.3, 0, 0.8, 0.15"
              $name: "Bezier (X1, Y1, X2, Y2)"
          $name: "Opacity"
        - min_adv_blur:
            - enable: false
              $name: "Enable"
            - duration: '250'
              $name: "Duration (ms)"
            - delay: '0'
              $name: "Delay (ms)"
            - bezier: "0.3, 0, 0.8, 0.15"
              $name: "Bezier (X1, Y1, X2, Y2)"
          $name: "Blur"
        - min_adv_pitch:
            - enable: false
              $name: "Enable"
            - duration: '250'
              $name: "Duration (ms)"
            - delay: '0'
              $name: "Delay (ms)"
            - bezier: "0.3, 0, 0.8, 0.15"
              $name: "Bezier (X1, Y1, X2, Y2)"
          $name: "Pitch"
        - min_adv_yaw:
            - enable: false
              $name: "Enable"
            - duration: '250'
              $name: "Duration (ms)"
            - delay: '0'
              $name: "Delay (ms)"
            - bezier: "0.3, 0, 0.8, 0.15"
              $name: "Bezier (X1, Y1, X2, Y2)"
          $name: "Yaw"
        - min_adv_roll:
            - enable: false
              $name: "Enable"
            - duration: '250'
              $name: "Duration (ms)"
            - delay: '0'
              $name: "Delay (ms)"
            - bezier: "0.3, 0, 0.8, 0.15"
              $name: "Bezier (X1, Y1, X2, Y2)"
          $name: "Roll"
      $name: "Overrides"
- RestoreAnimation:
    - enable_restore: true
      $name: "Enable"
    - duration_restore: '250'
      $name: "Base Duration (ms)"
    - restore_scale: "1, 1"
      $name: "Scale (X, Y)"
    - res_ignore_taskbar: false
      $name: "Ignore Taskbar"
    - res_track_taskbar: true
      $name: "Accurate Taskbar Tracking Trick"
    - res_target_width: '0.6'
      $name: "Target Width Ratio"
      $description: "Ratio of taskbar button width used as the restore origin width. Range 0.1–1.0. Lower = window starts smaller from the taskbar."
    - restore_pivot_preset: "1"
      $name: "Pivot Preset"
      $options:
      - "1": "Center"
      - "2": "Top Left"
      - "3": "Top"
      - "4": "Top Right"
      - "5": "Left"
      - "6": "Right"
      - "7": "Bottom Left"
      - "8": "Bottom"
      - "9": "Bottom Right"
      - "10": "Smart (Taskbar-aware)"
    - Transform:
        - restore_offset: "0, 0"
          $name: "Offset (X, Y)"
        - restore_pitch: '0'
          $name: "Pitch"
        - restore_yaw: '0'
          $name: "Yaw"
        - restore_roll: '1'
          $name: "Roll"
        - restore_z: '0'
          $name: "Z-Depth"
      $name: "Transform"
    - Appearance:
        - restore_opacity: '0'
          $name: "Opacity"
        - restore_blur: '0'
          $name: "Blur"
      $name: "Appearance"
    - Physics:
        - restore_spring: false
          $name: "Enable Spring"
        - restore_mass: '1'
          $name: "Mass"
        - restore_stiffness: '200'
          $name: "Stiffness"
        - restore_damping: '28'
          $name: "Damping"
      $name: "Physics"
    - restore_bezier: "0, 0, 0, 1"
      $name: "Base Bezier (X1, Y1, X2, Y2)"
    - Overrides:
        - res_adv_scale:
            - enable: false
              $name: "Enable"
            - duration: '350'
              $name: "Duration (ms)"
            - delay: '0'
              $name: "Delay (ms)"
            - bezier: "0, 0, 0, 1"
              $name: "Bezier (X1, Y1, X2, Y2)"
          $name: "Scale"
        - res_adv_opacity:
            - enable: false
              $name: "Enable"
            - duration: '200'
              $name: "Duration (ms)"
            - delay: '0'
              $name: "Delay (ms)"
            - bezier: "0.3, 0, 0.8, 0.15"
              $name: "Bezier (X1, Y1, X2, Y2)"
          $name: "Opacity"
        - res_adv_blur:
            - enable: false
              $name: "Enable"
            - duration: '300'
              $name: "Duration (ms)"
            - delay: '0'
              $name: "Delay (ms)"
            - bezier: "0, 0, 0, 1"
              $name: "Bezier (X1, Y1, X2, Y2)"
          $name: "Blur"
        - res_adv_pitch:
            - enable: false
              $name: "Enable"
            - duration: '400'
              $name: "Duration (ms)"
            - delay: '0'
              $name: "Delay (ms)"
            - bezier: "0, 0, 0, 1"
              $name: "Bezier (X1, Y1, X2, Y2)"
          $name: "Pitch"
        - res_adv_yaw:
            - enable: false
              $name: "Enable"
            - duration: '400'
              $name: "Duration (ms)"
            - delay: '0'
              $name: "Delay (ms)"
            - bezier: "0, 0, 0, 1"
              $name: "Bezier (X1, Y1, X2, Y2)"
          $name: "Yaw"
        - res_adv_roll:
            - enable: false
              $name: "Enable"
            - duration: '400'
              $name: "Duration (ms)"
            - delay: '0'
              $name: "Delay (ms)"
            - bezier: "0, 0, 0, 1"
              $name: "Bezier (X1, Y1, X2, Y2)"
          $name: "Roll"
      $name: "Overrides"
  $name: "Restore Animation"
- DragAnimation:
    - General:
        - drag_pivot_mode: "0"
          $name: "Pivot Mode"
          $options:
          - "0": "Manual (Center)"
          - "1": "Automatic (Cursor)"
        - drag_disable_on_resize: false
          $name: "Disable During Resize"
          $description: "Disables the drag tilt/jiggle animation when the window is being resized instead of moved."
        - drag_smoothing: '15'
          $name: "Smoothing Speed"
      $name: "General Settings"
    - Tilt3D:
        - enable_drag: true
          $name: "Enable 3D Drag Tilt (Pitch/Yaw)"
        - drag_intensity: '1'
          $name: "Tilt Intensity Multiplier"
      $name: "3D Drag Tilt (Pitch/Yaw)"
    - Roll2D:
        - enable_drag_roll: true
          $name: "Enable 2D Drag Roll (Rotation)"
        - drag_roll_intensity: '1'
          $name: "Roll Intensity Multiplier"
      $name: "2D Drag Roll (Rotation Z)"
    - JigglePhysics:
        - enable_drag_jiggle: true
          $name: "Enable Drag Jiggle (Scale X/Y Spring)"
        - invert_jiggle: false
          $name: "Invert Jiggle Direction"
        - jiggle_intensity: '1'
          $name: "Jiggle Intensity Multiplier"
        - jiggle_stiffness: '300'
          $name: "Spring Stiffness"
        - jiggle_damping: '15'
          $name: "Spring Damping"
        - jiggle_mass: '1'
          $name: "Spring Mass"
      $name: "Drag Jiggle Physics (Scale X/Y)"
  $name: "Drag Animation"
- System:
    - anim_vsync: false
      $name: "Enable VSync"
    - anim_fps: '75'
      $name: "Target FPS (VSync Off)"
  $name: "System"
*/
// ==/WindhawkModSettings==

#include <windows.h>
#include <windhawk_api.h>
#include <windhawk_utils.h>
#include <dcomp.h>
#include <d3d11.h>
#include <dxgi1_2.h>
#include <dwmapi.h>
#include <uxtheme.h>
#include <commctrl.h>
#include <math.h>
#include <vector>
#include <mutex>
#include <stdio.h>
#include <memory>
#include <unordered_map>
#include <atomic>

#include <winevt.h>

#define SHARED_SECTION __attribute__((section(".shared")))
asm(".section .shared,\"dws\"\n");
volatile LONG g_crashStrikes SHARED_SECTION = 0;

bool HasDwminitWarningInLastMinute() {
    static ULONGLONG s_lastCheckTime = 0;
    static bool s_lastResult = false;
    ULONGLONG now = GetTickCount64();
    if (s_lastCheckTime != 0 && (now - s_lastCheckTime < 60000)) {
        return s_lastResult;
    }
    s_lastCheckTime = now;

    const WCHAR* queryPath = L"Application";
    const WCHAR* query = L"*[System[Provider[@Name='Dwminit'] and (Level=3) and TimeCreated[timediff(@SystemTime) <= 60000]]]";
    EVT_HANDLE queryHandle = EvtQuery(nullptr, queryPath, query, EvtQueryChannelPath);
    if (!queryHandle) {
        s_lastResult = false;
        return false;
    }

    bool found = false;
    EVT_HANDLE eventHandle = nullptr;
    DWORD dwReturned = 0;
    if (EvtNext(queryHandle, 1, &eventHandle, 1000, 0, &dwReturned)) {
        found = true;
        EvtClose(eventHandle);
    }
    EvtClose(queryHandle);
    s_lastResult = found;
    return found;
}

bool CheckCrashLoopFailsafe() {
    if (!HasDwminitWarningInLastMinute()) {
        InterlockedExchange((volatile LONG*)&g_crashStrikes, 0);
        return true;
    }
    LONG strikes = InterlockedIncrement((volatile LONG*)&g_crashStrikes);
    if (strikes >= 2) return false;
    return true;
}

#define DWM_TNP_ENABLE3D 0x4000000
#define ANIM_TYPE_OPEN 0
#define ANIM_TYPE_CLOSE 1
#define ANIM_TYPE_MINIMIZE 2
#define ANIM_TYPE_RESTORE 3
#define ANIM_TYPE_DRAG 4
#define ANIM_TYPE_DRAG_END 5

#define REVEAL_DYNARRAY_SCAN_START 0x100
#define REVEAL_DYNARRAY_SCAN_END 0x250
#define REVEAL_DYNARRAY_CAPACITY_OFFSET 0x14
#define REVEAL_DYNARRAY_COUNT_OFFSET 0x18
#define REVEAL_DYNARRAY_TRACKED_COUNT_OFFSET 0x20
#define REVEAL_DYNARRAY_MAX_COUNT 8
#define REVEAL_DYNARRAY_MAX_CAPACITY 64

#define MAX_DYNARRAY_READ_BOUNDS (REVEAL_DYNARRAY_SCAN_END + REVEAL_DYNARRAY_TRACKED_COUNT_OFFSET + sizeof(void*))

// --- Fast Math Inlines & Constants ---
constexpr float PI_F = 3.14159265358979323846f;
template<typename T> inline T FastMax(T a, T b) { return a > b ? a : b; }
template<typename T> inline T FastMin(T a, T b) { return a < b ? a : b; }

// --- Metrics Cache ---
struct CACHED_METRICS {
    int cxScreen, cyScreen, xVirtual, yVirtual, cxVirtual, cyVirtual;
} GMetrics;

void UpdateMetricsCache() {
    GMetrics.cxScreen = GetSystemMetrics(SM_CXSCREEN);
    GMetrics.cyScreen = GetSystemMetrics(SM_CYSCREEN);
    GMetrics.xVirtual = GetSystemMetrics(SM_XVIRTUALSCREEN);
    GMetrics.yVirtual = GetSystemMetrics(SM_YVIRTUALSCREEN);
    GMetrics.cxVirtual = GetSystemMetrics(SM_CXVIRTUALSCREEN);
    GMetrics.cyVirtual = GetSystemMetrics(SM_CYVIRTUALSCREEN);
}

// --- Settings Struct & Loaders ---
float SolveCubicBezier(float x, float x1, float y1, float x2, float y2);
struct CubicBezierDef { float x1, y1, x2, y2; float LUT[512]; };
void BuildBezierLUT(CubicBezierDef& b) {
    for (int i = 0; i < 512; ++i) b.LUT[i] = SolveCubicBezier((float)i / 511.0f, b.x1, b.y1, b.x2, b.y2);
}
float FastSolveCubicBezier(float x, const CubicBezierDef& b) {
    if (!isfinite(x) || x <= 0.0f) return 0.0f;
    if (x >= 1.0f) return 1.0f;
    float scaled = x * 511.0f;
    if (!isfinite(scaled)) return 0.0f;
    int idx = (int)scaled;
    if (idx < 0) idx = 0;
    if (idx >= 511) return b.LUT[511];
    return b.LUT[idx] + (b.LUT[idx + 1] - b.LUT[idx]) * (scaled - idx);
}

struct AdvProperty { bool enabled; DWORD duration; DWORD delay; CubicBezierDef bezier; };
struct AdvAnimSettings { AdvProperty opacity, blur, scale, pitch, yaw, roll; };

struct MOD_SETTINGS {
    bool enable_open; DWORD duration_open;
    float open_translate_x, open_translate_y;
    float open_pitch, open_yaw, open_roll, open_z, open_scale_x, open_scale_y, open_opacity, open_blur;
    int open_pivot_preset; float open_pivot_x, open_pivot_y;
    CubicBezierDef open_bezier; bool open_spring; float open_mass, open_stiffness, open_damping;
    AdvAnimSettings open_adv;
    
    bool enable_close; DWORD duration_close;
    float close_translate_x, close_translate_y;
    float close_pitch, close_yaw, close_roll, close_z, close_scale_x, close_scale_y, close_opacity, close_blur;
    int close_pivot_preset; float close_pivot_x, close_pivot_y;
    CubicBezierDef close_bezier; bool close_spring; float close_mass, close_stiffness, close_damping;
    AdvAnimSettings close_adv;
    
    bool enable_minimize; DWORD duration_minimize;
    float min_translate_x, min_translate_y;
    bool min_ignore_taskbar; bool min_track_taskbar; float min_target_width;
    float min_pitch, min_yaw, min_roll, min_z, min_scale_x, min_scale_y, min_opacity, min_blur;
    int min_pivot_preset; float min_pivot_x, min_pivot_y;
    CubicBezierDef min_bezier; bool min_spring; float min_mass, min_stiffness, min_damping;
    AdvAnimSettings min_adv;
    
    bool enable_restore; DWORD duration_restore;
    float res_translate_x, res_translate_y;
    bool res_ignore_taskbar; bool res_track_taskbar; float res_target_width;
    float res_pitch, res_yaw, res_roll, res_z, res_scale_x, res_scale_y, res_opacity, res_blur;
    int res_pivot_preset; float res_pivot_x, res_pivot_y;
    CubicBezierDef res_bezier; bool res_spring; float res_mass, res_stiffness, res_damping;
    AdvAnimSettings res_adv;
    
    bool enable_drag; bool enable_drag_roll; bool enable_drag_jiggle; bool invert_jiggle; int drag_pivot_mode;
    bool drag_disable_on_resize;
    float drag_intensity, drag_roll_intensity, drag_smoothing;
    float jiggle_intensity, jiggle_stiffness, jiggle_damping, jiggle_mass;

    bool anim_vsync; int anim_fps; int cached_vsync_fps; int preset;
};

static std::shared_ptr<const MOD_SETTINGS> g_settingsSnapshot = std::make_shared<const MOD_SETTINGS>();

std::atomic<bool> g_cached_enable_drag{true};
std::atomic<bool> g_cached_enable_drag_roll{true};
std::atomic<bool> g_cached_enable_drag_jiggle{true};
std::atomic<bool> g_cached_invert_jiggle{false};
std::atomic<int> g_cached_drag_pivot_mode{0};
std::atomic<bool> g_cached_drag_disable_on_resize{false};
std::atomic<float> g_cached_drag_intensity{1.0f};
std::atomic<float> g_cached_drag_roll_intensity{1.0f};
std::atomic<float> g_cached_drag_smoothing{15.0f};
std::atomic<float> g_cached_jiggle_intensity{1.0f};
std::atomic<float> g_cached_jiggle_stiffness{300.0f};
std::atomic<float> g_cached_jiggle_damping{15.0f};
std::atomic<float> g_cached_jiggle_mass{1.0f};

MOD_SETTINGS GetSafeSettings() {
    auto snapshot = std::atomic_load(&g_settingsSnapshot);
    if (snapshot) return *snapshot;
    return MOD_SETTINGS{};
}

// --- Parsers ---
int ParseIntOpt(LPCWSTR name, int def) {
    LPCWSTR val = Wh_GetStringSetting(name);
    if (val) { int v = _wtoi(val); Wh_FreeStringSetting(val); return v; }
    return def;
}
float ParseFloatOpt(LPCWSTR name, float def) {
    LPCWSTR val = Wh_GetStringSetting(name);
    if (val) { float v = _wtof(val); Wh_FreeStringSetting(val); return v; }
    return def;
}
void ParseOffsetXY(LPCWSTR name, float& x, float& y, float dx, float dy) {
    x=dx; y=dy; LPCWSTR val = Wh_GetStringSetting(name);
    if (val) { swscanf(val, L"%f , %f", &x, &y); Wh_FreeStringSetting(val); }
}
void ParseScale(LPCWSTR name, float& sx, float& sy, float dsx, float dsy) {
    sx=dsx; sy=dsy; LPCWSTR val = Wh_GetStringSetting(name);
    if (val) { swscanf(val, L"%f , %f", &sx, &sy); Wh_FreeStringSetting(val); }
}
CubicBezierDef ParseBezier(LPCWSTR name, float dX1, float dY1, float dX2, float dY2) {
    CubicBezierDef b = { dX1, dY1, dX2, dY2, {0} }; LPCWSTR val = Wh_GetStringSetting(name);
    if (val) { swscanf(val, L"%f , %f , %f , %f", &b.x1, &b.y1, &b.x2, &b.y2); Wh_FreeStringSetting(val); }
    BuildBezierLUT(b);
    return b;
}
void ParseAdvNew(LPCWSTR prefix, AdvProperty& prop, int dDur, float x1, float y1, float x2, float y2) {
    WCHAR key[256];
    wsprintf(key, L"%s.enable", prefix);
    prop.enabled = Wh_GetIntSetting(key) != 0;
    wsprintf(key, L"%s.duration", prefix);
    prop.duration = Wh_GetIntSetting(key);
    if (prop.duration == 0) prop.duration = dDur;
    wsprintf(key, L"%s.delay", prefix);
    prop.delay = Wh_GetIntSetting(key);
    wsprintf(key, L"%s.bezier", prefix);
    prop.bezier = ParseBezier(key, x1, y1, x2, y2);
}

void UpdateRefreshRateCache() {
    MOD_SETTINGS currentSettings = GetSafeSettings();
    if (currentSettings.anim_vsync) {
        int BestFps = 0; DEVMODEW DevMode = {{0}}; DevMode.dmSize = sizeof(DevMode);
        for (DWORD I = 0; EnumDisplaySettingsW(NULL, I, &DevMode); ++I) {
            if ((DevMode.dmFields & DM_DISPLAYFREQUENCY) && DevMode.dmDisplayFrequency > 1 && DevMode.dmDisplayFrequency != 0xFFFFFFFF) {
                if ((int)DevMode.dmDisplayFrequency > BestFps) BestFps = (int)DevMode.dmDisplayFrequency;
            }
        }
        
        currentSettings.cached_vsync_fps = BestFps > 0 ? BestFps : 60;
        std::atomic_store(&g_settingsSnapshot, std::make_shared<const MOD_SETTINGS>(currentSettings));
    }
}

void LoadModSettings() {
    MOD_SETTINGS t = {0};
    
    // OPEN
    t.enable_open = Wh_GetIntSetting(L"OpenAnimation.enable_open") != 0; 
    t.duration_open = (DWORD)Wh_GetIntSetting(L"OpenAnimation.duration_open");
    if (t.duration_open == 0) t.duration_open = 250;
    t.open_pivot_preset = ParseIntOpt(L"OpenAnimation.open_pivot_preset", 1);
    t.open_pivot_x = 0.5f; t.open_pivot_y = 0.5f;
    ParseScale(L"OpenAnimation.open_scale", t.open_scale_x, t.open_scale_y, 1.0f, 1.0f);
    ParseOffsetXY(L"OpenAnimation.Transform.open_offset", t.open_translate_x, t.open_translate_y, 0, 0);
    t.open_z = ParseFloatOpt(L"OpenAnimation.Transform.open_z", 0.0f);
    t.open_pitch = ParseFloatOpt(L"OpenAnimation.Transform.open_pitch", 5.0f);
    t.open_yaw = ParseFloatOpt(L"OpenAnimation.Transform.open_yaw", 0.0f);
    t.open_roll = ParseFloatOpt(L"OpenAnimation.Transform.open_roll", 0.0f);
    t.open_opacity = ParseFloatOpt(L"OpenAnimation.Appearance.open_opacity", 0.0f);
    t.open_blur = ParseFloatOpt(L"OpenAnimation.Appearance.open_blur", 0.0f);
    t.open_spring = Wh_GetIntSetting(L"OpenAnimation.Physics.open_spring") != 0;
    t.open_mass = ParseFloatOpt(L"OpenAnimation.Physics.open_mass", 1.0f);
    t.open_stiffness = ParseFloatOpt(L"OpenAnimation.Physics.open_stiffness", 200.0f);
    t.open_damping = ParseFloatOpt(L"OpenAnimation.Physics.open_damping", 28.0f);
    t.open_bezier = ParseBezier(L"OpenAnimation.open_bezier", 0,0,0,1);
    ParseAdvNew(L"OpenAnimation.Overrides.open_adv_scale", t.open_adv.scale, 350, 0,0,0,1);
    ParseAdvNew(L"OpenAnimation.Overrides.open_adv_opacity", t.open_adv.opacity, 200, 0.3f,0,0.8f,0.15f);
    ParseAdvNew(L"OpenAnimation.Overrides.open_adv_blur", t.open_adv.blur, 300, 0,0,0,1);
    ParseAdvNew(L"OpenAnimation.Overrides.open_adv_pitch", t.open_adv.pitch, 400, 0,0,0,1);
    ParseAdvNew(L"OpenAnimation.Overrides.open_adv_yaw", t.open_adv.yaw, 400, 0,0,0,1);
    ParseAdvNew(L"OpenAnimation.Overrides.open_adv_roll", t.open_adv.roll, 400, 0,0,0,1);

    // CLOSE
    t.enable_close = Wh_GetIntSetting(L"CloseAnimation.enable_close") != 0; 
    t.duration_close = (DWORD)Wh_GetIntSetting(L"CloseAnimation.duration_close");
    if (t.duration_close == 0) t.duration_close = 166;
    t.close_pivot_preset = ParseIntOpt(L"CloseAnimation.close_pivot_preset", 1);
    t.close_pivot_x = 0.5f; t.close_pivot_y = 0.5f;
    ParseScale(L"CloseAnimation.close_scale", t.close_scale_x, t.close_scale_y, 1.0f, 1.0f);
    ParseOffsetXY(L"CloseAnimation.Transform.close_offset", t.close_translate_x, t.close_translate_y, 0, 0);
    t.close_z = ParseFloatOpt(L"CloseAnimation.Transform.close_z", 0.0f);
    t.close_pitch = ParseFloatOpt(L"CloseAnimation.Transform.close_pitch", 5.0f);
    t.close_yaw = ParseFloatOpt(L"CloseAnimation.Transform.close_yaw", 8.0f);
    t.close_roll = ParseFloatOpt(L"CloseAnimation.Transform.close_roll", 0.0f);
    t.close_opacity = ParseFloatOpt(L"CloseAnimation.Appearance.close_opacity", 0.0f);
    t.close_blur = ParseFloatOpt(L"CloseAnimation.Appearance.close_blur", 0.0f);
    t.close_spring = Wh_GetIntSetting(L"CloseAnimation.Physics.close_spring") != 0;
    t.close_mass = ParseFloatOpt(L"CloseAnimation.Physics.close_mass", 1.0f);
    t.close_stiffness = ParseFloatOpt(L"CloseAnimation.Physics.close_stiffness", 200.0f);
    t.close_damping = ParseFloatOpt(L"CloseAnimation.Physics.close_damping", 28.0f);
    t.close_bezier = ParseBezier(L"CloseAnimation.close_bezier", 0.3f,0,0.8f,0.15f);
    ParseAdvNew(L"CloseAnimation.Overrides.close_adv_scale", t.close_adv.scale, 200, 0.3f,0,0.8f,0.15f);
    ParseAdvNew(L"CloseAnimation.Overrides.close_adv_opacity", t.close_adv.opacity, 150, 0.3f,0,0.8f,0.15f);
    ParseAdvNew(L"CloseAnimation.Overrides.close_adv_blur", t.close_adv.blur, 150, 0.3f,0,0.8f,0.15f);
    ParseAdvNew(L"CloseAnimation.Overrides.close_adv_pitch", t.close_adv.pitch, 250, 0.3f,0,0.8f,0.15f);
    ParseAdvNew(L"CloseAnimation.Overrides.close_adv_yaw", t.close_adv.yaw, 250, 0.3f,0,0.8f,0.15f);
    ParseAdvNew(L"CloseAnimation.Overrides.close_adv_roll", t.close_adv.roll, 250, 0.3f,0,0.8f,0.15f);

    // MINIMIZE
    t.enable_minimize = Wh_GetIntSetting(L"MinimizeAnimation.enable_minimize") != 0; 
    t.duration_minimize = (DWORD)Wh_GetIntSetting(L"MinimizeAnimation.duration_minimize");
    if (t.duration_minimize == 0) t.duration_minimize = 250;
    t.min_ignore_taskbar = Wh_GetIntSetting(L"MinimizeAnimation.min_ignore_taskbar") != 0; 
    t.min_track_taskbar = Wh_GetIntSetting(L"MinimizeAnimation.min_track_taskbar") != 0;
    t.min_target_width = ParseFloatOpt(L"MinimizeAnimation.min_target_width", 0.6f);
    t.min_pivot_preset = ParseIntOpt(L"MinimizeAnimation.minimize_pivot_preset", 1);
    t.min_pivot_x = 0.5f; t.min_pivot_y = 0.5f;
    ParseScale(L"MinimizeAnimation.minimize_scale", t.min_scale_x, t.min_scale_y, 1.0f, 1.0f);
    ParseOffsetXY(L"MinimizeAnimation.Transform.minimize_offset", t.min_translate_x, t.min_translate_y, 0, 0);
    t.min_z = ParseFloatOpt(L"MinimizeAnimation.Transform.minimize_z", 0.0f);
    t.min_pitch = ParseFloatOpt(L"MinimizeAnimation.Transform.minimize_pitch", 0.0f);
    t.min_yaw = ParseFloatOpt(L"MinimizeAnimation.Transform.minimize_yaw", 0.0f);
    t.min_roll = ParseFloatOpt(L"MinimizeAnimation.Transform.minimize_roll", 1.0f);
    t.min_opacity = ParseFloatOpt(L"MinimizeAnimation.Appearance.minimize_opacity", 0.0f);
    t.min_blur = ParseFloatOpt(L"MinimizeAnimation.Appearance.minimize_blur", 0.0f);
    t.min_spring = Wh_GetIntSetting(L"MinimizeAnimation.Physics.minimize_spring") != 0;
    t.min_mass = ParseFloatOpt(L"MinimizeAnimation.Physics.minimize_mass", 1.0f);
    t.min_stiffness = ParseFloatOpt(L"MinimizeAnimation.Physics.minimize_stiffness", 200.0f);
    t.min_damping = ParseFloatOpt(L"MinimizeAnimation.Physics.minimize_damping", 28.0f);
    t.min_bezier = ParseBezier(L"MinimizeAnimation.minimize_bezier", 0.3f,0,0.8f,0.15f);
    ParseAdvNew(L"MinimizeAnimation.Overrides.min_adv_scale", t.min_adv.scale, 250, 0.3f,0,0.8f,0.15f);
    ParseAdvNew(L"MinimizeAnimation.Overrides.min_adv_opacity", t.min_adv.opacity, 200, 0.3f,0,0.8f,0.15f);
    ParseAdvNew(L"MinimizeAnimation.Overrides.min_adv_blur", t.min_adv.blur, 250, 0.3f,0,0.8f,0.15f);
    ParseAdvNew(L"MinimizeAnimation.Overrides.min_adv_pitch", t.min_adv.pitch, 250, 0.3f,0,0.8f,0.15f);
    ParseAdvNew(L"MinimizeAnimation.Overrides.min_adv_yaw", t.min_adv.yaw, 250, 0.3f,0,0.8f,0.15f);
    ParseAdvNew(L"MinimizeAnimation.Overrides.min_adv_roll", t.min_adv.roll, 250, 0.3f,0,0.8f,0.15f);

    // RESTORE
    t.enable_restore = Wh_GetIntSetting(L"RestoreAnimation.enable_restore") != 0; 
    t.duration_restore = (DWORD)Wh_GetIntSetting(L"RestoreAnimation.duration_restore");
    if (t.duration_restore == 0) t.duration_restore = 250;
    t.res_ignore_taskbar = Wh_GetIntSetting(L"RestoreAnimation.res_ignore_taskbar") != 0; 
    t.res_track_taskbar = Wh_GetIntSetting(L"RestoreAnimation.res_track_taskbar") != 0;
    t.res_target_width = ParseFloatOpt(L"RestoreAnimation.res_target_width", 0.6f);
    t.res_pivot_preset = ParseIntOpt(L"RestoreAnimation.restore_pivot_preset", 1);
    t.res_pivot_x = 0.5f; t.res_pivot_y = 0.5f;
    ParseScale(L"RestoreAnimation.restore_scale", t.res_scale_x, t.res_scale_y, 1.0f, 1.0f);
    ParseOffsetXY(L"RestoreAnimation.Transform.restore_offset", t.res_translate_x, t.res_translate_y, 0, 0);
    t.res_z = ParseFloatOpt(L"RestoreAnimation.Transform.restore_z", 0.0f);
    t.res_pitch = ParseFloatOpt(L"RestoreAnimation.Transform.restore_pitch", 0.0f);
    t.res_yaw = ParseFloatOpt(L"RestoreAnimation.Transform.restore_yaw", 0.0f);
    t.res_roll = ParseFloatOpt(L"RestoreAnimation.Transform.restore_roll", 1.0f);
    t.res_opacity = ParseFloatOpt(L"RestoreAnimation.Appearance.restore_opacity", 0.0f);
    t.res_blur = ParseFloatOpt(L"RestoreAnimation.Appearance.restore_blur", 0.0f);
    t.res_spring = Wh_GetIntSetting(L"RestoreAnimation.Physics.restore_spring") != 0;
    t.res_mass = ParseFloatOpt(L"RestoreAnimation.Physics.restore_mass", 1.0f);
    t.res_stiffness = ParseFloatOpt(L"RestoreAnimation.Physics.restore_stiffness", 200.0f);
    t.res_damping = ParseFloatOpt(L"RestoreAnimation.Physics.restore_damping", 28.0f);
    t.res_bezier = ParseBezier(L"RestoreAnimation.restore_bezier", 0.0f,0.0f,0.0f,1.0f);
    ParseAdvNew(L"RestoreAnimation.Overrides.res_adv_scale", t.res_adv.scale, 350, 0,0,0,1);
    ParseAdvNew(L"RestoreAnimation.Overrides.res_adv_opacity", t.res_adv.opacity, 200, 0.3f,0,0.8f,0.15f);
    ParseAdvNew(L"RestoreAnimation.Overrides.res_adv_blur", t.res_adv.blur, 300, 0,0,0,1);
    ParseAdvNew(L"RestoreAnimation.Overrides.res_adv_pitch", t.res_adv.pitch, 400, 0,0,0,1);
    ParseAdvNew(L"RestoreAnimation.Overrides.res_adv_yaw", t.res_adv.yaw, 400, 0,0,0,1);
    ParseAdvNew(L"RestoreAnimation.Overrides.res_adv_roll", t.res_adv.roll, 400, 0,0,0,1);

    LPCWSTR presetStr = Wh_GetStringSetting(L"preset");
    if (presetStr) {
        if (wcscmp(presetStr, L"win7") == 0) {
            t.preset = 1;
            t.enable_open = true;
            t.duration_open = 250;
            t.open_pivot_preset = 1;
            t.open_pivot_x = 0.5f; t.open_pivot_y = 0.5f;
            t.open_scale_x = 1.0f; t.open_scale_y = 1.0f;
            t.open_translate_x = 0.0f; t.open_translate_y = 0.0f;
            t.open_z = 0.1f;
            t.open_pitch = 5.0f; t.open_yaw = 0.0f; t.open_roll = 0.0f;
            t.open_opacity = 0.0f; t.open_blur = 0.0f;
            t.open_spring = false;
            t.open_bezier = { 0.0f, 0.5f, 0.5f, 1.0f, {0} };
            BuildBezierLUT(t.open_bezier);

            t.enable_close = true;
            t.duration_close = 166;
            t.close_pivot_preset = 8;
            t.close_pivot_x = 0.5f; t.close_pivot_y = 1.0f;
            t.close_scale_x = 1.0f; t.close_scale_y = 1.0f;
            t.close_translate_x = 0.0f; t.close_translate_y = 0.0f;
            t.close_z = 0.0f;
            t.close_pitch = 5.0f; t.close_yaw = 2.0f; t.close_roll = 0.0f;
            t.close_opacity = 0.0f; t.close_blur = 0.0f;
            t.close_spring = false;
            t.close_bezier = { 0.5f, 0.0f, 1.0f, 0.5f, {0} };
            BuildBezierLUT(t.close_bezier);

            t.enable_minimize = true;
            t.duration_minimize = 250;
            t.min_ignore_taskbar = false;
            t.min_track_taskbar = true;
            t.min_target_width = 0.6f;
            t.min_pivot_preset = 1;
            t.min_pivot_x = 0.5f; t.min_pivot_y = 0.5f;
            t.min_scale_x = 1.0f; t.min_scale_y = 1.0f;
            t.min_translate_x = 0.0f; t.min_translate_y = 0.0f;
            t.min_z = 0.0f;
            t.min_pitch = 5.0f; t.min_yaw = 8.0f; t.min_roll = 1.0f;
            t.min_opacity = 0.85f; t.min_blur = 0.0f;
            t.min_spring = false;
            t.min_bezier = { 0.0f, 0.0f, 1.0f, 1.0f, {0} };
            BuildBezierLUT(t.min_bezier);

            t.enable_restore = true;
            t.duration_restore = 250;
            t.res_ignore_taskbar = false;
            t.res_track_taskbar = true;
            t.res_target_width = 0.6f;
            t.res_pivot_preset = 1;
            t.res_pivot_x = 0.5f; t.res_pivot_y = 0.5f;
            t.res_scale_x = 1.0f; t.res_scale_y = 1.0f;
            t.res_translate_x = 0.0f; t.res_translate_y = 0.0f;
            t.res_z = 0.0f;
            t.res_pitch = 5.0f; t.res_yaw = 8.0f; t.res_roll = 1.0f;
            t.res_opacity = 0.0f; t.res_blur = 0.0f;
            t.res_spring = false;
            t.res_bezier = { 0.0f, 0.5f, 0.5f, 1.0f, {0} };
            BuildBezierLUT(t.res_bezier);
        }
        Wh_FreeStringSetting(presetStr);
    } else {
        t.preset = 0;
    }

    // DRAG - General
    t.drag_pivot_mode = ParseIntOpt(L"DragAnimation.General.drag_pivot_mode", 0);
    t.drag_disable_on_resize = Wh_GetIntSetting(L"DragAnimation.General.drag_disable_on_resize") != 0;
    t.drag_smoothing = ParseFloatOpt(L"DragAnimation.General.drag_smoothing", 15.0f);

    // DRAG - 3D Tilt
    t.enable_drag = Wh_GetIntSetting(L"DragAnimation.Tilt3D.enable_drag") != 0;
    t.drag_intensity = ParseFloatOpt(L"DragAnimation.Tilt3D.drag_intensity", 1.0f);

    // DRAG - 2D Roll
    t.enable_drag_roll = Wh_GetIntSetting(L"DragAnimation.Roll2D.enable_drag_roll") != 0;
    t.drag_roll_intensity = ParseFloatOpt(L"DragAnimation.Roll2D.drag_roll_intensity", 1.0f);

    // DRAG - Jiggle Physics
    t.enable_drag_jiggle = Wh_GetIntSetting(L"DragAnimation.JigglePhysics.enable_drag_jiggle") != 0;
    t.invert_jiggle = Wh_GetIntSetting(L"DragAnimation.JigglePhysics.invert_jiggle") != 0;
    t.jiggle_intensity = ParseFloatOpt(L"DragAnimation.JigglePhysics.jiggle_intensity", 1.0f);
    t.jiggle_stiffness = ParseFloatOpt(L"DragAnimation.JigglePhysics.jiggle_stiffness", 300.0f);
    t.jiggle_damping = ParseFloatOpt(L"DragAnimation.JigglePhysics.jiggle_damping", 15.0f);
    t.jiggle_mass = ParseFloatOpt(L"DragAnimation.JigglePhysics.jiggle_mass", 1.0f);

    g_cached_enable_drag.store(t.enable_drag, std::memory_order_relaxed);
    g_cached_enable_drag_roll.store(t.enable_drag_roll, std::memory_order_relaxed);
    g_cached_enable_drag_jiggle.store(t.enable_drag_jiggle, std::memory_order_relaxed);
    g_cached_invert_jiggle.store(t.invert_jiggle, std::memory_order_relaxed);
    g_cached_drag_pivot_mode.store(t.drag_pivot_mode, std::memory_order_relaxed);
    g_cached_drag_disable_on_resize.store(t.drag_disable_on_resize, std::memory_order_relaxed);
    g_cached_drag_intensity.store(t.drag_intensity, std::memory_order_relaxed);
    g_cached_drag_roll_intensity.store(t.drag_roll_intensity, std::memory_order_relaxed);
    g_cached_drag_smoothing.store(t.drag_smoothing, std::memory_order_relaxed);
    g_cached_jiggle_intensity.store(t.jiggle_intensity, std::memory_order_relaxed);
    g_cached_jiggle_stiffness.store(t.jiggle_stiffness, std::memory_order_relaxed);
    g_cached_jiggle_damping.store(t.jiggle_damping, std::memory_order_relaxed);
    g_cached_jiggle_mass.store(t.jiggle_mass, std::memory_order_relaxed);

    t.anim_vsync = Wh_GetIntSetting(L"System.anim_vsync") != 0;
    t.anim_fps = Wh_GetIntSetting(L"System.anim_fps");
    if (t.anim_fps <= 0) t.anim_fps = 60;
    
    auto currentSettings = GetSafeSettings();
    t.cached_vsync_fps = currentSettings.cached_vsync_fps;

    std::atomic_store(&g_settingsSnapshot, std::make_shared<const MOD_SETTINGS>(t));

    UpdateRefreshRateCache();
}

void Wh_ModSettingsChanged() { LoadModSettings(); }

// --- Physics Math Engine ---
inline float SampleCurveX(float t, float x1, float x2) {
    const float cx = 3.0f * x1; const float bx = 3.0f * (x2 - x1) - cx; const float ax = 1.0f - cx - bx;
    return t * (cx + t * (bx + t * ax));
}
inline float SampleCurveY(float t, float y1, float y2) {
    const float cy = 3.0f * y1; const float by = 3.0f * (y2 - y1) - cy; const float ay = 1.0f - cy - by;
    return t * (cy + t * (by + t * ay));
}
inline float SampleCurveDerivativeX(float t, float x1, float x2) {
    const float cx = 3.0f * x1; const float bx = 3.0f * (x2 - x1) - cx; const float ax = 1.0f - cx - bx;
    return cx + t * (2.0f * bx + 3.0f * ax * t);
}

float SolveCubicBezier(float x, float x1, float y1, float x2, float y2) {
    if (x <= 0.0f) return 0.0f; if (x >= 1.0f) return 1.0f; if (x1 == y1 && x2 == y2) return x; 
    
    float t = x; 
    bool newtonConverged = false;
    
    for (int i = 0; i < 8; i++) {
        float currentX = SampleCurveX(t, x1, x2) - x;
        if (fabsf(currentX) < 0.001f) { newtonConverged = true; break; }
        float dX = SampleCurveDerivativeX(t, x1, x2);
        if (fabsf(dX) < 1e-6f) break;
        t -= currentX / dX;
        t = FastMax(0.0f, FastMin(1.0f, t));
    }
    
    if (!newtonConverged || t < 0.0f || t > 1.0f) {
        float t0 = 0.0f, t1 = 1.0f; t = x;
        for (int i = 0; i < 20; i++) {
            float currentX = SampleCurveX(t, x1, x2);
            if (fabsf(currentX - x) < 0.001f) break;
            if (x > currentX) t0 = t; else t1 = t;
            t = (t1 - t0) * 0.5f + t0;
        }
    }
    return SampleCurveY(t, y1, y2);
}

struct SpringConstants { float w0, zeta, wd, gamma, r1, r2, A, B; int mode; };

SpringConstants InitSpring(float mass, float stiffness, float damping) {
    SpringConstants s = {0};
    if (mass <= 0.0f) mass = 1.0f;
    if (stiffness <= 0.0f) { s.mode = 3; return s; }
    s.w0 = sqrtf(stiffness / mass);
    s.zeta = damping / (2.0f * sqrtf(stiffness * mass));
    if (s.zeta < 1.0f) { s.mode = 0; s.wd = s.w0 * sqrtf(1.0f - s.zeta * s.zeta); s.A = 1.0f; s.B = (s.zeta * s.w0) / s.wd; } 
    else if (s.zeta > 1.0f) { s.mode = 1; s.gamma = s.w0 * sqrtf(s.zeta * s.zeta - 1.0f); s.r1 = -s.zeta * s.w0 + s.gamma; s.r2 = -s.zeta * s.w0 - s.gamma; s.A = -s.r2 / (s.r1 - s.r2); s.B = s.r1 / (s.r1 - s.r2); } 
    else { s.mode = 2; }
    return s;
}

float EvaluateSpring(float t, const SpringConstants& s) {
    if (s.mode == 3) return t >= 1.0f ? 1.0f : 0.0f;
    if (s.mode == 0) return 1.0f - expf(-s.zeta * s.w0 * t) * (s.A * cosf(s.wd * t) + s.B * sinf(s.wd * t));
    if (s.mode == 1) return 1.0f - (s.A * expf(s.r1 * t) + s.B * expf(s.r2 * t));
    return 1.0f - expf(-s.w0 * t) * (1.0f + s.w0 * t);
}

// ---------------------------------------------------------------------------------------------------------------------------

typedef HRESULT(WINAPI* DwmpCreateSharedThumbnailVisual_t)(HWND, HWND, DWORD, DWM_THUMBNAIL_PROPERTIES*, VOID*, VOID**, HTHUMBNAIL*);
typedef HRESULT(WINAPI* DwmUnregisterThumbnail_t)(HTHUMBNAIL);
typedef HRESULT(WINAPI* DwmUpdateThumbnailProperties_t)(HTHUMBNAIL, const DWM_THUMBNAIL_PROPERTIES*);
typedef BOOL(WINAPI* NtUserGetWindowMinimizeRect_t)(HWND, RECT*);

DwmpCreateSharedThumbnailVisual_t PDwmpCreateSharedThumbnailVisual = nullptr;
DwmUnregisterThumbnail_t PDwmUnregisterThumbnail = nullptr;
DwmUpdateThumbnailProperties_t PDwmUpdateThumbnailProperties = nullptr;
NtUserGetWindowMinimizeRect_t PNtUserGetWindowMinimizeRect = nullptr;

static bool RequestWindowCloakDirect(HWND hwnd, bool cloak) {
    if (!hwnd || !IsWindow(hwnd)) return false;
    int value = cloak ? 1 : 0;
    HRESULT hr = DwmSetWindowAttribute(hwnd, 13 /* DWMWA_CLOAK */, &value, sizeof(value));
    return SUCCEEDED(hr);
}

static bool RequestWindowCloak(HWND hwnd, bool cloak) {
    if (RequestWindowCloakDirect(hwnd, cloak)) return true;
    static UINT s_MsgCloak = RegisterWindowMessageW(L"WindowAnimationCloakTrigger");
    SendNotifyMessageW(hwnd, s_MsgCloak, cloak ? 1 : 0, 0);
    return true;
}

static bool QueryWindowCloaked(HWND hwnd, BOOL* cloaked) {
    if (!hwnd || !IsWindow(hwnd) || !cloaked) return false;
    *cloaked = FALSE;
    HRESULT hr = DwmGetWindowAttribute(hwnd, 14 /* DWMWA_CLOAKED */, cloaked, sizeof(*cloaked));
    return SUCCEEDED(hr);
}

struct THUMB_OVERSCAN { int Left; int Top; int Right; int Bottom; };

static THUMB_OVERSCAN ComputeOverscan(const RECT& RcFrame) {
    const int W = FastMax((int)(RcFrame.right - RcFrame.left), 1);
    const int H = FastMax((int)(RcFrame.bottom - RcFrame.top), 1);
    int Pad = FastMax(W, H) / 10;
    if (Pad < 64) Pad = 64;
    if (Pad > 192) Pad = 192;
    return { Pad, Pad, Pad, Pad };
}

struct ANIM_PARAMS {
    HWND HwndOriginal; int AnimType; DWORD MasterDuration;
    RECT RcFrame; RECT RcTaskbar; THUMB_OVERSCAN Overscan; void* PWindowData;
    double CreationTimeSec;
};

struct FAST_TEARDOWN {
    IDCompositionVisual* PRootVisual;
    std::atomic<bool> Signaled;
    FAST_TEARDOWN() : PRootVisual(nullptr), Signaled(false) {}
    ~FAST_TEARDOWN() { if (PRootVisual) PRootVisual->Release(); }
};

struct ACTIVE_ANIM {
    HWND HwndHost; IDCompositionTarget* PTarget; IDCompositionVisual* PRootVisual; RECT HostRect;
    IDCompositionVisual* PTrackingVisual; IDCompositionEffectGroup* PTrackingEffectGroup;
    IDCompositionVisual* PBlurVisual; IDCompositionGaussianBlurEffect* PBlurEffect;
    IDCompositionVisual* PVisual; IDCompositionEffectGroup* PEffectGroup;
    IDCompositionMatrixTransform3D* PTransform; IDCompositionMatrixTransform3D* PTrackingTransform;
    HTHUMBNAIL HThumbnail;
    double EndTimeSec; double RevealWaitDeadlineSec;
    DWORD MasterDuration; int AnimType; HWND HwndOriginal;
    RECT InitialRcFrame; RECT LastRcFrame; RECT RcTaskbar; THUMB_OVERSCAN Overscan;
    float TrackingInitialW; float TrackingInitialH;
    std::vector<IDCompositionAnimation*> ScalarAnimations; void* PWindowData;
    std::shared_ptr<FAST_TEARDOWN> TeardownPtr;
    double CreationTimeSec;
    double CurrentPitch; double CurrentYaw; double CurrentRoll;
    double TargetPitch; double TargetYaw; double TargetRoll;
    double JigglePosX; double JiggleVelX; double JiggleTargetX;
    double JigglePosY; double JiggleVelY; double JiggleTargetY;
    POINT LastCursorPos; double LastCursorTime;
    bool WindowCloaked;
    bool ThumbnailVisible;
    bool PendingUncloak;
    double UncloakStartTimeSec;
    bool DragOverlayRevealed;
    bool CloakRequested;
    double CloakRequestTimeSec;
    bool DragFailed;

    ACTIVE_ANIM() = default;
    ACTIVE_ANIM(
        HWND hHost, IDCompositionTarget* pTgt, IDCompositionVisual* pRoot, RECT hRect,
        IDCompositionVisual* pTrackVis, IDCompositionEffectGroup* pTrackEff,
        IDCompositionVisual* pBlurVis, IDCompositionGaussianBlurEffect* pBlurEff,
        IDCompositionVisual* pVis, IDCompositionEffectGroup* pEffGrp,
        IDCompositionMatrixTransform3D* pTrans, IDCompositionMatrixTransform3D* pTrackTrans,
        HTHUMBNAIL hThumb, double endSec, double revealWaitSec, DWORD masterDur, int aType,
        HWND hOrig, RECT initFrame, RECT lastFrame, RECT rcTb, THUMB_OVERSCAN over,
        float trackInitW, float trackInitH, std::vector<IDCompositionAnimation*>&& scalarAnims,
        void* pWinData, std::shared_ptr<FAST_TEARDOWN> tdPtr, double createSec,
        double curPitch, double curYaw, double curRoll, double tgtPitch, double tgtYaw, double tgtRoll,
        double jX, double jVX, double jTX, double jY, double jVY, double jTY,
        POINT lastCurPos, double lastCurTime, bool winCloaked,
        bool thumbVis = true, bool pendUncloak = false, double uncloakStartSec = 0.0,
        bool dragOverlayRev = false, bool cloakReq = false, double cloakReqTimeSec = 0.0, bool dragFailed = false
    ) : HwndHost(hHost), PTarget(pTgt), PRootVisual(pRoot), HostRect(hRect),
        PTrackingVisual(pTrackVis), PTrackingEffectGroup(pTrackEff),
        PBlurVisual(pBlurVis), PBlurEffect(pBlurEff), PVisual(pVis), PEffectGroup(pEffGrp),
        PTransform(pTrans), PTrackingTransform(pTrackTrans), HThumbnail(hThumb),
        EndTimeSec(endSec), RevealWaitDeadlineSec(revealWaitSec), MasterDuration(masterDur),
        AnimType(aType), HwndOriginal(hOrig), InitialRcFrame(initFrame), LastRcFrame(lastFrame),
        RcTaskbar(rcTb), Overscan(over), TrackingInitialW(trackInitW), TrackingInitialH(trackInitH),
        ScalarAnimations(std::move(scalarAnims)), PWindowData(pWinData), TeardownPtr(tdPtr),
        CreationTimeSec(createSec), CurrentPitch(curPitch), CurrentYaw(curYaw), CurrentRoll(curRoll),
        TargetPitch(tgtPitch), TargetYaw(tgtYaw), TargetRoll(tgtRoll),
        JigglePosX(jX), JiggleVelX(jVX), JiggleTargetX(jTX),
        JigglePosY(jY), JiggleVelY(jVY), JiggleTargetY(jTY),
        LastCursorPos(lastCurPos), LastCursorTime(lastCurTime), WindowCloaked(winCloaked),
        ThumbnailVisible(thumbVis), PendingUncloak(pendUncloak), UncloakStartTimeSec(uncloakStartSec),
        DragOverlayRevealed(dragOverlayRev), CloakRequested(cloakReq), CloakRequestTimeSec(cloakReqTimeSec), DragFailed(dragFailed) {}

    ACTIVE_ANIM(ACTIVE_ANIM&& other) noexcept {
        *this = std::move(other);
    }
    ACTIVE_ANIM& operator=(ACTIVE_ANIM&& other) noexcept {
        if (this != &other) {
            HwndHost = other.HwndHost; other.HwndHost = NULL;
            PTarget = other.PTarget; other.PTarget = nullptr;
            PRootVisual = other.PRootVisual; other.PRootVisual = nullptr;
            HostRect = other.HostRect;
            PTrackingVisual = other.PTrackingVisual; other.PTrackingVisual = nullptr;
            PTrackingEffectGroup = other.PTrackingEffectGroup; other.PTrackingEffectGroup = nullptr;
            PBlurVisual = other.PBlurVisual; other.PBlurVisual = nullptr;
            PBlurEffect = other.PBlurEffect; other.PBlurEffect = nullptr;
            PVisual = other.PVisual; other.PVisual = nullptr;
            PEffectGroup = other.PEffectGroup; other.PEffectGroup = nullptr;
            PTransform = other.PTransform; other.PTransform = nullptr;
            PTrackingTransform = other.PTrackingTransform; other.PTrackingTransform = nullptr;
            HThumbnail = other.HThumbnail; other.HThumbnail = NULL;
            EndTimeSec = other.EndTimeSec;
            RevealWaitDeadlineSec = other.RevealWaitDeadlineSec;
            MasterDuration = other.MasterDuration;
            AnimType = other.AnimType;
            HwndOriginal = other.HwndOriginal;
            InitialRcFrame = other.InitialRcFrame;
            LastRcFrame = other.LastRcFrame;
            RcTaskbar = other.RcTaskbar;
            Overscan = other.Overscan;
            TrackingInitialW = other.TrackingInitialW;
            TrackingInitialH = other.TrackingInitialH;
            ScalarAnimations = std::move(other.ScalarAnimations);
            PWindowData = other.PWindowData; other.PWindowData = nullptr;
            TeardownPtr = std::move(other.TeardownPtr);
            CreationTimeSec = other.CreationTimeSec;
            CurrentPitch = other.CurrentPitch; CurrentYaw = other.CurrentYaw; CurrentRoll = other.CurrentRoll;
            TargetPitch = other.TargetPitch; TargetYaw = other.TargetYaw; TargetRoll = other.TargetRoll;
            JigglePosX = other.JigglePosX; JiggleVelX = other.JiggleVelX; JiggleTargetX = other.JiggleTargetX;
            JigglePosY = other.JigglePosY; JiggleVelY = other.JiggleVelY; JiggleTargetY = other.JiggleTargetY;
            LastCursorPos = other.LastCursorPos; LastCursorTime = other.LastCursorTime;
            WindowCloaked = other.WindowCloaked;
            ThumbnailVisible = other.ThumbnailVisible;
            PendingUncloak = other.PendingUncloak;
            UncloakStartTimeSec = other.UncloakStartTimeSec;
            DragOverlayRevealed = other.DragOverlayRevealed;
            CloakRequested = other.CloakRequested;
            CloakRequestTimeSec = other.CloakRequestTimeSec;
            DragFailed = other.DragFailed;
        }
        return *this;
    }
};

struct DEFERRED_THUMB_UPDATE { HTHUMBNAIL h; DWM_THUMBNAIL_PROPERTIES props; };
struct DEFERRED_WINPOS_UPDATE { HWND hwnd; HWND hwndInsertAfter; int x; int y; int cx; int cy; UINT flags; };
struct REVEAL_OFFSET_INFO { DWORD DynArrayOffset; DWORD TotalCountOffset; };
REVEAL_OFFSET_INFO GRevealOffsetInfo = { 0, 0 };

HINSTANCE GHinst = NULL;
UINT GUMsgAnimateWindow = 0;
UINT GUMsgInstantTeardown = 0;
UINT GUMsgAnimTick = 0;
HANDLE GHAnimWaitableTimer = NULL;
HWND GHwndAnimController = NULL;
HANDLE GHAnimThread = NULL;
DWORD GHAnimThreadId = 0;
bool GAnimationsShiftKeyEnabled = false;

static void StartAnimationTimer(HWND hController);
static void StopAnimationTimer(HWND hController);

typedef HRESULT(__fastcall* CTopLevelWindow3D_StartAnimation_t)(void* Self, unsigned int AnimType);
extern CTopLevelWindow3D_StartAnimation_t CTopLevelWindow3D_StartAnimation_Orig;
typedef HRESULT(__fastcall* CTopLevelWindow3D_StopAnimation_t)(void* Self);
extern CTopLevelWindow3D_StopAnimation_t CTopLevelWindow3D_StopAnimation_Orig;

thread_local DWORD GCustomAnimDuration = 0;
thread_local int GCurrentCustomAnimType = -1;
std::atomic<DWORD> GClassHwndOffset{0};
std::once_flag GScannerFlag;

std::atomic<bool> g_ModUnloading{false};

bool IsSafeToDComp() {
    if (g_ModUnloading.load()) return false;
    static auto pRtlDllShutdownInProgress = (BOOLEAN(NTAPI*)())GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "RtlDllShutdownInProgress");
    return !(pRtlDllShutdownInProgress && pRtlDllShutdownInProgress());
}

LRESULT CALLBACK HostWindowProc(HWND Hwnd, UINT UMsg, WPARAM WParam, LPARAM LParam) {
    if (UMsg == WM_CLOSE) return 0;
    return DefWindowProcW(Hwnd, UMsg, WParam, LParam);
}

ID3D11Device* GPD3DDevice = nullptr;
ID3D11DeviceContext* GPD3DContext = nullptr;
IDCompositionDevice* GPDCompDevice = nullptr;
IDCompositionDevice3* GPDCompDevice3 = nullptr;
std::atomic<bool> GCommitHooked{false};
std::atomic<bool> GIsTimerActive{false};
IUnknown* GPDCompDesktopDevice = nullptr;

static void StartAnimationTimer(HWND hController) {
    if (GIsTimerActive) return;
    timeBeginPeriod(1);
    GIsTimerActive = true;
    
    MOD_SETTINGS settings = GetSafeSettings();
    int targetFps = settings.anim_vsync ? settings.cached_vsync_fps : settings.anim_fps;
    if (targetFps <= 0) targetFps = 60;
    LONG periodMs = FastMax(1, 1000 / targetFps);

    if (!GHAnimWaitableTimer) {
        typedef HANDLE(WINAPI* pfnCreateWaitableTimerExW)(LPSECURITY_ATTRIBUTES, LPCWSTR, DWORD, DWORD);
        auto pCreateWaitableTimerExW = (pfnCreateWaitableTimerExW)GetProcAddress(GetModuleHandleW(L"kernel32.dll"), "CreateWaitableTimerExW");
        if (pCreateWaitableTimerExW) {
            GHAnimWaitableTimer = pCreateWaitableTimerExW(NULL, NULL, 0x00000002 /* CREATE_WAITABLE_TIMER_HIGH_RESOLUTION */, TIMER_ALL_ACCESS);
        }
        if (!GHAnimWaitableTimer) {
            GHAnimWaitableTimer = CreateWaitableTimerW(NULL, FALSE, NULL);
        }
    }

    if (GHAnimWaitableTimer) {
        LARGE_INTEGER dueTime;
        dueTime.QuadPart = -10000LL;
        SetWaitableTimer(GHAnimWaitableTimer, &dueTime, periodMs, NULL, NULL, FALSE);
    }
}

static void StopAnimationTimer(HWND hController) {
    if (!GIsTimerActive) return;
    if (GHAnimWaitableTimer) {
        CancelWaitableTimer(GHAnimWaitableTimer);
    }
    timeEndPeriod(1);
    GIsTimerActive = false;
}

typedef HRESULT(__stdcall* DCompCommit_t)(void*);
DCompCommit_t OrigDCompCommit = nullptr;
std::vector<ACTIVE_ANIM> GAnimations;
std::mutex GAnimationsMutex;
std::recursive_mutex GDCompTreeMutex;
static std::atomic<int> GActiveAnimCount{0};

HRESULT __stdcall HookedDCompCommit(void* pThis) {
    if (pThis != GPDCompDevice && GPDCompDevice && IsSafeToDComp()
        && GActiveAnimCount.load(std::memory_order_relaxed) > 0) {
        std::lock_guard<std::recursive_mutex> lock(GDCompTreeMutex);
        GPDCompDevice->Commit();
    }
    return OrigDCompCommit(pThis);
}

std::unordered_map<HWND, std::shared_ptr<FAST_TEARDOWN>> GFastTeardownMap;
SRWLOCK GTeardownLock = SRWLOCK_INIT;

std::vector<ANIM_PARAMS*> GPendingAnimations;
std::mutex GPendingMutex;

namespace CDesktopManager { DWORD CALLBACK DesktopThreadProc(HANDLE HEvent); }

static double QueryTimeSeconds() {
    static double InvFreq = 0.0;
    if (InvFreq == 0.0) { LARGE_INTEGER Freq; QueryPerformanceFrequency(&Freq); InvFreq = 1.0 / (double)Freq.QuadPart; }
    LARGE_INTEGER Now; QueryPerformanceCounter(&Now); return (double)Now.QuadPart * InvFreq;
}

static std::unordered_map<HWND, double> GDragFailureCooldownUntil;
static std::mutex GDragFailureMutex;

static void MarkDragFailure(HWND hwnd) {
    if (!hwnd) return;
    double until = QueryTimeSeconds() + 0.5; // 500 ms cooldown
    std::lock_guard<std::mutex> lock(GDragFailureMutex);
    GDragFailureCooldownUntil[hwnd] = until;
}

static bool IsDragInFailureCooldown(HWND hwnd) {
    if (!hwnd) return false;
    std::lock_guard<std::mutex> lock(GDragFailureMutex);
    auto it = GDragFailureCooldownUntil.find(hwnd);
    if (it != GDragFailureCooldownUntil.end()) {
        if (QueryTimeSeconds() < it->second) return true;
        GDragFailureCooldownUntil.erase(it);
    }
    return false;
}

static double MsToSeconds(DWORD Ms) { return (double)Ms * 0.001; }
static bool NearlyEqual(float A, float B, float Eps = 0.00001f) { return fabsf(A - B) <= Eps; }

static int GetAnimationSampleCount(DWORD DurationMs, const MOD_SETTINGS& Settings) {
    int EffectiveFps = Settings.anim_vsync ? Settings.cached_vsync_fps : Settings.anim_fps;
    if (EffectiveFps <= 0) EffectiveFps = 60;
    return (int)FastMax(1.0, FastMin(1000.0, ceil((double)DurationMs * (double)EffectiveFps * 0.001)));
}

static DWORD GetFailSafeMs(int AnimType) { return (AnimType == ANIM_TYPE_OPEN || AnimType == ANIM_TYPE_RESTORE) ? 120 : 0; }

static bool TryReadMemory(const void* Address, void* Buffer, SIZE_T Size) {
    SIZE_T BytesRead = 0; 
    return ReadProcessMemory(GetCurrentProcess(), Address, Buffer, Size, &BytesRead) && BytesRead == Size;
}

static bool IsProbablyRevealDynArray(const BYTE* LocalBuffer, DWORD Offset) {
    void* ArrayPtr = *(void**)(LocalBuffer + Offset);
    DWORD Capacity = *(DWORD*)(LocalBuffer + Offset + REVEAL_DYNARRAY_CAPACITY_OFFSET);
    DWORD Count = *(DWORD*)(LocalBuffer + Offset + REVEAL_DYNARRAY_COUNT_OFFSET);
    DWORD TrackedCount = *(DWORD*)(LocalBuffer + Offset + REVEAL_DYNARRAY_TRACKED_COUNT_OFFSET);

    if (!ArrayPtr || (ULONG_PTR)ArrayPtr < 0x10000) return false;
    if (Count == 0 || Count > REVEAL_DYNARRAY_MAX_COUNT || Capacity == 0 || Capacity > REVEAL_DYNARRAY_MAX_CAPACITY) return false;
    if (Count > Capacity || TrackedCount > Count || TrackedCount > REVEAL_DYNARRAY_MAX_COUNT) return false;

    void* FirstEntry = nullptr;
    if (!TryReadMemory(ArrayPtr, &FirstEntry, sizeof(FirstEntry)) || !FirstEntry || (ULONG_PTR)FirstEntry < 0x10000) return false;
    return true;
}

static bool ReadRevealCounter(void* PWindowData, DWORD* PSecondaryRepCount) {
    if (!PWindowData || !PSecondaryRepCount) return false;
    if (GRevealOffsetInfo.TotalCountOffset == 0) {
        BYTE Buffer[MAX_DYNARRAY_READ_BOUNDS] = {0};
        if (!TryReadMemory(PWindowData, Buffer, sizeof(Buffer))) return false;
        for (DWORD Offset = REVEAL_DYNARRAY_SCAN_START; Offset <= REVEAL_DYNARRAY_SCAN_END; Offset += sizeof(void*)) {
            if (IsProbablyRevealDynArray(Buffer, Offset)) {
                GRevealOffsetInfo.DynArrayOffset = Offset; GRevealOffsetInfo.TotalCountOffset = Offset + REVEAL_DYNARRAY_COUNT_OFFSET; break;
            }
        }
        if (GRevealOffsetInfo.TotalCountOffset == 0) return false;
    }
    return TryReadMemory((BYTE*)PWindowData + GRevealOffsetInfo.TotalCountOffset, PSecondaryRepCount, sizeof(DWORD));
}

static bool IsWindowReadyForReveal(void* PWindowData, int AnimType) {
    if (AnimType == ANIM_TYPE_RESTORE) return true;
    DWORD SecondaryRepCount = 0;
    if (!ReadRevealCounter(PWindowData, &SecondaryRepCount)) return true;
    return SecondaryRepCount >= 1;
}

// --- Window Targeting ---
static RECT GetMonitorWorkRectFromRect(const RECT& Rc) {
    HMONITOR HMon = MonitorFromRect(&Rc, MONITOR_DEFAULTTONEAREST); MONITORINFO Mi = { sizeof(Mi) };
    if (HMon && GetMonitorInfoW(HMon, &Mi)) return Mi.rcWork;
    return { GMetrics.xVirtual, GMetrics.yVirtual, GMetrics.xVirtual + GMetrics.cxVirtual, GMetrics.yVirtual + GMetrics.cyVirtual };
}

static RECT GetAnimationHostRect(HWND HwndOriginal, int AnimType) {
    if (AnimType != ANIM_TYPE_MINIMIZE && IsWindow(HwndOriginal) && IsZoomed(HwndOriginal)) {
        RECT RcWindow = { 0 };
        if (GetWindowRect(HwndOriginal, &RcWindow)) return GetMonitorWorkRectFromRect(RcWindow);
    }
    return { GMetrics.xVirtual, GMetrics.yVirtual, GMetrics.xVirtual + GMetrics.cxVirtual, GMetrics.yVirtual + GMetrics.cyVirtual };
}

static bool IsTopmostWindow(HWND Hwnd) { return Hwnd && ((GetWindowLongPtrW(Hwnd, GWL_EXSTYLE) & WS_EX_TOPMOST) != 0); }

static void PositionAnimationHostWindow(HWND HwndHost, HWND HwndOriginal, int AnimType, RECT* PAppliedRect = nullptr, std::vector<DEFERRED_WINPOS_UPDATE>* pDeferredUpdates = nullptr) {
    if (!HwndHost || !IsWindow(HwndHost)) return;
    RECT RcHost = GetAnimationHostRect(HwndOriginal, AnimType);
    int HostW = RcHost.right - RcHost.left; int HostH = RcHost.bottom - RcHost.top;
    if (HostW <= 0 || HostH <= 0) return;

    bool isDrag = (AnimType == ANIM_TYPE_DRAG || AnimType == ANIM_TYPE_DRAG_END);
    bool wantTopmost = false;
    if (!isDrag) {
        wantTopmost = (AnimType == ANIM_TYPE_MINIMIZE || AnimType == ANIM_TYPE_CLOSE || AnimType == ANIM_TYPE_RESTORE);
    }
    if (!wantTopmost && IsWindow(HwndOriginal)) {
        wantTopmost = IsTopmostWindow(HwndOriginal);
    }

    if (!isDrag) {
        LONG_PTR exStyle = GetWindowLongPtrW(HwndHost, GWL_EXSTYLE);
        if (wantTopmost) exStyle |= WS_EX_TOPMOST; else exStyle &= ~WS_EX_TOPMOST;
        SetWindowLongPtrW(HwndHost, GWL_EXSTYLE, exStyle);
    }

    HWND insertAfter = wantTopmost ? HWND_TOPMOST : (IsWindow(HwndOriginal) ? HwndOriginal : HWND_NOTOPMOST);

    if (pDeferredUpdates) {
        pDeferredUpdates->push_back({HwndHost, insertAfter, RcHost.left, RcHost.top, HostW, HostH, SWP_NOACTIVATE | SWP_SHOWWINDOW});
    } else {
        SetWindowPos(HwndHost, insertAfter, RcHost.left, RcHost.top, HostW, HostH, SWP_NOACTIVATE | SWP_SHOWWINDOW);
    }

    if (PAppliedRect) *PAppliedRect = RcHost;
}

#define MAX_HOST_POOL 8
struct HOST_POOL_ENTRY { HWND Hwnd; IDCompositionTarget* Target; IDCompositionVisual* RootVisual; bool InUse; };
HOST_POOL_ENTRY GHostPool[MAX_HOST_POOL] = {{0}};
std::mutex GHostPoolMutex;

static bool GetPooledHostWindow(HWND HwndOriginal, int AnimType, RECT* PHostRect, HWND& OutHwnd, IDCompositionTarget*& OutTarget, IDCompositionVisual*& OutRoot) {
    std::lock_guard<std::recursive_mutex> dcompLock(GDCompTreeMutex);
    std::lock_guard<std::mutex> lock(GHostPoolMutex);
    for (int i = 0; i < MAX_HOST_POOL; ++i) {
        if (!GHostPool[i].InUse && GHostPool[i].Hwnd != NULL) {
            GHostPool[i].InUse = true;
            OutHwnd = GHostPool[i].Hwnd;
            OutTarget = GHostPool[i].Target;
            OutRoot = GHostPool[i].RootVisual;
            
            if (AnimType == ANIM_TYPE_MINIMIZE) {
                SetWindowLongW(OutHwnd, GWL_EXSTYLE, GetWindowLongW(OutHwnd, GWL_EXSTYLE) | WS_EX_TOPMOST);
            } else {
                SetWindowLongW(OutHwnd, GWL_EXSTYLE, GetWindowLongW(OutHwnd, GWL_EXSTYLE) & ~WS_EX_TOPMOST);
            }
            
            PositionAnimationHostWindow(OutHwnd, HwndOriginal, AnimType, PHostRect);
            OutRoot->RemoveAllVisuals();
            return true;
        }
    }
    return false;
}

static void ReturnPooledHostWindow(HWND HwndHost) {
    std::lock_guard<std::recursive_mutex> dcompLock(GDCompTreeMutex);
    std::lock_guard<std::mutex> lock(GHostPoolMutex);
    for (int i = 0; i < MAX_HOST_POOL; ++i) {
        if (GHostPool[i].Hwnd == HwndHost) {
            GHostPool[i].InUse = false;
            GHostPool[i].RootVisual->RemoveAllVisuals();
            if (IsSafeToDComp() && GPDCompDevice) GPDCompDevice->Commit();
            SetWindowPos(HwndHost, NULL, -20000, -20000, 1, 1, SWP_NOACTIVATE | SWP_NOZORDER);
            break;
        }
    }
}

// --- Matrix Engine ---
struct D2DMatrix {
    float M[4][4];
    D2DMatrix() {
        memset(M, 0, sizeof(M));
        M[0][0] = 1.0f; M[1][1] = 1.0f; M[2][2] = 1.0f; M[3][3] = 1.0f;
    }
    D2DMatrix(int) {} 
    D2DMatrix operator*(const D2DMatrix& B) const {
        D2DMatrix Res(0);
        for (int I = 0; I < 4; ++I) {
            for (int J = 0; J < 4; ++J) {
                Res.M[I][J] = M[I][0] * B.M[0][J] + M[I][1] * B.M[1][J] + M[I][2] * B.M[2][J] + M[I][3] * B.M[3][J];
            }
        }
        return Res;
    }
};

struct SAMPLE_POINT { double OffsetSec; D2DMatrix Mat; float Opacity; float Blur; };

D2DMatrix D2DMatrixTranslation(float X, float Y, float Z) { D2DMatrix Res; Res.M[3][0] = X; Res.M[3][1] = Y; Res.M[3][2] = Z; return Res; }
D2DMatrix D2DMatrixRotationX(float Degrees) { float Rad = Degrees * PI_F / 180.0f; float C = cosf(Rad), S = sinf(Rad); D2DMatrix Res; Res.M[1][1] = C; Res.M[1][2] = S; Res.M[2][1] = -S; Res.M[2][2] = C; return Res; }
D2DMatrix D2DMatrixRotationY(float Degrees) { float Rad = Degrees * PI_F / 180.0f; float C = cosf(Rad), S = sinf(Rad); D2DMatrix Res; Res.M[0][0] = C; Res.M[0][2] = -S; Res.M[2][0] = S; Res.M[2][2] = C; return Res; }
D2DMatrix D2DMatrixRotationZ(float Degrees) { float Rad = Degrees * PI_F / 180.0f; float C = cosf(Rad), S = sinf(Rad); D2DMatrix Res; Res.M[0][0] = C; Res.M[0][1] = S; Res.M[1][0] = -S; Res.M[1][1] = C; return Res; }
D2DMatrix D2DMatrixPerspectiveRH(float Depth) { D2DMatrix Res; if (Depth != 0.0f) Res.M[2][3] = -1.0f / Depth; return Res; }
D2DMatrix D2DMatrixScaling(float X, float Y, float Z) { D2DMatrix Res(0); memset(Res.M, 0, sizeof(Res.M)); Res.M[0][0] = X; Res.M[1][1] = Y; Res.M[2][2] = Z; Res.M[3][3] = 1.0f; return Res; }

void GetPivotValues(int preset, float customX, float customY, float& pX, float& pY) {
    if (preset == 0) { pX = customX; pY = customY; return; }
    switch (preset) {
        case 2: pX = 0.0f; pY = 0.0f; break; // TL
        case 3: pX = 0.5f; pY = 0.0f; break; // T
        case 4: pX = 1.0f; pY = 0.0f; break; // TR
        case 5: pX = 0.0f; pY = 0.5f; break; // L
        case 6: pX = 1.0f; pY = 0.5f; break; // R
        case 7: pX = 0.0f; pY = 1.0f; break; // BL
        case 8: pX = 0.5f; pY = 1.0f; break; // B
        case 9: pX = 1.0f; pY = 1.0f; break; // BR
        case 10: pX = 0.5f; pY = 1.0f; break; // Smart (Taskbar-aware) - default, will be overridden
        default: pX = 0.5f; pY = 0.5f; break; // C
    }
}

namespace CTopLevelWindow4D {
    static bool ShouldTrackLiveWindowRect(int AnimType) { return AnimType == ANIM_TYPE_OPEN || AnimType == ANIM_TYPE_RESTORE || AnimType == ANIM_TYPE_DRAG || AnimType == ANIM_TYPE_DRAG_END; }

    static float EvaluateAnimationProgress(int AnimType, double T_sec, DWORD MasterDuration, const MOD_SETTINGS& Settings) {
        bool useSpring = false; float sMass = 1.0f, sStiffness = 200.0f, sDamping = 28.0f; int baseDurMs = 250;
        CubicBezierDef bezier = {0.0f, 0.0f, 0.0f, 1.0f};

        if (AnimType == ANIM_TYPE_OPEN) { baseDurMs = Settings.duration_open; useSpring = Settings.open_spring; sMass = Settings.open_mass; sStiffness = Settings.open_stiffness; sDamping = Settings.open_damping; bezier = Settings.open_bezier; }
        else if (AnimType == ANIM_TYPE_CLOSE) { baseDurMs = Settings.duration_close; useSpring = Settings.close_spring; sMass = Settings.close_mass; sStiffness = Settings.close_stiffness; sDamping = Settings.close_damping; bezier = Settings.close_bezier; }
        else if (AnimType == ANIM_TYPE_MINIMIZE) { baseDurMs = Settings.duration_minimize; useSpring = Settings.min_spring; sMass = Settings.min_mass; sStiffness = Settings.min_stiffness; sDamping = Settings.min_damping; bezier = Settings.min_bezier; }
        else if (AnimType == ANIM_TYPE_RESTORE) { baseDurMs = Settings.duration_restore; useSpring = Settings.res_spring; sMass = Settings.res_mass; sStiffness = Settings.res_stiffness; sDamping = Settings.res_damping; bezier = Settings.res_bezier; }

        if (useSpring) {
            SpringConstants Spring = InitSpring(sMass, sStiffness, sDamping);
            return EvaluateSpring((float)T_sec, Spring);
        } else {
            if (T_sec >= MsToSeconds(baseDurMs)) return 1.0f;
            float BaseProgress = (float)(T_sec / MsToSeconds(baseDurMs));
            return FastSolveCubicBezier(BaseProgress, bezier);
        }
    }

    struct ANIM_TRANSFORM_PARAMS {
        float Pitch, Yaw, Roll, ZTrans, XTrans, YTrans, ScaleX, ScaleY, Opacity, Blur, CurCenterX, CurCenterY, PivotX, PivotY;
        float eTrans, eP, eY, eR, eS, eO, eB;
    };

    void ComputeTransformParams(ANIM_TRANSFORM_PARAMS* pOut, int AnimType, double T_sec, float GlobalEasedProgress, RECT RcFrame, RECT RcTaskbar, const THUMB_OVERSCAN& Overscan, const MOD_SETTINGS& Settings) {
        float W = FastMax((float)(RcFrame.right - RcFrame.left), 1.0f);
        float H = FastMax((float)(RcFrame.bottom - RcFrame.top), 1.0f);

        if (Settings.preset == 1) { // Windows 7 Preset
            double MasterDurSec = MsToSeconds(AnimType == ANIM_TYPE_OPEN ? 250 : (AnimType == ANIM_TYPE_CLOSE ? 166 : 250));
            float t_progress = FastMax(0.0f, FastMin(1.0f, (float)(T_sec / MasterDurSec)));
            float Pitch = 0.0f, Yaw = 0.0f, Roll = 0.0f, ZTrans = 0.0f, XTrans = 0.0f, YTrans = 0.0f, ScaleX = 1.0f, ScaleY = 1.0f, Opacity = 1.0f;
            float pX = 0.5f, pY = 0.5f;

            if (AnimType == ANIM_TYPE_OPEN) {
                float ease = sqrtf(t_progress);
                float invEase = 1.0f - ease;
                Pitch = invEase * 5.0f;
                Yaw = 0.0f;
                Roll = 0.0f;
                ZTrans = invEase * (H * 0.1f);
                XTrans = 0.0f;
                YTrans = invEase * (H * -0.017f);
                ScaleX = 1.0f; ScaleY = 1.0f;
                Opacity = ease;
                pX = 0.5f; pY = 0.5f;
            } else if (AnimType == ANIM_TYPE_CLOSE) {
                float ease = 1.0f - sqrtf(1.0f - t_progress);
                Pitch = ease * -5.0f;
                Yaw = ease * -2.0f;
                Roll = 0.0f;
                ZTrans = 0.0f; XTrans = 0.0f; YTrans = 0.0f;
                ScaleX = 1.0f; ScaleY = 1.0f;
                Opacity = 1.0f - t_progress; // Linear decay!
                pX = 0.5f; pY = 1.0f; // Bottom Center
            } else {
                // MINIMIZE & RESTORE
                bool minimize = (AnimType == ANIM_TYPE_MINIMIZE);
                float cv = minimize ? (1.0f - t_progress) : (1.0f - sqrtf(1.0f - t_progress));
                float v1 = minimize ? t_progress : (1.0f - cv);

                float TbW = FastMax((float)(RcTaskbar.right - RcTaskbar.left), 1.0f);
                float targetWidthRatio = (AnimType == ANIM_TYPE_MINIMIZE)
                    ? Settings.min_target_width
                    : Settings.res_target_width;
                targetWidthRatio = FastMax(0.1f, FastMin(1.0f, targetWidthRatio));
                float finalW = TbW * targetWidthRatio;
                float finalH = finalW * (H / W);
                float finalX = (float)RcTaskbar.left + (finalW * 0.3f);
                float finalY = (float)RcTaskbar.top - finalH;

                float curW = (1.0f - v1) * W + v1 * finalW;
                float curH = (1.0f - v1) * H + v1 * finalH;
                float curX = (1.0f - v1) * (float)RcFrame.left + v1 * finalX;
                float curY = (1.0f - v1) * (float)RcFrame.top + v1 * finalY;

                Opacity = minimize ? (cv * 0.85f) : cv;
                Pitch = v1 * -5.0f;
                Yaw = v1 * -8.0f;
                Roll = v1 * -1.0f;
                ScaleX = curW / W;
                ScaleY = curH / H;
                XTrans = curX - (float)RcFrame.left;
                YTrans = curY - (float)RcFrame.top;
                ZTrans = 0.0f;
                pX = 0.5f; pY = 1.0f; // Bottom Center
            }

            pOut->Pitch = Pitch; pOut->Yaw = Yaw; pOut->Roll = Roll;
            pOut->ZTrans = ZTrans; pOut->XTrans = XTrans; pOut->YTrans = YTrans;
            pOut->ScaleX = ScaleX; pOut->ScaleY = ScaleY;
            pOut->Opacity = Opacity; pOut->Blur = 0.0f;
            pOut->CurCenterX = W * pX + Overscan.Left;
            pOut->CurCenterY = H * pY + Overscan.Top;
            pOut->PivotX = pX; pOut->PivotY = pY;
            pOut->eTrans = GlobalEasedProgress; pOut->eP = GlobalEasedProgress; pOut->eY = GlobalEasedProgress;
            pOut->eR = GlobalEasedProgress; pOut->eS = GlobalEasedProgress; pOut->eO = GlobalEasedProgress; pOut->eB = GlobalEasedProgress;
            return;
        }

        float Opacity = 1.0f; float Blur = 0.0f;
        float XTransVal = 0.0f, YTransVal = 0.0f, PitchVal = 0.0f, YawVal = 0.0f, RollVal = 0.0f, ZTransVal = 0.0f, ScaleStartX = 1.0f, ScaleStartY = 1.0f, BlurMax = 0.0f;
        int PivotPreset = 1; float PivotCustX = 0.5f, PivotCustY = 0.5f;

        AdvAnimSettings Adv;

        if (AnimType == ANIM_TYPE_OPEN) { Adv = Settings.open_adv; XTransVal = Settings.open_translate_x; YTransVal = Settings.open_translate_y; PitchVal = Settings.open_pitch; YawVal = Settings.open_yaw; RollVal = Settings.open_roll; ZTransVal = Settings.open_z; ScaleStartX = Settings.open_scale_x; ScaleStartY = Settings.open_scale_y; BlurMax = Settings.open_blur; PivotPreset = Settings.open_pivot_preset; PivotCustX = Settings.open_pivot_x; PivotCustY = Settings.open_pivot_y; } 
        else if (AnimType == ANIM_TYPE_CLOSE) { Adv = Settings.close_adv; XTransVal = Settings.close_translate_x; YTransVal = Settings.close_translate_y; PitchVal = Settings.close_pitch; YawVal = Settings.close_yaw; RollVal = Settings.close_roll; ZTransVal = Settings.close_z; ScaleStartX = Settings.close_scale_x; ScaleStartY = Settings.close_scale_y; BlurMax = Settings.close_blur; PivotPreset = Settings.close_pivot_preset; PivotCustX = Settings.close_pivot_x; PivotCustY = Settings.close_pivot_y; } 
        else if (AnimType == ANIM_TYPE_MINIMIZE) { Adv = Settings.min_adv; XTransVal = Settings.min_translate_x; YTransVal = Settings.min_translate_y; PitchVal = Settings.min_pitch; YawVal = Settings.min_yaw; RollVal = Settings.min_roll; ZTransVal = Settings.min_z; ScaleStartX = Settings.min_scale_x; ScaleStartY = Settings.min_scale_y; BlurMax = Settings.min_blur; PivotPreset = Settings.min_pivot_preset; PivotCustX = Settings.min_pivot_x; PivotCustY = Settings.min_pivot_y; } 
        else if (AnimType == ANIM_TYPE_RESTORE) { Adv = Settings.res_adv; XTransVal = Settings.res_translate_x; YTransVal = Settings.res_translate_y; PitchVal = Settings.res_pitch; YawVal = Settings.res_yaw; RollVal = Settings.res_roll; ZTransVal = Settings.res_z; ScaleStartX = Settings.res_scale_x; ScaleStartY = Settings.res_scale_y; BlurMax = Settings.res_blur; PivotPreset = Settings.res_pivot_preset; PivotCustX = Settings.res_pivot_x; PivotCustY = Settings.res_pivot_y; }

        auto GetEase = [&](const AdvProperty& prop) -> float {
            if (!prop.enabled) return GlobalEasedProgress;
            double adjusted_sec = T_sec - (prop.delay * 0.001);
            if (adjusted_sec < 0.0) return 0.0f;
            float p = FastMax(0.0f, FastMin(1.0f, (float)(adjusted_sec / (prop.duration * 0.001))));
            return FastSolveCubicBezier(p, prop.bezier);
        };

        float eP = GetEase(Adv.pitch), eY = GetEase(Adv.yaw), eR = GetEase(Adv.roll);
        float eS = GetEase(Adv.scale), eO = GetEase(Adv.opacity), eB = GetEase(Adv.blur);
        float eTrans = GlobalEasedProgress;

        float Pitch = 0.0f, Yaw = 0.0f, Roll = 0.0f, ZTrans = 0.0f, XTrans = 0.0f, YTrans = 0.0f, ScaleX = 1.0f, ScaleY = 1.0f;
        
        float pX = 0.5f, pY = 0.5f;
        GetPivotValues(PivotPreset, PivotCustX, PivotCustY, pX, pY);

        // Smart pivot: adjust horizontal pivot toward taskbar button
        if (PivotPreset == 10 && (AnimType == ANIM_TYPE_MINIMIZE || AnimType == ANIM_TYPE_RESTORE)) {
            float winCx = (float)(RcFrame.left + RcFrame.right) * 0.5f;
            float tbCx = (float)(RcTaskbar.left + RcTaskbar.right) * 0.5f;
            float winW = FastMax((float)(RcFrame.right - RcFrame.left), 1.0f);
            float bias = (tbCx - winCx) / winW;
            pX = FastMax(0.0f, FastMin(1.0f, 0.5f + bias * 0.35f));
            pY = 1.0f; // Bottom pivot for "fold toward taskbar" feel
        }

        float CurCenterX = W * pX + Overscan.Left;
        float CurCenterY = H * pY + Overscan.Top;

        if (AnimType == ANIM_TYPE_OPEN || AnimType == ANIM_TYPE_CLOSE) {
            if (AnimType == ANIM_TYPE_OPEN) {
                Pitch = (1.0f - eP) * PitchVal; Yaw = (1.0f - eY) * YawVal; Roll = (1.0f - eR) * RollVal;
                Opacity = Settings.open_opacity + (eO * (1.0f - Settings.open_opacity));
                Blur = (1.0f - eB) * BlurMax;
                ZTrans = (1.0f - eTrans) * (GMetrics.cxScreen * ZTransVal); XTrans = (1.0f - eTrans) * (GMetrics.cxScreen * XTransVal); YTrans = (1.0f - eTrans) * (GMetrics.cyScreen * YTransVal);
                ScaleX = 1.0f - ((1.0f - eS) * (1.0f - ScaleStartX));
                ScaleY = 1.0f - ((1.0f - eS) * (1.0f - ScaleStartY));
            } else {
                Pitch = eP * -PitchVal; Yaw = eY * -YawVal; Roll = eR * -RollVal;
                ZTrans = eTrans * (GMetrics.cxScreen * ZTransVal); XTrans = eTrans * (GMetrics.cxScreen * XTransVal); YTrans = eTrans * (GMetrics.cyScreen * YTransVal);
                ScaleX = 1.0f - (eS * (1.0f - ScaleStartX));
                ScaleY = 1.0f - (eS * (1.0f - ScaleStartY));
                Opacity = 1.0f - (eO * (1.0f - Settings.close_opacity)); Blur = eB * BlurMax;
            }
        } else {
            float V1 = (AnimType == ANIM_TYPE_MINIMIZE) ? eTrans : (1.0f - eTrans);
            float Op1 = (AnimType == ANIM_TYPE_MINIMIZE) ? eO : (1.0f - eO);
            float Bl1 = (AnimType == ANIM_TYPE_MINIMIZE) ? eB : (1.0f - eB);
            
            float targetOp = (AnimType == ANIM_TYPE_MINIMIZE) ? Settings.min_opacity : Settings.res_opacity;
            Opacity = targetOp + ((1.0f - Op1) * (1.0f - targetOp));
            Blur = Bl1 * BlurMax;

            float WinX = (float)RcFrame.left - Overscan.Left, WinY = (float)RcFrame.top - Overscan.Top;
            float FinalW = W, FinalH = H, FinalX = (float)RcFrame.left, FinalY = (float)RcFrame.top;
            bool ignoreTaskbar = (AnimType == ANIM_TYPE_MINIMIZE) ? Settings.min_ignore_taskbar : Settings.res_ignore_taskbar;

            if (!ignoreTaskbar) {
                float TbW = FastMax((float)(RcTaskbar.right - RcTaskbar.left), 1.0f);
                float TbH = FastMax((float)(RcTaskbar.bottom - RcTaskbar.top), 1.0f);
                float TbX = (float)RcTaskbar.left, TbY = (float)RcTaskbar.top;
                float targetWidthRatio = (AnimType == ANIM_TYPE_MINIMIZE)
                    ? Settings.min_target_width
                    : Settings.res_target_width;
                targetWidthRatio = FastMax(0.1f, FastMin(1.0f, targetWidthRatio));
                FinalW = TbW * targetWidthRatio; 
                FinalH = FinalW * (H / W);
                FinalX = TbX + (TbW - FinalW) * 0.5f; 
                FinalY = TbY + (TbH - FinalH) * 0.5f; 
            }

            float CurW = (1.0f - V1) * W + V1 * FinalW; float CurH = (1.0f - V1) * H + V1 * FinalH;
            
            Pitch = (AnimType == ANIM_TYPE_MINIMIZE) ? (eP * -PitchVal) : ((1.0f - eP) * -PitchVal);
            Yaw = (AnimType == ANIM_TYPE_MINIMIZE) ? (eY * -YawVal) : ((1.0f - eY) * -YawVal);
            Roll = (AnimType == ANIM_TYPE_MINIMIZE) ? (eR * -RollVal) : ((1.0f - eR) * -RollVal);
            ZTrans = V1 * ZTransVal * (float)GMetrics.cxScreen;
            
            float VScale = (AnimType == ANIM_TYPE_MINIMIZE) ? eS : (1.0f - eS);
            float ScaleMultX = 1.0f - (VScale * (1.0f - ScaleStartX));
            float ScaleMultY = 1.0f - (VScale * (1.0f - ScaleStartY));
            
            ScaleX = (CurW * ScaleMultX) / W; ScaleY = (CurH * ScaleMultY) / H;
            
            float EndCenterX = FinalX - WinX + FinalW * pX; 
            float EndCenterY = FinalY - WinY + FinalH * pY;

            XTrans = V1 * (EndCenterX - CurCenterX) + V1 * (GMetrics.cxScreen * XTransVal);
            YTrans = V1 * (EndCenterY - CurCenterY) + V1 * (GMetrics.cyScreen * YTransVal);
        }

        pOut->Pitch = Pitch; pOut->Yaw = Yaw; pOut->Roll = Roll;
        pOut->ZTrans = ZTrans; pOut->XTrans = XTrans; pOut->YTrans = YTrans;
        pOut->ScaleX = ScaleX; pOut->ScaleY = ScaleY;
        pOut->Opacity = Opacity;
        pOut->Blur = Blur;
        pOut->CurCenterX = CurCenterX; pOut->CurCenterY = CurCenterY;
        pOut->PivotX = pX; pOut->PivotY = pY;
        pOut->eTrans = eTrans; pOut->eP = eP; pOut->eY = eY; pOut->eR = eR;
        pOut->eS = eS; pOut->eO = eO; pOut->eB = eB;
    }

    void BuildMatrixFromParams(D2DMatrix* PMatFinal, const ANIM_TRANSFORM_PARAMS& p, int AnimType, float W, float H, const THUMB_OVERSCAN& Overscan, int Preset = 0) {
        if (Preset == 1) { // Windows 7 Preset
            float WinCenterX = W * 0.5f + (float)Overscan.Left;
            float WinCenterY = H * 0.5f + (float)Overscan.Top;

            if (AnimType == ANIM_TYPE_OPEN || AnimType == ANIM_TYPE_CLOSE) {
                float pivotX = (float)Overscan.Left;
                float pivotY = (AnimType == ANIM_TYPE_OPEN) ? WinCenterY : (H + (float)Overscan.Top);
                
                D2DMatrix MatModel = D2DMatrixTranslation(-pivotX, -pivotY, 0.0f);
                if (p.Yaw != 0.0f) MatModel = MatModel * D2DMatrixRotationY(p.Yaw);
                if (p.Pitch != 0.0f) MatModel = MatModel * D2DMatrixRotationX(p.Pitch);
                MatModel = MatModel * D2DMatrixTranslation(pivotX, pivotY + p.YTrans, p.ZTrans);

                float PerspDepth = FastMax(H, 1.0f) * 0.8f;
                D2DMatrix MatCamera = D2DMatrixTranslation(-WinCenterX, -WinCenterY, 0.0f) * D2DMatrixScaling(1.0f, 1.0f, -1.0f) * D2DMatrixPerspectiveRH(PerspDepth) * D2DMatrixTranslation(WinCenterX, WinCenterY, 0.0f);

                *PMatFinal = MatModel * MatCamera;
            } else {
                // MINIMIZE & RESTORE
                float cxScreen = (float)GMetrics.cxScreen;
                float camX = W * 0.5f, camY = H * 0.5f;

                D2DMatrix MatModel = D2DMatrixScaling(1.0f / W, 1.0f / H, 1.0f) *
                                     D2DMatrixTranslation(0.0f, -1.0f, 0.0f);
                if (p.Roll != 0.0f) MatModel = MatModel * D2DMatrixRotationZ(p.Roll);
                if (p.Pitch != 0.0f) MatModel = MatModel * D2DMatrixRotationX(p.Pitch);
                if (p.Yaw != 0.0f) MatModel = MatModel * D2DMatrixRotationY(p.Yaw);
                MatModel = MatModel * D2DMatrixTranslation(0.0f, 1.0f, 0.0f) *
                           D2DMatrixScaling(p.ScaleX * W, p.ScaleY * H, cxScreen);

                D2DMatrix MatCamera = D2DMatrixTranslation(-camX, -camY, 0.0f) *
                                      D2DMatrixScaling(1.0f, 1.0f, -1.0f) *
                                      D2DMatrixPerspectiveRH(cxScreen) *
                                      D2DMatrixTranslation(camX, camY, 0.0f);

                D2DMatrix Mat2DOffset = D2DMatrixTranslation(p.XTrans, p.YTrans, 0.0f);

                D2DMatrix MatExp = MatModel * MatCamera * Mat2DOffset;

                *PMatFinal = D2DMatrixTranslation(-(float)Overscan.Left, -(float)Overscan.Top, 0.0f) *
                             MatExp *
                             D2DMatrixTranslation((float)Overscan.Left, (float)Overscan.Top, 0.0f);
            }
            return;
        }

        D2DMatrix MatModel; D2DMatrix MatCamera; D2DMatrix Mat2DOffset;
        float WinCenterX = W * 0.5f + Overscan.Left;
        float WinCenterY = H * 0.5f + Overscan.Top;

        MatModel = D2DMatrixTranslation(-p.CurCenterX, -p.CurCenterY, 0.0f);
        if (p.ScaleX != 1.0f || p.ScaleY != 1.0f) MatModel = MatModel * D2DMatrixScaling(p.ScaleX, p.ScaleY, 1.0f);
        if (p.Roll != 0.0f) MatModel = MatModel * D2DMatrixRotationZ(p.Roll);
        if (p.Yaw != 0.0f) MatModel = MatModel * D2DMatrixRotationY(p.Yaw);
        if (p.Pitch != 0.0f) MatModel = MatModel * D2DMatrixRotationX(p.Pitch);
        MatModel = MatModel * D2DMatrixTranslation(p.CurCenterX, p.CurCenterY, p.ZTrans);

        float PerspDepth = (AnimType == ANIM_TYPE_OPEN || AnimType == ANIM_TYPE_CLOSE) ? (H * 0.8f) : ((float)GMetrics.cxScreen);
        MatCamera = D2DMatrixTranslation(-WinCenterX, -WinCenterY, 0.0f) * 
                    D2DMatrixScaling(1.0f, 1.0f, -1.0f) * 
                    D2DMatrixPerspectiveRH(PerspDepth) * 
                    D2DMatrixTranslation(WinCenterX, WinCenterY, 0.0f);
        Mat2DOffset = D2DMatrixTranslation(p.XTrans, p.YTrans, 0.0f);
        *PMatFinal = MatModel * MatCamera * Mat2DOffset;
    }

    static void SetTrackingVisualRect(IDCompositionVisual* PTrackingVisual, IDCompositionMatrixTransform3D* PTrackingTransform, const RECT& HostRect, const RECT& InitialRcFrame, const RECT& RcNow, const THUMB_OVERSCAN& Overscan) {
        if (!PTrackingVisual || !PTrackingTransform) return;
        D3DMATRIX Mat = {{{0}}}; Mat._11 = 1.0f; Mat._22 = 1.0f; Mat._33 = 1.0f; Mat._44 = 1.0f;
        PTrackingTransform->SetMatrix(Mat);
        PTrackingVisual->SetOffsetX((float)(RcNow.left - HostRect.left - Overscan.Left));
        PTrackingVisual->SetOffsetY((float)(RcNow.top - HostRect.top - Overscan.Top));
    }

    static IDCompositionAnimation* CreateSteppedMatrixAnimation(const std::vector<SAMPLE_POINT>& Samples, int Row, int Col) {
        if (!GPDCompDevice || Samples.size() < 2) return nullptr;
        IDCompositionAnimation* Anim = nullptr;
        if (FAILED(GPDCompDevice->CreateAnimation(&Anim)) || !Anim) return nullptr;

        for (size_t I = 0; I + 1 < Samples.size(); ++I) {
            double T0 = Samples[I].OffsetSec, T1 = Samples[I + 1].OffsetSec; float V0 = Samples[I].Mat.M[Row][Col], V1 = Samples[I + 1].Mat.M[Row][Col];
            double Dt = T1 - T0; if (Dt <= 0.0) continue;
            double Slope = ((double)V1 - (double)V0) / Dt;
            if (FAILED(Anim->AddCubic(T0, V0, Slope, 0.0, 0.0))) { Anim->Release(); return nullptr; }
        }
        if (FAILED(Anim->End(Samples.back().OffsetSec, Samples.back().Mat.M[Row][Col]))) { Anim->Release(); return nullptr; }
        return Anim;
    }

    static IDCompositionAnimation* CreateSteppedOpacityAnimation(const std::vector<SAMPLE_POINT>& Samples) {
        if (!GPDCompDevice || Samples.size() < 2) return nullptr;
        IDCompositionAnimation* Anim = nullptr;
        if (FAILED(GPDCompDevice->CreateAnimation(&Anim)) || !Anim) return nullptr;

        for (size_t I = 0; I + 1 < Samples.size(); ++I) {
            double T0 = Samples[I].OffsetSec, T1 = Samples[I + 1].OffsetSec; float V0 = Samples[I].Opacity, V1 = Samples[I+1].Opacity;
            double Dt = T1 - T0; if (Dt <= 0.0) continue;
            double Slope = ((double)V1 - (double)V0) / Dt;
            if (FAILED(Anim->AddCubic(T0, V0, Slope, 0.0, 0.0))) { Anim->Release(); return nullptr; }
        }
        if (FAILED(Anim->End(Samples.back().OffsetSec, Samples.back().Opacity))) { Anim->Release(); return nullptr; }
        return Anim;
    }

    static IDCompositionAnimation* CreateSteppedBlurAnimation(const std::vector<SAMPLE_POINT>& Samples) {
        if (!GPDCompDevice || Samples.size() < 2) return nullptr;
        IDCompositionAnimation* Anim = nullptr;
        if (FAILED(GPDCompDevice->CreateAnimation(&Anim)) || !Anim) return nullptr;

        for (size_t I = 0; I + 1 < Samples.size(); ++I) {
            double T0 = Samples[I].OffsetSec, T1 = Samples[I + 1].OffsetSec; float V0 = Samples[I].Blur, V1 = Samples[I+1].Blur;
            double Dt = T1 - T0; if (Dt <= 0.0) continue;
            double Slope = ((double)V1 - (double)V0) / Dt;
            if (FAILED(Anim->AddCubic(T0, V0, Slope, 0.0, 0.0))) { Anim->Release(); return nullptr; }
        }
        if (FAILED(Anim->End(Samples.back().OffsetSec, Samples.back().Blur))) { Anim->Release(); return nullptr; }
        return Anim;
    }

    static void ReleaseAnimationResources(ACTIVE_ANIM& Anim) {
        std::unique_lock<std::recursive_mutex> dcompLock(GDCompTreeMutex);
        if (Anim.PRootVisual && Anim.PTrackingVisual) Anim.PRootVisual->RemoveVisual(Anim.PTrackingVisual);
        for (auto* A : Anim.ScalarAnimations) if (A) A->Release();
        Anim.ScalarAnimations.clear();

        if (Anim.PTrackingTransform) Anim.PTrackingTransform->Release(); if (Anim.PTrackingEffectGroup) Anim.PTrackingEffectGroup->Release();
        if (Anim.PBlurEffect) Anim.PBlurEffect->Release(); if (Anim.PBlurVisual) Anim.PBlurVisual->Release();
        if (Anim.PTrackingVisual) Anim.PTrackingVisual->Release(); if (Anim.PTransform) Anim.PTransform->Release();
        if (Anim.PEffectGroup) Anim.PEffectGroup->Release();

        if (Anim.PVisual) Anim.PVisual->Release();
        if (Anim.HThumbnail && PDwmUnregisterThumbnail) PDwmUnregisterThumbnail(Anim.HThumbnail);

        if (Anim.HwndHost) ReturnPooledHostWindow(Anim.HwndHost);
    }

    static void ClearFastTeardown(HWND Hwnd) {
        AcquireSRWLockExclusive(&GTeardownLock);
        GFastTeardownMap.erase(Hwnd);
        ReleaseSRWLockExclusive(&GTeardownLock);
    }

    static bool BuildAnimation(IDCompositionMatrixTransform3D* PTransform, IDCompositionEffectGroup* PEffectGroup, IDCompositionGaussianBlurEffect* PBlurEffect, int AnimType, DWORD MasterDuration, RECT RcFrame, RECT RcTaskbar, const THUMB_OVERSCAN& Overscan, std::vector<IDCompositionAnimation*>& AnimRefs, bool IsInterruption, const ANIM_TRANSFORM_PARAMS& OldParams, const MOD_SETTINGS& Settings) {
        if (AnimType == ANIM_TYPE_DRAG || AnimType == ANIM_TYPE_DRAG_END) {
            // Overlay opacity for drag is managed by the handoff state machine.
            return true;
        }
        if (MasterDuration == 0) MasterDuration = 1;
        const int SampleCount = GetAnimationSampleCount(MasterDuration, Settings); const double MasterDurationSec = MsToSeconds(MasterDuration);
        
        std::vector<SAMPLE_POINT> Samples; Samples.reserve(SampleCount + 1);
        double InverseSampleCount = 1.0 / (double)SampleCount;

        ANIM_TRANSFORM_PARAMS NewBaseParams = {0};
        ANIM_TRANSFORM_PARAMS DeltaParams = {0};
        if (IsInterruption) {
            ComputeTransformParams(&NewBaseParams, AnimType, 0.0, 0.0f, RcFrame, RcTaskbar, Overscan, Settings);
            DeltaParams.Pitch = OldParams.Pitch - NewBaseParams.Pitch;
            DeltaParams.Yaw = OldParams.Yaw - NewBaseParams.Yaw;
            DeltaParams.Roll = OldParams.Roll - NewBaseParams.Roll;
            DeltaParams.ZTrans = OldParams.ZTrans - NewBaseParams.ZTrans;
            DeltaParams.XTrans = OldParams.XTrans - NewBaseParams.XTrans;
            DeltaParams.YTrans = OldParams.YTrans - NewBaseParams.YTrans;
            DeltaParams.ScaleX = OldParams.ScaleX - NewBaseParams.ScaleX;
            DeltaParams.ScaleY = OldParams.ScaleY - NewBaseParams.ScaleY;
            DeltaParams.Opacity = OldParams.Opacity - NewBaseParams.Opacity;
            DeltaParams.Blur = OldParams.Blur - NewBaseParams.Blur;
            DeltaParams.CurCenterX = OldParams.CurCenterX - NewBaseParams.CurCenterX;
            DeltaParams.CurCenterY = OldParams.CurCenterY - NewBaseParams.CurCenterY;
        }

        float W = FastMax((float)(RcFrame.right - RcFrame.left), 1.0f);
        float H = FastMax((float)(RcFrame.bottom - RcFrame.top), 1.0f);

        for (int I = 0; I <= SampleCount; ++I) {
            double Progress = (double)I * InverseSampleCount; 
            double T_sec = MasterDurationSec * Progress;
            
            float GlobalEasedProgress = EvaluateAnimationProgress(AnimType, T_sec, MasterDuration, Settings);

            ANIM_TRANSFORM_PARAMS PtParams;
            ComputeTransformParams(&PtParams, AnimType, T_sec, GlobalEasedProgress, RcFrame, RcTaskbar, Overscan, Settings);

            if (IsInterruption) {
                float DecayTrans = 1.0f - PtParams.eTrans;
                float DecayPitch = 1.0f - PtParams.eP;
                float DecayYaw = 1.0f - PtParams.eY;
                float DecayRoll = 1.0f - PtParams.eR;
                float DecayScale = 1.0f - PtParams.eS;
                float DecayOpacity = 1.0f - PtParams.eO;
                float DecayBlur = 1.0f - PtParams.eB;

                PtParams.Pitch += DeltaParams.Pitch * DecayPitch;
                PtParams.Yaw += DeltaParams.Yaw * DecayYaw;
                PtParams.Roll += DeltaParams.Roll * DecayRoll;
                PtParams.ZTrans += DeltaParams.ZTrans * DecayTrans;
                PtParams.XTrans += DeltaParams.XTrans * DecayTrans;
                PtParams.YTrans += DeltaParams.YTrans * DecayTrans;
                PtParams.ScaleX += DeltaParams.ScaleX * DecayScale;
                PtParams.ScaleY += DeltaParams.ScaleY * DecayScale;
                PtParams.Opacity += DeltaParams.Opacity * DecayOpacity;
                PtParams.Blur += DeltaParams.Blur * DecayBlur;
                PtParams.CurCenterX += DeltaParams.CurCenterX * DecayTrans;
                PtParams.CurCenterY += DeltaParams.CurCenterY * DecayTrans;
            }

            PtParams.ScaleX = FastMax(PtParams.ScaleX, 0.001f);
            PtParams.ScaleY = FastMax(PtParams.ScaleY, 0.001f);
            PtParams.Opacity = FastMax(0.0f, FastMin(1.0f, PtParams.Opacity));
            PtParams.Blur = FastMax(0.0f, PtParams.Blur);
            PtParams.ZTrans = FastMax(PtParams.ZTrans, -(H * 0.8f) + 1.0f);

            SAMPLE_POINT Pt = {}; Pt.OffsetSec = T_sec;
            Pt.Opacity = PtParams.Opacity;
            Pt.Blur = PtParams.Blur;
            BuildMatrixFromParams(&Pt.Mat, PtParams, AnimType, W, H, Overscan, Settings.preset);
            Samples.push_back(Pt);
        }

        D3DMATRIX Base = {}; memcpy(&Base, &Samples[0].Mat, sizeof(Base));
        
        if (FAILED(PTransform->SetMatrix(Base))) return false;

        for (int Row = 0; Row < 4; ++Row) {
            for (int Col = 0; Col < 4; ++Col) {
                float First = Samples[0].Mat.M[Row][Col]; bool Changed = false;
                for (size_t I = 1; I < Samples.size(); ++I) { if (!NearlyEqual(First, Samples[I].Mat.M[Row][Col])) { Changed = true; break; } }
                if (!Changed) continue;
                IDCompositionAnimation* Anim = CreateSteppedMatrixAnimation(Samples, Row, Col);
                if (!Anim) return false;
                if (FAILED(PTransform->SetMatrixElement(Row, Col, Anim))) { Anim->Release(); return false; }
                AnimRefs.push_back(Anim);
            }
        }

        float BaseOpacity = Samples[0].Opacity; bool OpacityChanged = false;
        for (size_t I = 1; I < Samples.size(); ++I) { if (!NearlyEqual(BaseOpacity, Samples[I].Opacity)) { OpacityChanged = true; break; } }
        
        if (OpacityChanged) {
            IDCompositionAnimation* OpacityAnim = CreateSteppedOpacityAnimation(Samples);
            if (!OpacityAnim) return false;
            if (FAILED(PEffectGroup->SetOpacity(OpacityAnim))) { OpacityAnim->Release(); return false; }
            AnimRefs.push_back(OpacityAnim);
        } 

        if (PBlurEffect) {
            float BaseBlur = Samples[0].Blur; bool BlurChanged = false;
            for (size_t I = 1; I < Samples.size(); ++I) { if (!NearlyEqual(BaseBlur, Samples[I].Blur)) { BlurChanged = true; break; } }

            if (BlurChanged) {
                IDCompositionAnimation* BlurAnim = CreateSteppedBlurAnimation(Samples);
                if (!BlurAnim) return false;
                if (FAILED(PBlurEffect->SetStandardDeviation(BlurAnim))) { BlurAnim->Release(); return false; }
                AnimRefs.push_back(BlurAnim);
            }
        }
        return true;
    }

    static void SignalEarlyReveal(HWND hwnd) {
        if (GHwndAnimController)
            PostMessageW(GHwndAnimController, GUMsgInstantTeardown, 0, (LPARAM)hwnd);
    }

    void UpdateScene3D(ANIM_PARAMS* PParams) {
        UpdateMetricsCache();
        
        HWND HWnd = PParams->HwndOriginal; int AnimType = PParams->AnimType; DWORD MasterDuration = PParams->MasterDuration;
        RECT RcFrame = PParams->RcFrame; RECT RcTaskbar = PParams->RcTaskbar; THUMB_OVERSCAN Overscan = PParams->Overscan;
        void* PWindowData = PParams->PWindowData;

        if (!GPDCompDevice || !PDwmpCreateSharedThumbnailVisual) return;

        bool IsInterruption = false;
        ANIM_TRANSFORM_PARAMS OldParams = {0};
        ACTIVE_ANIM ExistingAnim = {};
        MOD_SETTINGS Settings = GetSafeSettings();

        {
            std::lock_guard<std::mutex> lock(GAnimationsMutex);
            for (auto it = GAnimations.begin(); it != GAnimations.end(); ++it) {
                if (it->HwndOriginal == HWnd) {
                    for (auto* A : it->ScalarAnimations) if (A) A->Release();
                    it->ScalarAnimations.clear();
                    ExistingAnim = std::move(*it);
                    IsInterruption = true;
                    GAnimations.erase(it);
                    GActiveAnimCount.fetch_sub(1, std::memory_order_relaxed);
                    break;
                }
            }
        }

        double NowSec = QueryTimeSeconds();
        RECT RcHost = { 0 }; 

        if (IsInterruption) {
            double OldT_sec = FastMax(0.0, NowSec - ExistingAnim.CreationTimeSec);
            float OldProgress = EvaluateAnimationProgress(ExistingAnim.AnimType, OldT_sec, ExistingAnim.MasterDuration, Settings);
            ComputeTransformParams(&OldParams, ExistingAnim.AnimType, OldT_sec, OldProgress, ExistingAnim.InitialRcFrame, ExistingAnim.RcTaskbar, ExistingAnim.Overscan, Settings);
            
            float OldH = FastMax((float)(ExistingAnim.InitialRcFrame.bottom - ExistingAnim.InitialRcFrame.top), 1.0f);
            OldParams.ScaleX = FastMax(OldParams.ScaleX, 0.001f);
            OldParams.ScaleY = FastMax(OldParams.ScaleY, 0.001f);
            OldParams.Opacity = FastMax(0.0f, FastMin(1.0f, OldParams.Opacity));
            OldParams.Blur = FastMax(0.0f, OldParams.Blur);
            OldParams.ZTrans = FastMax(OldParams.ZTrans, -(OldH * 0.8f) + 1.0f);
        }

        HWND HwndHost = NULL;
        IDCompositionTarget* PTarget = nullptr; IDCompositionVisual* PRootVisual = nullptr;
        IDCompositionVisual* PAnimVisual = nullptr; HTHUMBNAIL HThumbnail = NULL;
        IDCompositionVisual* PTrackingVisual = nullptr; IDCompositionEffectGroup* PTrackingEffectGroup = nullptr;
        IDCompositionVisual* PBlurVisual = nullptr; IDCompositionGaussianBlurEffect* PBlurEffect = nullptr;
        IDCompositionMatrixTransform3D* PTrackingTransform = nullptr; IDCompositionEffectGroup* PEffectGroup = nullptr;
        IDCompositionMatrixTransform3D* PTransform = nullptr;
        std::vector<IDCompositionAnimation*> AnimRefs;
        std::shared_ptr<FAST_TEARDOWN> teardown;

        auto cleanup = [&]() {
            ClearFastTeardown(HWnd);
            for (auto* A : AnimRefs) if (A) A->Release();
            if (PTransform) PTransform->Release(); if (PEffectGroup) PEffectGroup->Release();
            if (PBlurEffect) PBlurEffect->Release(); if (PBlurVisual) PBlurVisual->Release();
            if (PTrackingTransform) PTrackingTransform->Release(); if (PTrackingEffectGroup) PTrackingEffectGroup->Release();
            if (PTrackingVisual) PTrackingVisual->Release(); if (PAnimVisual) PAnimVisual->Release();
            if (HThumbnail && PDwmUnregisterThumbnail) PDwmUnregisterThumbnail(HThumbnail);
            if (HwndHost) ReturnPooledHostWindow(HwndHost);
        };

        std::unique_lock<std::recursive_mutex> dcompLock(GDCompTreeMutex);

        if (IsInterruption) {
            HwndHost = ExistingAnim.HwndHost;
            PTarget = ExistingAnim.PTarget;
            PRootVisual = ExistingAnim.PRootVisual;
            PAnimVisual = ExistingAnim.PVisual;
            HThumbnail = ExistingAnim.HThumbnail;
            PTrackingVisual = ExistingAnim.PTrackingVisual;
            PTrackingEffectGroup = ExistingAnim.PTrackingEffectGroup;
            PBlurVisual = ExistingAnim.PBlurVisual;
            PBlurEffect = ExistingAnim.PBlurEffect;
            PTrackingTransform = ExistingAnim.PTrackingTransform;
            PEffectGroup = ExistingAnim.PEffectGroup;
            PTransform = ExistingAnim.PTransform;
            teardown = ExistingAnim.TeardownPtr;
            
            if (teardown) teardown->Signaled.store(false);

            for (auto* A : ExistingAnim.ScalarAnimations) if (A) A->Release();
            ExistingAnim.ScalarAnimations.clear();

            int Width = FastMax((int)(RcFrame.right - RcFrame.left), 1);
            int Height = FastMax((int)(RcFrame.bottom - RcFrame.top), 1);
            int PaddedWidth = Width + Overscan.Left + Overscan.Right; int PaddedHeight = Height + Overscan.Top + Overscan.Bottom;
            DWM_THUMBNAIL_PROPERTIES Thumb = { 0 };
            Thumb.dwFlags = DWM_TNP_VISIBLE | DWM_TNP_RECTDESTINATION | DWM_TNP_RECTSOURCE | DWM_TNP_OPACITY | DWM_TNP_ENABLE3D;
            Thumb.opacity = 255; Thumb.fVisible = TRUE;
            Thumb.rcDestination = { 0, 0, PaddedWidth, PaddedHeight };
            Thumb.rcSource = { -Overscan.Left, -Overscan.Top, Width + Overscan.Right, Height + Overscan.Bottom };
            if (PDwmUpdateThumbnailProperties && HThumbnail) PDwmUpdateThumbnailProperties(HThumbnail, &Thumb);

            PositionAnimationHostWindow(HwndHost, HWnd, AnimType, &RcHost);
            SetTrackingVisualRect(PTrackingVisual, PTrackingTransform, RcHost, RcFrame, RcFrame, Overscan);

            if (AnimType == ANIM_TYPE_DRAG && PEffectGroup) {
                PEffectGroup->SetOpacity(0.0f);
            }

            if (PRootVisual && PTrackingVisual) {
                PRootVisual->RemoveAllVisuals();
                PRootVisual->AddVisual(PTrackingVisual, TRUE, nullptr);
            }

        } else {
            if (!GetPooledHostWindow(HWnd, AnimType, &RcHost, HwndHost, PTarget, PRootVisual)) { cleanup(); SignalEarlyReveal(HWnd); return; }

            int Width = RcFrame.right - RcFrame.left; int Height = RcFrame.bottom - RcFrame.top;
            if (Width <= 0 || Height <= 0) { cleanup(); SignalEarlyReveal(HWnd); return; }

            bool isDrag = (AnimType == ANIM_TYPE_DRAG);
            int PaddedWidth = Width + Overscan.Left + Overscan.Right; int PaddedHeight = Height + Overscan.Top + Overscan.Bottom;
            DWM_THUMBNAIL_PROPERTIES Thumb = { 0 };
            Thumb.dwFlags = DWM_TNP_VISIBLE | DWM_TNP_RECTDESTINATION | DWM_TNP_RECTSOURCE | DWM_TNP_OPACITY | DWM_TNP_ENABLE3D;
            Thumb.opacity = 255; Thumb.fVisible = TRUE;
            Thumb.rcDestination = { 0, 0, PaddedWidth, PaddedHeight };
            Thumb.rcSource = { -Overscan.Left, -Overscan.Top, Width + Overscan.Right, Height + Overscan.Bottom };

            VOID* PAPIContext = GPDCompDesktopDevice ? (VOID*)GPDCompDesktopDevice : (VOID*)GPDCompDevice;
            if (PAPIContext) PDwmpCreateSharedThumbnailVisual(HwndHost, HWnd, 2, &Thumb, PAPIContext, (void**)&PAnimVisual, &HThumbnail);

            if (!PAnimVisual) { cleanup(); SignalEarlyReveal(HWnd); return; }
            if (PDwmUpdateThumbnailProperties && HThumbnail) PDwmUpdateThumbnailProperties(HThumbnail, &Thumb);

            bool WantsBlur = false;
            if (AnimType == ANIM_TYPE_OPEN) WantsBlur = Settings.open_blur > 0.0f; else if (AnimType == ANIM_TYPE_CLOSE) WantsBlur = Settings.close_blur > 0.0f;
            else if (AnimType == ANIM_TYPE_MINIMIZE) WantsBlur = Settings.min_blur > 0.0f; else if (AnimType == ANIM_TYPE_RESTORE) WantsBlur = Settings.res_blur > 0.0f;

            if (WantsBlur && GPDCompDevice3) {
                if (FAILED(GPDCompDevice->CreateVisual(&PBlurVisual)) || FAILED(GPDCompDevice3->CreateGaussianBlurEffect(&PBlurEffect))) {
                    if (PBlurVisual) { PBlurVisual->Release(); PBlurVisual = nullptr; }
                    if (PBlurEffect) { PBlurEffect->Release(); PBlurEffect = nullptr; }
                }
            }

            if (FAILED(GPDCompDevice->CreateVisual(&PTrackingVisual)) || FAILED(GPDCompDevice->CreateEffectGroup(&PTrackingEffectGroup)) ||
                FAILED(GPDCompDevice->CreateMatrixTransform3D(&PTrackingTransform)) || FAILED(GPDCompDevice->CreateEffectGroup(&PEffectGroup)) ||
                FAILED(GPDCompDevice->CreateMatrixTransform3D(&PTransform))) { cleanup(); SignalEarlyReveal(HWnd); return; }

            SetTrackingVisualRect(PTrackingVisual, PTrackingTransform, RcHost, RcFrame, RcFrame, Overscan);
            PTrackingEffectGroup->SetTransform3D(PTrackingTransform); PTrackingVisual->SetEffect(PTrackingEffectGroup);

            ANIM_TRANSFORM_PARAMS InitParams;
            ComputeTransformParams(&InitParams, AnimType, 0.0f, 0.0f, RcFrame, RcTaskbar, Overscan, Settings);
            if (isDrag) {
                InitParams.Pitch = 0.0f; InitParams.Yaw = 0.0f; InitParams.Roll = 0.0f;
                InitParams.XTrans = 0.0f; InitParams.YTrans = 0.0f; InitParams.ZTrans = 0.0f;
                InitParams.ScaleX = 1.0f; InitParams.ScaleY = 1.0f;
            }
            
            float InitH = FastMax((float)(RcFrame.bottom - RcFrame.top), 1.0f);
            InitParams.ScaleX = FastMax(InitParams.ScaleX, 0.001f);
            InitParams.ScaleY = FastMax(InitParams.ScaleY, 0.001f);
            InitParams.Opacity = FastMax(0.0f, FastMin(1.0f, InitParams.Opacity));
            InitParams.Blur = FastMax(0.0f, InitParams.Blur);
            InitParams.ZTrans = FastMax(InitParams.ZTrans, -(InitH * 0.8f) + 1.0f);

            D2DMatrix InitMat; BuildMatrixFromParams(&InitMat, InitParams, AnimType, FastMax((float)(RcFrame.right - RcFrame.left), 1.0f), InitH, Overscan, Settings.preset);
            float InitOpacity = InitParams.Opacity; float InitBlur = InitParams.Blur;
            D3DMATRIX InitBase = {}; memcpy(&InitBase, &InitMat, sizeof(InitBase));
            PTransform->SetMatrix(InitBase); PEffectGroup->SetOpacity(isDrag ? 0.0f : InitOpacity);
            if (PBlurEffect) PBlurEffect->SetStandardDeviation(FastMax(InitBlur, 0.001f));

            PEffectGroup->SetTransform3D(PTransform); 
            if (WantsBlur && PBlurVisual && PBlurEffect) {
                PBlurVisual->SetEffect(PEffectGroup); PAnimVisual->SetEffect(PBlurEffect);
                PTrackingVisual->AddVisual(PBlurVisual, TRUE, nullptr); PBlurVisual->AddVisual(PAnimVisual, TRUE, nullptr);
            } else {
                PAnimVisual->SetEffect(PEffectGroup); PTrackingVisual->AddVisual(PAnimVisual, TRUE, nullptr);
            }

            // Original window remains visible during drag unless naturally cloaked.
            // We use a native animation spoofing trick to force DWM to natively hide the real window.

            PRootVisual->AddVisual(PTrackingVisual, TRUE, nullptr);
        }
        
        if (AnimType == ANIM_TYPE_OPEN || AnimType == ANIM_TYPE_RESTORE) {
            if (!teardown) {
                teardown = std::make_shared<FAST_TEARDOWN>();
                teardown->PRootVisual = PRootVisual;
                PRootVisual->AddRef();
                teardown->Signaled = false;
                {
                    AcquireSRWLockExclusive(&GTeardownLock);
                    GFastTeardownMap[HWnd] = teardown;
                    ReleaseSRWLockExclusive(&GTeardownLock);
                }
            }
        } else {
            if (teardown) {
                ClearFastTeardown(HWnd);
                teardown.reset();
            }
        }

        if (!BuildAnimation(PTransform, PEffectGroup, PBlurEffect, AnimType, MasterDuration, RcFrame, RcTaskbar, Overscan, AnimRefs, IsInterruption, OldParams, Settings)) {
            cleanup(); 
            SignalEarlyReveal(HWnd);
            return; 
        }

        bool needsFlush = false;
        if (IsSafeToDComp()) {
            GPDCompDevice->Commit();
            needsFlush = true;
        }

        NowSec = QueryTimeSeconds();

        ACTIVE_ANIM Anim(
            HwndHost, PTarget, PRootVisual, RcHost, PTrackingVisual, PTrackingEffectGroup, PBlurVisual, PBlurEffect, PAnimVisual, PEffectGroup, PTransform, PTrackingTransform, HThumbnail,
            NowSec + MsToSeconds(MasterDuration), NowSec + MsToSeconds(MasterDuration + GetFailSafeMs(AnimType)), MasterDuration, AnimType, HWnd, RcFrame, RcFrame, RcTaskbar, Overscan,
            FastMax((float)(RcFrame.right - RcFrame.left), 1.0f), FastMax((float)(RcFrame.bottom - RcFrame.top), 1.0f), std::move(AnimRefs), PWindowData, teardown, NowSec,
            ExistingAnim.CurrentPitch, ExistingAnim.CurrentYaw, ExistingAnim.CurrentRoll, ExistingAnim.TargetPitch, ExistingAnim.TargetYaw, ExistingAnim.TargetRoll, ExistingAnim.JigglePosX, ExistingAnim.JiggleVelX, ExistingAnim.JiggleTargetX, ExistingAnim.JigglePosY, ExistingAnim.JiggleVelY, ExistingAnim.JiggleTargetY, ExistingAnim.LastCursorPos, ExistingAnim.LastCursorTime, false,
            true, false, 0.0, false, false, 0.0, false
        );

        dcompLock.unlock();
        if (needsFlush) DwmFlush();

        {
            std::lock_guard<std::mutex> lock(GAnimationsMutex);
            GAnimations.push_back(std::move(Anim));
            GActiveAnimCount.fetch_add(1, std::memory_order_relaxed);
            if (GAnimations.size() == 1) {
                StartAnimationTimer(GHwndAnimController);
            }
        }
    }
}

namespace CDesktopManager {
    static bool GIsDCompInitialized = false;
    bool InitializeDComp();
    void EnsureDCompInitialized() {
        if (GIsDCompInitialized) return;
        InitializeDComp(); UpdateMetricsCache();
        std::unique_lock<std::recursive_mutex> dcompLock(GDCompTreeMutex);
        std::lock_guard<std::mutex> lock(GHostPoolMutex);
        for (int i = 0; i < MAX_HOST_POOL; ++i) {
            DWORD ExStyle = WS_EX_NOREDIRECTIONBITMAP | WS_EX_TOOLWINDOW | WS_EX_TRANSPARENT | WS_EX_LAYERED | WS_EX_NOACTIVATE;
            HWND h = CreateWindowExW(ExStyle, L"AnimationHostClass", NULL, WS_POPUP, -20000, -20000, 1, 1, NULL, NULL, GHinst, NULL);
            ShowWindow(h, SW_SHOWNOACTIVATE);
            IDCompositionTarget* target = nullptr;
            IDCompositionVisual* root = nullptr;
            if (GPDCompDevice && SUCCEEDED(GPDCompDevice->CreateTargetForHwnd(h, TRUE, &target)) && SUCCEEDED(GPDCompDevice->CreateVisual(&root))) {
                target->SetRoot(root);
                GHostPool[i] = { h, target, root, false };
            } else {
                if (target) target->Release();
                DestroyWindow(h);
            }
        }
        GIsDCompInitialized = true;
    }

static HMODULE GDcompModule = NULL;

    bool InitializeDComp() {
        if (GPDCompDevice) return true;
        HRESULT Hr = D3D11CreateDevice(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, D3D11_CREATE_DEVICE_BGRA_SUPPORT, nullptr, 0, D3D11_SDK_VERSION, &GPD3DDevice, nullptr, &GPD3DContext);
        if (FAILED(Hr)) return false;

        IDXGIDevice* PDXGIDevice = nullptr; GPD3DDevice->QueryInterface(__uuidof(IDXGIDevice), (void**)&PDXGIDevice);
        
        if (!GDcompModule) GDcompModule = LoadLibraryW(L"dcomp.dll");
        if (GDcompModule) {
            auto PDCompCreate3 = (HRESULT(WINAPI*)(IUnknown*, REFIID, void**))GetProcAddress(GDcompModule, "DCompositionCreateDevice3");
            if (PDCompCreate3) {
                static const GUID IID_DesktopDevice = { 0x5f4633fe, 0x1e08, 0x4cb8, { 0x8c, 0x75, 0xce, 0x24, 0x33, 0x3f, 0x56, 0x02 } };
                Hr = PDCompCreate3((IUnknown*)PDXGIDevice, IID_DesktopDevice, (void**)&GPDCompDesktopDevice);
                if (SUCCEEDED(Hr) && GPDCompDesktopDevice) {
                    Hr = GPDCompDesktopDevice->QueryInterface(__uuidof(IDCompositionDevice), (void**)&GPDCompDevice);
                    GPDCompDesktopDevice->QueryInterface(__uuidof(IDCompositionDevice3), (void**)&GPDCompDevice3);
                }
            }
        }

        if (!GPDCompDevice) {
            if (PDXGIDevice) {
                Hr = DCompositionCreateDevice(PDXGIDevice, __uuidof(IDCompositionDevice), (void**)&GPDCompDevice);
            }
        }
        
        if (SUCCEEDED(Hr) && GPDCompDevice) {
            std::unique_lock<std::recursive_mutex> dcompLock(GDCompTreeMutex);
            if (!GCommitHooked) {
                void** vtable = *(void***)GPDCompDevice;
                Wh_SetFunctionHook(vtable[3], (void*)HookedDCompCommit, (void**)&OrigDCompCommit);
                GCommitHooked = true;
            }
        }

        if (PDXGIDevice) PDXGIDevice->Release();
        return SUCCEEDED(Hr) && GPDCompDevice;
    }
    
    RECT GetRefinedTaskbarRect(HWND hwndOriginal, RECT approxRect, bool enableCursorTrack) {
        int w = approxRect.right - approxRect.left;
        int maxW = GetSystemMetrics(SM_CXVIRTUALSCREEN);
        if (maxW <= 0) maxW = GetSystemMetrics(SM_CXSCREEN);
        if (w <= 0 || approxRect.left <= -20000 || w > maxW) { 
            w = 160; 
            if (approxRect.left > -20000 && approxRect.right > -20000) {
                int cx = approxRect.left + (approxRect.right - approxRect.left) / 2;
                approxRect.left = cx - w / 2;
                approxRect.right = cx + w / 2;
            } else {
                int sw = GetSystemMetrics(SM_CXSCREEN);
                approxRect.left = sw / 2 - w / 2; 
                approxRect.right = sw / 2 + w / 2; 
            }
        }
        
        if (!enableCursorTrack) return approxRect;
        
        POINT pt;
        if (GetCursorPos(&pt)) {
            HWND hTray = FindWindowW(L"Shell_TrayWnd", NULL);
            if (hTray) {
                RECT trayRect;
                if (GetWindowRect(hTray, &trayRect)) {
                    if (PtInRect(&trayRect, pt)) {
                        approxRect.left = pt.x - w / 2;
                        approxRect.right = pt.x + w / 2;
                        approxRect.top = trayRect.top;
                        approxRect.bottom = trayRect.bottom;
                    }
                }
            }
        }
        return approxRect;
    }

    LRESULT CALLBACK DesktopWindowProc(HWND Hwnd, UINT UMsg, WPARAM WParam, LPARAM LParam) {
        if (UMsg == WM_NCHITTEST) return HTTRANSPARENT;
        if (UMsg == WM_CLOSE) { if (g_ModUnloading.load()) DestroyWindow(Hwnd); return 0; }
        if (UMsg == WM_DESTROY) { PostQuitMessage(0); return 0; }

        if (UMsg == GUMsgInstantTeardown && UMsg != 0) {
            HWND HwndTarget = (HWND)LParam;
            bool isInterrupted = false;
            MSG peekMsg;
            if (PeekMessageW(&peekMsg, Hwnd, GUMsgAnimateWindow, GUMsgAnimateWindow, PM_NOREMOVE)) {
                ANIM_PARAMS* p = (ANIM_PARAMS*)peekMsg.lParam;
                if (p && p->HwndOriginal == HwndTarget) isInterrupted = true;
            }
            if (!isInterrupted) {
                std::lock_guard<std::mutex> lock(GPendingMutex);
                for (auto* p : GPendingAnimations) {
                    if (p->HwndOriginal == HwndTarget) { isInterrupted = true; break; }
                }
            }

            if (!isInterrupted) {
                std::shared_ptr<FAST_TEARDOWN> targetTeardown;
                {
                    AcquireSRWLockShared(&GTeardownLock);
                    auto it = GFastTeardownMap.find(HwndTarget);
                    if (it != GFastTeardownMap.end()) targetTeardown = it->second;
                    ReleaseSRWLockShared(&GTeardownLock);
                }
                if (targetTeardown && targetTeardown->PRootVisual && targetTeardown->Signaled.load()) {
                    std::unique_lock<std::recursive_mutex> dcompLock(GDCompTreeMutex);
                    targetTeardown->PRootVisual->RemoveAllVisuals();
                    if (GPDCompDevice && IsSafeToDComp()) GPDCompDevice->Commit();
                }
            }
            return 0;
        }

        if (UMsg == GUMsgAnimateWindow && UMsg != 0) {
            EnsureDCompInitialized();
            ANIM_PARAMS* PParams = (ANIM_PARAMS*)LParam;

            if (PParams->HwndOriginal && IsWindow(PParams->HwndOriginal)) {
                if (PParams->AnimType == ANIM_TYPE_OPEN || PParams->AnimType == ANIM_TYPE_RESTORE) {
                    RECT RealRect;
                    bool gotRect = GetWindowRect(PParams->HwndOriginal, &RealRect) &&
                                   RealRect.left > -20000 && RealRect.top > -20000;

                    if (!gotRect && PParams->AnimType == ANIM_TYPE_RESTORE) {
                        WINDOWPLACEMENT wp = {}; wp.length = sizeof(wp);
                        if (GetWindowPlacement(PParams->HwndOriginal, &wp) &&
                            wp.rcNormalPosition.right - wp.rcNormalPosition.left > 0 &&
                            wp.rcNormalPosition.bottom - wp.rcNormalPosition.top > 0) {
                            RealRect = wp.rcNormalPosition;
                            gotRect = true;
                        }
                    }

                    if (gotRect) PParams->RcFrame = RealRect;
                }
            }
            PParams->Overscan = ComputeOverscan(PParams->RcFrame);

            if (PParams->RcFrame.left <= -20000 || PParams->RcFrame.top <= -20000 || (PParams->RcFrame.right - PParams->RcFrame.left) <= 0 || (PParams->RcFrame.bottom - PParams->RcFrame.top) <= 0) {
                delete PParams; return 0;
            }
            
            if (PParams->AnimType == ANIM_TYPE_MINIMIZE || PParams->AnimType == ANIM_TYPE_RESTORE) {
                bool doTrack = false;
                MOD_SETTINGS currentSettings = GetSafeSettings();
                if (currentSettings.preset != 1) {
                    if (PParams->AnimType == ANIM_TYPE_MINIMIZE) doTrack = currentSettings.min_track_taskbar;
                    if (PParams->AnimType == ANIM_TYPE_RESTORE) doTrack = currentSettings.res_track_taskbar;
                    PParams->RcTaskbar = GetRefinedTaskbarRect(PParams->HwndOriginal, PParams->RcTaskbar, doTrack);
                }
            }
            
            bool isInterruption = false;
            {
                std::lock_guard<std::mutex> lock(GAnimationsMutex);
                for (const auto& anim : GAnimations) {
                    if (anim.HwndOriginal == PParams->HwndOriginal) { isInterruption = true; break; }
                }
            }

            if (PParams->AnimType == ANIM_TYPE_CLOSE || PParams->AnimType == ANIM_TYPE_MINIMIZE || PParams->AnimType == ANIM_TYPE_RESTORE || PParams->AnimType == ANIM_TYPE_DRAG || isInterruption) {
                CTopLevelWindow4D::UpdateScene3D(PParams);
                delete PParams;
            } else {
                std::lock_guard<std::mutex> lock(GPendingMutex);
                for (size_t i = 0; i < GPendingAnimations.size(); ) {
                    if (GPendingAnimations[i]->HwndOriginal == PParams->HwndOriginal) {
                        delete GPendingAnimations[i];
                        GPendingAnimations[i] = GPendingAnimations.back();
                        GPendingAnimations.pop_back();
                    } else {
                        ++i;
                    }
                }
                GPendingAnimations.push_back(PParams);
                SetTimer(Hwnd, 2, 16, NULL);
            }
            return 0;
        }

        if (UMsg == WM_TIMER && WParam == 2) {
            double NowSec = QueryTimeSeconds();
            std::vector<ANIM_PARAMS*> ReadyAnims;
            {
                std::lock_guard<std::mutex> lock(GPendingMutex);
                for (size_t i = 0; i < GPendingAnimations.size(); ) {
                    auto* PParams = GPendingAnimations[i];
                    bool isReady = true;
                    if (PParams->AnimType == ANIM_TYPE_RESTORE || PParams->AnimType == ANIM_TYPE_OPEN) {
                        isReady = IsWindowReadyForReveal(PParams->PWindowData, PParams->AnimType) || (NowSec - PParams->CreationTimeSec >= 0.500);
                    }
                    if (isReady && NowSec - PParams->CreationTimeSec >= 0.050) {
                        ReadyAnims.push_back(PParams);
                        GPendingAnimations[i] = GPendingAnimations.back();
                        GPendingAnimations.pop_back();
                    } else { ++i; }
                }
                if (GPendingAnimations.empty()) KillTimer(Hwnd, 2);
            }
            for (auto* PParams : ReadyAnims) {
                CTopLevelWindow4D::UpdateScene3D(PParams);
                delete PParams;
            }
            return 0;
        }

        if (UMsg == WM_DISPLAYCHANGE || UMsg == WM_SETTINGCHANGE || UMsg == 0x02E0 /* WM_DPICHANGED */) {
            UpdateMetricsCache(); UpdateRefreshRateCache(); bool NeedsCommit = false;
            std::vector<DEFERRED_WINPOS_UPDATE> WinUpdates;
            
            { 
                std::lock_guard<std::mutex> lock(GAnimationsMutex);
                std::unique_lock<std::recursive_mutex> dcompLock(GDCompTreeMutex);
                for (auto& Anim : GAnimations) {
                    if (Anim.AnimType != ANIM_TYPE_MINIMIZE) PositionAnimationHostWindow(Anim.HwndHost, Anim.HwndOriginal, Anim.AnimType, &Anim.HostRect, &WinUpdates);
                    CTopLevelWindow4D::SetTrackingVisualRect(Anim.PTrackingVisual, Anim.PTrackingTransform, Anim.HostRect, Anim.InitialRcFrame, Anim.LastRcFrame, Anim.Overscan);
                    NeedsCommit = true;
                }
            } 
            
            for (const auto& wu : WinUpdates) {
                SetWindowPos(wu.hwnd, wu.hwndInsertAfter, wu.x, wu.y, wu.cx, wu.cy, wu.flags);
            }
            if (NeedsCommit && GPDCompDevice && IsSafeToDComp()) {
                std::unique_lock<std::recursive_mutex> dcompLock(GDCompTreeMutex);
                GPDCompDevice->Commit();
            }
            return 0;
        }

        if (UMsg == GUMsgAnimTick && UMsg != 0) {
            double NowSec = QueryTimeSeconds(); 
            bool NeedsCommit = false;
            bool IsEmpty = false;
            bool DragHandoffFlush = false;
            std::vector<std::pair<HWND, bool>> DragHandoffOps;

            std::vector<ACTIVE_ANIM> ToDestroy;
            std::vector<DEFERRED_THUMB_UPDATE> ThumbUpdates;
            std::vector<DEFERRED_WINPOS_UPDATE> WinUpdates;

            { 
                std::lock_guard<std::mutex> lock(GAnimationsMutex);
                std::unique_lock<std::recursive_mutex> dcompLock(GDCompTreeMutex);

                for (size_t i = 0; i < GAnimations.size(); ) {
                    auto& Anim = GAnimations[i];

                    if (CTopLevelWindow4D::ShouldTrackLiveWindowRect(Anim.AnimType)) {
                        RECT RcNow = Anim.LastRcFrame;
                        if (GetWindowRect(Anim.HwndOriginal, &RcNow) && !EqualRect(&RcNow, &Anim.LastRcFrame)) {
                            bool SizeChanged = (RcNow.right - RcNow.left) != (Anim.LastRcFrame.right - Anim.LastRcFrame.left) || 
                                               (RcNow.bottom - RcNow.top) != (Anim.LastRcFrame.bottom - Anim.LastRcFrame.top);
                            Anim.LastRcFrame = RcNow;
                            
                            PositionAnimationHostWindow(Anim.HwndHost, Anim.HwndOriginal, Anim.AnimType, &Anim.HostRect, &WinUpdates);
                            CTopLevelWindow4D::SetTrackingVisualRect(Anim.PTrackingVisual, Anim.PTrackingTransform, Anim.HostRect, Anim.InitialRcFrame, RcNow, Anim.Overscan);

                            if (SizeChanged && PDwmUpdateThumbnailProperties) {
                                int Width = FastMax((int)(RcNow.right - RcNow.left), 1);
                                int Height = FastMax((int)(RcNow.bottom - RcNow.top), 1);
                                int PaddedWidth = Width + Anim.Overscan.Left + Anim.Overscan.Right;
                                int PaddedHeight = Height + Anim.Overscan.Top + Anim.Overscan.Bottom;

                                DWM_THUMBNAIL_PROPERTIES Thumb = { 0 };
                                Thumb.dwFlags = DWM_TNP_VISIBLE | DWM_TNP_RECTSOURCE | DWM_TNP_RECTDESTINATION | DWM_TNP_OPACITY | DWM_TNP_ENABLE3D;
                                Thumb.opacity = 255; Thumb.fVisible = TRUE;
                                Thumb.rcDestination = { 0, 0, PaddedWidth, PaddedHeight };
                                Thumb.rcSource = { -Anim.Overscan.Left, -Anim.Overscan.Top, Width + Anim.Overscan.Right, Height + Anim.Overscan.Bottom };
                                ThumbUpdates.push_back({ Anim.HThumbnail, Thumb });
                            }
                            NeedsCommit = true;
                        }
                    } else if (Anim.AnimType == ANIM_TYPE_CLOSE) {
                        WinUpdates.push_back({ Anim.HwndHost, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE });
                    }

                    if (Anim.AnimType == ANIM_TYPE_DRAG || Anim.AnimType == ANIM_TYPE_DRAG_END) {
                        POINT curPt; GetCursorPos(&curPt);
                        double dt = NowSec - Anim.LastCursorTime;
                        if (dt <= 0.0) dt = 0.016;

                        if (Anim.AnimType == ANIM_TYPE_DRAG) {
                            Anim.EndTimeSec = NowSec + 10.0;
                            if (!Anim.DragOverlayRevealed && !Anim.CloakRequested) {
                                if (NowSec - Anim.CreationTimeSec >= 0.016) {
                                    if (Anim.PEffectGroup) {
                                        Anim.PEffectGroup->SetOpacity(1.0f);
                                    }
                                    Anim.DragOverlayRevealed = true;
                                    Anim.CloakRequested = true;
                                    Anim.CloakRequestTimeSec = NowSec;
                                    DragHandoffOps.push_back({ Anim.HwndOriginal, true });
                                    NeedsCommit = true;
                                    DragHandoffFlush = true;
                                }
                            }
                            if (Anim.CloakRequested && !Anim.WindowCloaked && !Anim.DragFailed) {
                                BOOL cloaked = FALSE;
                                if (QueryWindowCloaked(Anim.HwndOriginal, &cloaked)) {
                                    if (cloaked) {
                                        Anim.WindowCloaked = true;
                                    } else if (NowSec - Anim.CloakRequestTimeSec >= 0.150) {
                                        Anim.DragFailed = true;
                                        Anim.EndTimeSec = NowSec - 1.0;
                                        MarkDragFailure(Anim.HwndOriginal);
                                        RequestWindowCloak(Anim.HwndOriginal, false);
                                    }
                                }
                            }
                            bool CanApplyDragTransform = Anim.DragOverlayRevealed && (Anim.WindowCloaked || (NowSec - Anim.CloakRequestTimeSec >= 0.016));
                            if ((GetAsyncKeyState(VK_LBUTTON) & 0x8000) == 0) {
                                Anim.AnimType = ANIM_TYPE_DRAG_END;
                                Anim.EndTimeSec = NowSec + 3.0; 
                            } else if (CanApplyDragTransform && Anim.LastCursorTime > 0.0 && dt < 0.1) {
                                double vx = (curPt.x - Anim.LastCursorPos.x) / dt;
                                double vy = (curPt.y - Anim.LastCursorPos.y) / dt;

                                if (g_cached_enable_drag.load(std::memory_order_relaxed)) {
                                    float drag_intensity = g_cached_drag_intensity.load(std::memory_order_relaxed);
                                    double intensity = drag_intensity * 0.005; 
                                    Anim.TargetPitch = -vy * intensity;
                                    Anim.TargetYaw = vx * intensity;
                                    Anim.TargetPitch = FastMax(-45.0, FastMin(45.0, Anim.TargetPitch));
                                    Anim.TargetYaw = FastMax(-45.0, FastMin(45.0, Anim.TargetYaw));
                                } else {
                                    Anim.TargetPitch = 0.0;
                                    Anim.TargetYaw = 0.0;
                                }

                                if (g_cached_enable_drag_roll.load(std::memory_order_relaxed)) {
                                    float roll_intensity = g_cached_drag_roll_intensity.load(std::memory_order_relaxed);
                                    double intensityRoll = roll_intensity * 0.005;
                                    Anim.TargetRoll = vx * intensityRoll;
                                    Anim.TargetRoll = FastMax(-45.0, FastMin(45.0, Anim.TargetRoll));
                                } else {
                                    Anim.TargetRoll = 0.0;
                                }

                                if (g_cached_enable_drag_jiggle.load(std::memory_order_relaxed)) {
                                    float jiggle_intensity = g_cached_jiggle_intensity.load(std::memory_order_relaxed);
                                    float sign = g_cached_invert_jiggle.load(std::memory_order_relaxed) ? -1.0f : 1.0f;
                                    double speedX = fabs(vx);
                                    double speedY = fabs(vy);
                                    double targetX = sign * ((speedX * 0.00015) - (speedY * 0.000075)) * jiggle_intensity;
                                    double targetY = sign * ((speedY * 0.00015) - (speedX * 0.000075)) * jiggle_intensity;
                                    Anim.JiggleTargetX = FastMax(-0.3, FastMin(0.5, targetX));
                                    Anim.JiggleTargetY = FastMax(-0.3, FastMin(0.5, targetY));
                                } else {
                                    Anim.JiggleTargetX = 0.0;
                                    Anim.JiggleTargetY = 0.0;
                                }
                            }
                            Anim.LastCursorPos = curPt;
                            Anim.LastCursorTime = NowSec;
                        } else {
                            // ANIM_TYPE_DRAG_END decay mode
                            if ((GetAsyncKeyState(VK_LBUTTON) & 0x8000) != 0) {
                                // Resume active drag seamlessly in-place
                                Anim.AnimType = ANIM_TYPE_DRAG;
                                Anim.EndTimeSec = NowSec + 10.0;
                            } else {
                                Anim.TargetPitch = 0.0;
                                Anim.TargetYaw = 0.0;
                                Anim.TargetRoll = 0.0;
                                Anim.JiggleTargetX = 0.0;
                                Anim.JiggleTargetY = 0.0;
                                // EndTimeSec was set once at DRAG→DRAG_END transition (NowSec + 3.0).
                                // Do NOT refresh it here — that would prevent TimeDone from ever
                                // becoming true, causing the animation to run forever if the
                                // underdamped jiggle spring never meets the settle thresholds.
                            }
                        }

                        if (g_cached_enable_drag_jiggle.load(std::memory_order_relaxed)) {
                            float jiggle_stiffness = FastMax(1.0f, g_cached_jiggle_stiffness.load(std::memory_order_relaxed));
                            float jiggle_damping = FastMax(0.1f, g_cached_jiggle_damping.load(std::memory_order_relaxed));
                            float jiggle_mass = FastMax(0.01f, g_cached_jiggle_mass.load(std::memory_order_relaxed));

                            double subDt = FastMin(dt, 0.033);

                            double forceX = -jiggle_stiffness * (Anim.JigglePosX - Anim.JiggleTargetX) - jiggle_damping * Anim.JiggleVelX;
                            double accelX = forceX / jiggle_mass;
                            Anim.JiggleVelX += accelX * subDt;
                            Anim.JigglePosX += Anim.JiggleVelX * subDt;

                            double forceY = -jiggle_stiffness * (Anim.JigglePosY - Anim.JiggleTargetY) - jiggle_damping * Anim.JiggleVelY;
                            double accelY = forceY / jiggle_mass;
                            Anim.JiggleVelY += accelY * subDt;
                            Anim.JigglePosY += Anim.JiggleVelY * subDt;
                        } else {
                            Anim.JigglePosX = 0.0; Anim.JiggleVelX = 0.0; Anim.JiggleTargetX = 0.0;
                            Anim.JigglePosY = 0.0; Anim.JiggleVelY = 0.0; Anim.JiggleTargetY = 0.0;
                        }

                        if (Anim.AnimType == ANIM_TYPE_DRAG_END) {
                            // Guarantee minimum 150ms release decay time for natural visual smoothness
                            if (NowSec - Anim.LastCursorTime >= 0.150) {
                                bool pitchSettled = fabs(Anim.CurrentPitch) < 0.05 && fabs(Anim.TargetPitch) < 0.05;
                                bool yawSettled = fabs(Anim.CurrentYaw) < 0.05 && fabs(Anim.TargetYaw) < 0.05;
                                bool rollSettled = fabs(Anim.CurrentRoll) < 0.05 && fabs(Anim.TargetRoll) < 0.05;
                                bool jiggleSettled = fabs(Anim.JigglePosX) < 0.0005 && fabs(Anim.JiggleVelX) < 0.001 &&
                                                     fabs(Anim.JigglePosY) < 0.0005 && fabs(Anim.JiggleVelY) < 0.001;

                                if (pitchSettled && yawSettled && rollSettled && jiggleSettled) {
                                    Anim.EndTimeSec = NowSec - 1.0; // Clean natural completion
                                }
                            }
                        }

                        float drag_smoothing = g_cached_drag_smoothing.load(std::memory_order_relaxed);
                        double smoothing = drag_smoothing;
                        if (smoothing <= 0.0) smoothing = 1.0;
                        double lerpFactor = 1.0 - exp(-smoothing * dt);
                        Anim.CurrentPitch += (Anim.TargetPitch - Anim.CurrentPitch) * lerpFactor;
                        Anim.CurrentYaw += (Anim.TargetYaw - Anim.CurrentYaw) * lerpFactor;
                        Anim.CurrentRoll += (Anim.TargetRoll - Anim.CurrentRoll) * lerpFactor;

                        if (Anim.PTransform) {
                            float W = FastMax((float)(Anim.LastRcFrame.right - Anim.LastRcFrame.left), 1.0f);
                            float H = FastMax((float)(Anim.LastRcFrame.bottom - Anim.LastRcFrame.top), 1.0f);
                            float cx = W * 0.5f + Anim.Overscan.Left;
                            float cy = H * 0.5f + Anim.Overscan.Top;
                            if (g_cached_drag_pivot_mode.load(std::memory_order_relaxed) == 1) {
                                cx = (float)(Anim.LastCursorPos.x - Anim.LastRcFrame.left) + Anim.Overscan.Left;
                                cy = (float)(Anim.LastCursorPos.y - Anim.LastRcFrame.top) + Anim.Overscan.Top;
                                cx = FastMax((float)Anim.Overscan.Left, FastMin(cx, W + Anim.Overscan.Left));
                                cy = FastMax((float)Anim.Overscan.Top, FastMin(cy, H + Anim.Overscan.Top));
                            }
                            CTopLevelWindow4D::ANIM_TRANSFORM_PARAMS PtParams = {};
                            PtParams.Pitch = (float)Anim.CurrentPitch;
                            PtParams.Yaw = (float)Anim.CurrentYaw;
                            PtParams.Roll = (float)Anim.CurrentRoll;
                            PtParams.ScaleX = FastMax(0.5f, FastMin(1.5f, 1.0f + (float)Anim.JigglePosX));
                            PtParams.ScaleY = FastMax(0.5f, FastMin(1.5f, 1.0f + (float)Anim.JigglePosY));
                            PtParams.Opacity = 1.0f;
                            PtParams.CurCenterX = cx;
                            PtParams.CurCenterY = cy;
                            D2DMatrix Mat;
                            CTopLevelWindow4D::BuildMatrixFromParams(&Mat, PtParams, Anim.AnimType, W, H, Anim.Overscan);
                            D3DMATRIX BaseMat; memcpy(&BaseMat, &Mat, sizeof(BaseMat));
                            Anim.PTransform->SetMatrix(BaseMat);
                            Anim.PEffectGroup->SetTransform3D(Anim.PTransform);
                            Anim.PVisual->SetEffect(Anim.PEffectGroup);
                        }
                        NeedsCommit = true;
                    }

                    bool TimeDone = NowSec >= Anim.EndTimeSec;
                    bool DragCloakActive = Anim.WindowCloaked || Anim.CloakRequested;
                    
                    if (TimeDone && DragCloakActive && !Anim.PendingUncloak && (Anim.AnimType == ANIM_TYPE_DRAG || Anim.AnimType == ANIM_TYPE_DRAG_END)) {
                        Anim.PendingUncloak = true;
                        Anim.UncloakStartTimeSec = NowSec;
                        if (Anim.PEffectGroup) {
                            Anim.PEffectGroup->SetOpacity(0.0f);
                        }
                        DragHandoffOps.push_back({ Anim.HwndOriginal, false });
                        NeedsCommit = true;
                        DragHandoffFlush = true;
                        TimeDone = false; 
                    }

                    if (Anim.PendingUncloak) {
                        if (NowSec - Anim.UncloakStartTimeSec >= 0.016) {
                            BOOL cloaked = TRUE;
                            bool queryOk = QueryWindowCloaked(Anim.HwndOriginal, &cloaked);
                            if (queryOk && !cloaked) {
                                TimeDone = true;
                            } else if (NowSec - Anim.UncloakStartTimeSec >= 0.100 /* DRAG_UNCLOAK_CONFIRM_TIMEOUT_SEC */) {
                                TimeDone = true;
                            } else {
                                TimeDone = false;
                            }
                        } else {
                            TimeDone = false;
                        }
                    }

                    if (TimeDone && (Anim.AnimType == ANIM_TYPE_MINIMIZE || Anim.AnimType == ANIM_TYPE_CLOSE)) {
                        bool HasPendingRestore = false;
                        {
                            std::lock_guard<std::mutex> lockPending(GPendingMutex);
                            for (auto* pending : GPendingAnimations) {
                                if (pending->HwndOriginal == Anim.HwndOriginal && (pending->AnimType == ANIM_TYPE_RESTORE || pending->AnimType == ANIM_TYPE_OPEN)) {
                                    HasPendingRestore = true;
                                    break;
                                }
                            }
                        }
                        if (HasPendingRestore) TimeDone = false;
                    }

                    bool RevealReady = (Anim.AnimType == ANIM_TYPE_OPEN || Anim.AnimType == ANIM_TYPE_RESTORE) ? (IsWindowReadyForReveal(Anim.PWindowData, Anim.AnimType) || NowSec >= Anim.RevealWaitDeadlineSec) : true;
                    
                    bool TeardownSignaled = false;
                    if (Anim.TeardownPtr) TeardownSignaled = Anim.TeardownPtr->Signaled.load();

                    if ((TeardownSignaled && (TimeDone || Anim.AnimType == ANIM_TYPE_OPEN)) || (TimeDone && RevealReady)) {
                        ToDestroy.push_back(std::move(GAnimations[i])); 
                        if (i != GAnimations.size() - 1) {
                            GAnimations[i] = std::move(GAnimations.back());
                        }
                        GAnimations.pop_back(); 
                        GActiveAnimCount.fetch_sub(1, std::memory_order_relaxed);
                        NeedsCommit = true;
                    } else { 
                        ++i; 
                    }
                }
                IsEmpty = GAnimations.empty();
            } 
            
            for (const auto& wu : WinUpdates) {
                SetWindowPos(wu.hwnd, wu.hwndInsertAfter, wu.x, wu.y, wu.cx, wu.cy, wu.flags);
            }
            for (const auto& tu : ThumbUpdates) {
                PDwmUpdateThumbnailProperties(tu.h, &tu.props);
            }
            for (auto& deadAnim : ToDestroy) {
                if ((deadAnim.WindowCloaked || deadAnim.CloakRequested) && !deadAnim.PendingUncloak && deadAnim.HwndOriginal && IsWindow(deadAnim.HwndOriginal)) {
                    RequestWindowCloak(deadAnim.HwndOriginal, false);
                }
                if (deadAnim.AnimType == ANIM_TYPE_DRAG || deadAnim.AnimType == ANIM_TYPE_DRAG_END) {
                    SetWindowPos(deadAnim.HwndOriginal, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
                }
                CTopLevelWindow4D::ClearFastTeardown(deadAnim.HwndOriginal);
                CTopLevelWindow4D::ReleaseAnimationResources(deadAnim);
            }
            if (NeedsCommit && IsSafeToDComp() && GPDCompDevice) {
                std::unique_lock<std::recursive_mutex> dcompLock(GDCompTreeMutex);
                GPDCompDevice->Commit();
            }
            if (!DragHandoffOps.empty()) {
                for (const auto& op : DragHandoffOps) {
                    HWND hwnd = op.first;
                    bool cloak = op.second;
                    if (!RequestWindowCloakDirect(hwnd, cloak)) {
                        RequestWindowCloak(hwnd, cloak);
                    }
                }
                if (DragHandoffFlush) {
                    DwmFlush();
                }
            }
            if (IsEmpty) {
                StopAnimationTimer(Hwnd);
            }
            return 0;
        }
        return DefWindowProc(Hwnd, UMsg, WParam, LParam);
    }

    // Removed GHwndToTargetClass

    HWINEVENTHOOK GLocationChangeHook = NULL;

    void CALLBACK WinEventProc(HWINEVENTHOOK hWinEventHook, DWORD event, HWND hwnd, LONG idObject, LONG idChild, DWORD dwEventThread, DWORD dwmsEventTime) {
        if (idObject != OBJID_WINDOW || idChild != CHILDID_SELF) return;
        if (event == EVENT_OBJECT_LOCATIONCHANGE) {
            bool dragActive = g_cached_enable_drag.load(std::memory_order_relaxed) || 
                              g_cached_enable_drag_roll.load(std::memory_order_relaxed) ||
                              g_cached_enable_drag_jiggle.load(std::memory_order_relaxed);
            if (!dragActive) return;
            if ((GetAsyncKeyState(VK_LBUTTON) & 0x8000) == 0) return;
            if (!hwnd || !IsWindowVisible(hwnd)) return;

            WCHAR className[256] = {0};
            if (GetClassNameW(hwnd, className, 256)) {
                if (wcscmp(className, L"AnimationHostClass") == 0 || wcscmp(className, L"AnimationControllerClass") == 0) return;
            }

            BOOL alreadyCloaked = FALSE;
            if (QueryWindowCloaked(hwnd, &alreadyCloaked) && alreadyCloaked) return;

            if (IsDragInFailureCooldown(hwnd)) return;
            
            LONG_PTR style = GetWindowLongPtrW(hwnd, GWL_STYLE);
            if ((style & WS_CHILD) != 0) return;

            RECT rect; GetWindowRect(hwnd, &rect);
            if (rect.right - rect.left < 100 || rect.bottom - rect.top < 100) return;

            static std::unordered_map<HWND, RECT> s_lastRect;
            if (s_lastRect.size() > 128) {
                for (auto itPrune = s_lastRect.begin(); itPrune != s_lastRect.end(); ) {
                    if (!IsWindow(itPrune->first)) {
                        itPrune = s_lastRect.erase(itPrune);
                    } else {
                        ++itPrune;
                    }
                }
            }
            bool actuallyMoved = false;
            bool sizeChanged = false;
            auto it = s_lastRect.find(hwnd);
            if (it != s_lastRect.end()) {
                if (it->second.left != rect.left || it->second.top != rect.top ||
                    it->second.right != rect.right || it->second.bottom != rect.bottom) {
                    actuallyMoved = true;
                }
                if (it->second.right - it->second.left != rect.right - rect.left ||
                    it->second.bottom - it->second.top != rect.bottom - rect.top) {
                    sizeChanged = true;
                }
            } else {
                actuallyMoved = true;
            }
            s_lastRect[hwnd] = rect;
            if (!actuallyMoved) return;

            // Skip drag animation during resize if the setting is enabled
            if (sizeChanged && g_cached_drag_disable_on_resize.load(std::memory_order_relaxed)) return;

            bool isAlreadyDragging = false;
            {
                std::lock_guard<std::mutex> lock(GAnimationsMutex);
                for (const auto& anim : GAnimations) {
                    if (anim.HwndOriginal == hwnd && (anim.AnimType == ANIM_TYPE_DRAG || anim.AnimType == ANIM_TYPE_DRAG_END)) {
                        isAlreadyDragging = true;
                        break;
                    }
                }
            }
            if (!isAlreadyDragging && GHwndAnimController) {
                ANIM_PARAMS* PParams = new ANIM_PARAMS{ hwnd, ANIM_TYPE_DRAG, 0xFFFFFFFF, rect, {0}, ComputeOverscan(rect), nullptr, QueryTimeSeconds() };
                if (!PostMessageW(GHwndAnimController, GUMsgAnimateWindow, 0, (LPARAM)PParams)) {
                    delete PParams;
                }
            }
        }
    }

    DWORD CALLBACK DesktopThreadProc(HANDLE HEvent) {
        CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);

        WNDCLASSW Wc = { 0 }; Wc.lpfnWndProc = DesktopWindowProc; Wc.hInstance = GHinst; Wc.lpszClassName = L"AnimationControllerClass";
        RegisterClassW(&Wc);
        WNDCLASSW HostWc = { 0 }; HostWc.lpfnWndProc = HostWindowProc; HostWc.hInstance = GHinst; HostWc.lpszClassName = L"AnimationHostClass";
        RegisterClassW(&HostWc);

        GHwndAnimController = CreateWindowExW(0, L"AnimationControllerClass", NULL, 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, GHinst, NULL);
        GLocationChangeHook = SetWinEventHook(EVENT_OBJECT_LOCATIONCHANGE, EVENT_OBJECT_LOCATIONCHANGE, NULL, WinEventProc, 0, 0, WINEVENT_OUTOFCONTEXT | WINEVENT_SKIPOWNPROCESS);

        if (HEvent) SetEvent(HEvent);

        MSG Msg;
        while (true) {
            DWORD waitResult = WAIT_TIMEOUT;
            if (GIsTimerActive && GHAnimWaitableTimer) {
                waitResult = MsgWaitForMultipleObjectsEx(1, &GHAnimWaitableTimer, INFINITE, QS_ALLINPUT, MWMO_ALERTABLE);
            } else {
                if (!GetMessageW(&Msg, NULL, 0, 0)) break;
                TranslateMessage(&Msg); DispatchMessageW(&Msg);
                continue;
            }

            if (waitResult == WAIT_OBJECT_0) {
                if (GHwndAnimController) PostMessageW(GHwndAnimController, GUMsgAnimTick, 0, 0);
            } else if (waitResult == WAIT_OBJECT_0 + 1) {
                while (PeekMessageW(&Msg, NULL, 0, 0, PM_REMOVE)) {
                    if (Msg.message == WM_QUIT) goto thread_exit;
                    TranslateMessage(&Msg); DispatchMessageW(&Msg);
                }
            }
        }

thread_exit:
        if (GLocationChangeHook) UnhookWinEvent(GLocationChangeHook);

        while (PeekMessageW(&Msg, NULL, 0, 0, PM_REMOVE)) { if (Msg.message == GUMsgAnimateWindow && Msg.lParam) delete (ANIM_PARAMS*)Msg.lParam;
        }

        {
            std::lock_guard<std::mutex> lock(GPendingMutex);
            for (auto* PParams : GPendingAnimations) delete PParams;
            GPendingAnimations.clear();
        }

        std::vector<ACTIVE_ANIM> ToDestroy;
        {
            std::lock_guard<std::mutex> lock(GAnimationsMutex);
            ToDestroy = std::move(GAnimations);
            GActiveAnimCount.store(0, std::memory_order_relaxed);
        }
        
        StopAnimationTimer(GHwndAnimController);
        if (GHAnimWaitableTimer) {
            CloseHandle(GHAnimWaitableTimer);
            GHAnimWaitableTimer = NULL;
        }
        
        for (auto& Anim : ToDestroy) {
            CTopLevelWindow4D::ClearFastTeardown(Anim.HwndOriginal);
            CTopLevelWindow4D::ReleaseAnimationResources(Anim);
        }

        {
            AcquireSRWLockExclusive(&GTeardownLock);
            GFastTeardownMap.clear();
            ReleaseSRWLockExclusive(&GTeardownLock);
        }

        {
            std::unique_lock<std::recursive_mutex> dcompLock(GDCompTreeMutex);
            std::lock_guard<std::mutex> lock(GHostPoolMutex);
            for (int i = 0; i < MAX_HOST_POOL; ++i) {
                if (GHostPool[i].RootVisual) GHostPool[i].RootVisual->Release();
                if (GHostPool[i].Target) GHostPool[i].Target->Release();
                if (GHostPool[i].Hwnd) DestroyWindow(GHostPool[i].Hwnd);
                GHostPool[i] = {0};
            }
        }
        
        if (GPDCompDevice3) { GPDCompDevice3->Release(); GPDCompDevice3 = nullptr; }
        if (GPDCompDevice) { GPDCompDevice->Release(); GPDCompDevice = nullptr; }
        if (GPDCompDesktopDevice) { GPDCompDesktopDevice->Release(); GPDCompDesktopDevice = nullptr; }
        if (GPD3DContext) { GPD3DContext->Release(); GPD3DContext = nullptr; }
        if (GPD3DDevice) { GPD3DDevice->Release(); GPD3DDevice = nullptr; }
        if (GHwndAnimController && ::IsWindow(GHwndAnimController)) DestroyWindow(GHwndAnimController);

        UnregisterClassW(L"AnimationHostClass", GHinst);
        UnregisterClassW(L"AnimationControllerClass", GHinst); CoUninitialize();
        return 0;
    }
}

typedef HRESULT(WINAPI* GetThemeAnimationProperty_t)(HTHEME, int, int, int, VOID*, DWORD, DWORD*);
GetThemeAnimationProperty_t PGetThemeAnimationPropertyOrig = nullptr;
HRESULT WINAPI GetThemeAnimationProperty_Hook(HTHEME HTheme, int IStoryboardId, int ITargetId, int EProperty, VOID* PvProperty, DWORD CbSize, DWORD* PcbSizeOut) {
    if (GCustomAnimDuration > 0) {
        if (EProperty == 5 && PvProperty && CbSize >= sizeof(DWORD)) { *(DWORD*)PvProperty = GCustomAnimDuration; if (PcbSizeOut) *PcbSizeOut = sizeof(DWORD); return S_OK; }
        if (EProperty == 2 && PvProperty && CbSize >= sizeof(DWORD)) {
            *(DWORD*)PvProperty = 0; if (PcbSizeOut) *PcbSizeOut = sizeof(DWORD); return S_OK;
        }
        if (EProperty == 6 && PvProperty && CbSize >= sizeof(DWORD)) { *(DWORD*)PvProperty = 0; if (PcbSizeOut) *PcbSizeOut = sizeof(DWORD); return S_OK; }
    }
    return PGetThemeAnimationPropertyOrig(HTheme, IStoryboardId, ITargetId, EProperty, PvProperty, CbSize, PcbSizeOut);
}

typedef HRESULT(WINAPI* GetThemeAnimationTransform_t)(HTHEME, int, int, DWORD, VOID*, DWORD, DWORD*);
GetThemeAnimationTransform_t PGetThemeAnimationTransformOrig = nullptr;
HRESULT WINAPI GetThemeAnimationTransform_Hook(HTHEME HTheme, int IStoryboardId, int ITargetId, DWORD DwTransformIndex, VOID* PTransform, DWORD CbSize, DWORD* PcbSizeOut) {
    HRESULT Hr = PGetThemeAnimationTransformOrig(HTheme, IStoryboardId, ITargetId, DwTransformIndex, PTransform, CbSize, PcbSizeOut);
    if (SUCCEEDED(Hr) && GCustomAnimDuration > 0 && PTransform && CbSize >= 20) {
        DWORD ETransformType = *(DWORD*)PTransform; 
        DWORD* PDuration = (DWORD*)((BYTE*)PTransform + 12);

        if (ETransformType == 2 && CbSize >= 28) {
            float* ROpacity = (float*)((BYTE*)PTransform + 20); float* RInitialOpacity = (float*)((BYTE*)PTransform + 24);
            *ROpacity = 0.0f; *RInitialOpacity = 0.0f; *PDuration = GCustomAnimDuration; 
        } else if (ETransformType == 1 && CbSize >= 36) {
            float* RX = (float*)((BYTE*)PTransform + 20); float* RY = (float*)((BYTE*)PTransform + 24);
            float* RInitialX = (float*)((BYTE*)PTransform + 28); float* RInitialY = (float*)((BYTE*)PTransform + 32);
            *RX = 0.0f; *RY = 0.0f; *RInitialX = 0.0f; *RInitialY = 0.0f; *PDuration = GCustomAnimDuration;
        } else if (ETransformType == 0 && CbSize >= 36) {
            float* RX = (float*)((BYTE*)PTransform + 20); float* RY = (float*)((BYTE*)PTransform + 24);
            float* RInitialX = (float*)((BYTE*)PTransform + 28); float* RInitialY = (float*)((BYTE*)PTransform + 32);
            *RX = 1.0f; *RY = 1.0f; *RInitialX = 1.0f; *RInitialY = 1.0f; *PDuration = GCustomAnimDuration;
        }
    }
    return Hr;
}

void FindWindowHandleOffset_Impl(void* Self) {
    BYTE Buffer[0x1A0 + sizeof(void*)] = {0}; SIZE_T BytesRead = 0;
    if (ReadProcessMemory(GetCurrentProcess(), Self, Buffer, sizeof(Buffer), &BytesRead)) {
        for (DWORD Offset = 0x100; Offset <= 0x1A0; Offset += 8) {
            void* PossibleClass = *(void**)(Buffer + Offset);
            if (PossibleClass && (ULONG_PTR)PossibleClass > 0x10000) {
                HWND PossibleHwnd = nullptr;
                if (ReadProcessMemory(GetCurrentProcess(), (char*)PossibleClass + 0x28, &PossibleHwnd, sizeof(HWND), &BytesRead) && BytesRead == sizeof(HWND)) {
                    if (PossibleHwnd && IsWindow(PossibleHwnd) && GetAncestor(PossibleHwnd, GA_ROOT) == PossibleHwnd) {
                        if (GetWindowThreadProcessId(PossibleHwnd, NULL) != 0) {
                            GClassHwndOffset.store(Offset, std::memory_order_release);
                            return;
                        }
                    }
                }
            }
        }
    }
}

// --- Hook Definitions ---

typedef HRESULT(__fastcall* CTopLevelWindow3D_StartAnimation_t)(void* Self, unsigned int AnimType);
typedef HRESULT(__fastcall* CTopLevelWindow3D_StopAnimation_t)(void* Self);
CTopLevelWindow3D_StartAnimation_t CTopLevelWindow3D_StartAnimation_Orig = nullptr;
CTopLevelWindow3D_StopAnimation_t CTopLevelWindow3D_StopAnimation_Orig = nullptr;

HRESULT __fastcall CTopLevelWindow3D_StopAnimation_Hook(void* Self) {
    HWND Hwnd = nullptr;

    DWORD offset = GClassHwndOffset.load(std::memory_order_acquire);
    if (Self != nullptr && offset != 0) {
        void* TargetClass = nullptr;
        if (TryReadMemory((char*)Self + offset, &TargetClass, sizeof(void*)) && TargetClass) {
            if (!TryReadMemory((char*)TargetClass + 40, &Hwnd, sizeof(HWND))) Hwnd = nullptr;
        }
    }

    if (Hwnd && IsWindow(Hwnd)) {
        std::shared_ptr<FAST_TEARDOWN> targetTeardown;
        {
            AcquireSRWLockShared(&GTeardownLock);
            auto it = GFastTeardownMap.find(Hwnd);
            if (it != GFastTeardownMap.end()) targetTeardown = it->second;
            ReleaseSRWLockShared(&GTeardownLock);
        }

        if (targetTeardown && targetTeardown->PRootVisual) {
            bool expected = false;
            if (targetTeardown->Signaled.compare_exchange_strong(expected, true)) {
                std::unique_lock<std::recursive_mutex> dcompLock(GDCompTreeMutex);
                targetTeardown->PRootVisual->RemoveAllVisuals();
                // NO Commit() or DwmFlush() here! DWM handles the frame commit natively.
            }
        }
    }
    return CTopLevelWindow3D_StopAnimation_Orig(Self);
}

static DWORD GetMaxAnimationDuration(DWORD BaseDur, const AdvAnimSettings& Adv) {
    DWORD MaxD = BaseDur;
    if (Adv.opacity.enabled && Adv.opacity.duration + Adv.opacity.delay > MaxD) MaxD = Adv.opacity.duration + Adv.opacity.delay;
    if (Adv.blur.enabled && Adv.blur.duration + Adv.blur.delay > MaxD) MaxD = Adv.blur.duration + Adv.blur.delay;
    if (Adv.scale.enabled && Adv.scale.duration + Adv.scale.delay > MaxD) MaxD = Adv.scale.duration + Adv.scale.delay;
    if (Adv.pitch.enabled && Adv.pitch.duration + Adv.pitch.delay > MaxD) MaxD = Adv.pitch.duration + Adv.pitch.delay;
    if (Adv.yaw.enabled && Adv.yaw.duration + Adv.yaw.delay > MaxD) MaxD = Adv.yaw.duration + Adv.yaw.delay;
    if (Adv.roll.enabled && Adv.roll.duration + Adv.roll.delay > MaxD) MaxD = Adv.roll.duration + Adv.roll.delay;
    return MaxD;
}

struct CTimeline {
    double& GetDurationValue() {
        return *&(reinterpret_cast<double*>(this)[3]);
    }
};

static void SetDwmTimelineDuration(void* Self, double durationSec) {
    if (!Self) return;

    static ULONG s_buildNumber = 0;
    if (s_buildNumber == 0) {
        RTL_OSVERSIONINFOW osVersion = { sizeof(osVersion) };
        HMODULE hNtdll = GetModuleHandleW(L"ntdll.dll");
        if (hNtdll) {
            auto pRtlGetVersion = (NTSTATUS (NTAPI *)(PRTL_OSVERSIONINFOW))GetProcAddress(hNtdll, "RtlGetVersion");
            if (pRtlGetVersion) pRtlGetVersion(&osVersion);
        }
        s_buildNumber = osVersion.dwBuildNumber ? osVersion.dwBuildNumber : 19041;
    }

    size_t timelineIdx = 45;
    if (s_buildNumber >= 26100) {
        timelineIdx = 40;
    } else if (s_buildNumber >= 22000) {
        timelineIdx = 46;
    }

    void* pTimeline = nullptr;
    if (TryReadMemory((char*)Self + timelineIdx * sizeof(void*), &pTimeline, sizeof(void*)) && pTimeline) {
        if ((ULONG_PTR)pTimeline > 0x10000) {
            double duration = durationSec;
            SIZE_T written = 0;
            WriteProcessMemory(GetCurrentProcess(), reinterpret_cast<double*>(pTimeline) + 3, &duration, sizeof(double), &written);
        }
    }
}

HRESULT __fastcall CTopLevelWindow3D_StartAnimation_Hook(void* Self, unsigned int AnimType) {
    bool WasHandled = false; int CustomAnimType = -1;
    HWND Hwnd = nullptr;
    RECT RcFrame = { 0 }; void* TargetClass = nullptr;

    if (Self != nullptr) {
        std::call_once(GScannerFlag, [Self]() {
            FindWindowHandleOffset_Impl(Self);
        });
        DWORD offset = GClassHwndOffset.load(std::memory_order_acquire);
        if (offset != 0) {
            if (TryReadMemory((char*)Self + offset, &TargetClass, sizeof(void*)) && TargetClass) {
                if (!TryReadMemory((char*)TargetClass + 40, &Hwnd, sizeof(HWND)) || !IsWindow(Hwnd)) {
                    Hwnd = nullptr;
                } else {
                    if (!TryReadMemory((char*)TargetClass + 48, &RcFrame.left, sizeof(int)) ||
                        !TryReadMemory((char*)TargetClass + 52, &RcFrame.top, sizeof(int)) ||
                        !TryReadMemory((char*)TargetClass + 56, &RcFrame.right, sizeof(int)) ||
                        !TryReadMemory((char*)TargetClass + 60, &RcFrame.bottom, sizeof(int))) {
                        Hwnd = nullptr;
                    }
                    if (Hwnd && (RcFrame.right <= RcFrame.left || RcFrame.bottom <= RcFrame.top || RcFrame.left <= -20000)) {
                        Hwnd = nullptr;
                    }
                }
            }
        }
    }

    if (Hwnd) {
        if (AnimType == 1) CustomAnimType = ANIM_TYPE_OPEN;
        else if (AnimType == 3) CustomAnimType = ANIM_TYPE_MINIMIZE;
        else if (AnimType == 5) CustomAnimType = ANIM_TYPE_RESTORE;
        else if (AnimType == 6) CustomAnimType = ANIM_TYPE_CLOSE;

        if (CustomAnimType != -1) {
            MOD_SETTINGS Settings = GetSafeSettings();
            DWORD BaseDuration = 250; DWORD MasterDuration = 250;
            
            if (Settings.preset == 1) {
                if (CustomAnimType == ANIM_TYPE_OPEN) MasterDuration = 250;
                else if (CustomAnimType == ANIM_TYPE_CLOSE) MasterDuration = 166;
                else if (CustomAnimType == ANIM_TYPE_MINIMIZE) MasterDuration = 250;
                else if (CustomAnimType == ANIM_TYPE_RESTORE) MasterDuration = 250;
            } else {
                if (CustomAnimType == ANIM_TYPE_OPEN) {
                    if (!Settings.enable_open) CustomAnimType = -1;
                    else { BaseDuration = Settings.duration_open; MasterDuration = GetMaxAnimationDuration(BaseDuration, Settings.open_adv); }
                } else if (CustomAnimType == ANIM_TYPE_CLOSE) {
                    if (!Settings.enable_close) CustomAnimType = -1;
                    else { BaseDuration = Settings.duration_close; MasterDuration = GetMaxAnimationDuration(BaseDuration, Settings.close_adv); }
                } else if (CustomAnimType == ANIM_TYPE_MINIMIZE) {
                    if (!Settings.enable_minimize) CustomAnimType = -1;
                    else { BaseDuration = Settings.duration_minimize; MasterDuration = GetMaxAnimationDuration(BaseDuration, Settings.min_adv); }
                } else if (CustomAnimType == ANIM_TYPE_RESTORE) {
                    if (!Settings.enable_restore) CustomAnimType = -1;
                    else { BaseDuration = Settings.duration_restore; MasterDuration = GetMaxAnimationDuration(BaseDuration, Settings.res_adv); }
                }
            }

            if (CustomAnimType != -1) {
                if (GAnimationsShiftKeyEnabled && (GetAsyncKeyState(VK_SHIFT) & 0x8000)) MasterDuration *= 20;
                RECT RcTaskbar = { 0 };
                if (CustomAnimType == ANIM_TYPE_MINIMIZE || CustomAnimType == ANIM_TYPE_RESTORE) {
                    if (PNtUserGetWindowMinimizeRect) PNtUserGetWindowMinimizeRect(Hwnd, &RcTaskbar);
                    if (IsRectEmpty(&RcTaskbar) || RcTaskbar.left <= -20000 || RcTaskbar.top <= -20000) {
                        HWND hTray = FindWindowW(L"Shell_TrayWnd", NULL);
                        if (hTray && GetWindowRect(hTray, &RcTaskbar)) {
                            // Valid taskbar rect
                        } else {
                            int Sw = GetSystemMetrics(SM_CXSCREEN);
                            int Sh = GetSystemMetrics(SM_CYSCREEN);
                            RcTaskbar = { Sw / 2 - 50, Sh - 40, Sw / 2 + 50, Sh };
                        }
                    }
                }

                THUMB_OVERSCAN Overscan = ComputeOverscan(RcFrame);

                if (GHwndAnimController) {
                    ANIM_PARAMS* PParams = new ANIM_PARAMS{ Hwnd, CustomAnimType, MasterDuration, RcFrame, RcTaskbar, Overscan, TargetClass, QueryTimeSeconds() };
                    if (PostMessageW(GHwndAnimController, GUMsgAnimateWindow, 0, (LPARAM)PParams)) { 
                        WasHandled = true;
                        GCustomAnimDuration = MasterDuration; GCurrentCustomAnimType = CustomAnimType;
                        SetDwmTimelineDuration(Self, (double)MasterDuration / 1000.0);
                    } else { 
                        delete PParams;
                    }
                }
            }
        }
    }
    
    struct ScopedDurationReset {
        bool& handled;
        ~ScopedDurationReset() { if (handled) { GCustomAnimDuration = 0; GCurrentCustomAnimType = -1; } }
    } resetter{ WasHandled };

    return CTopLevelWindow3D_StartAnimation_Orig(Self, AnimType);
}

typedef LRESULT(WINAPI* DefWindowProcW_t)(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
DefWindowProcW_t DefWindowProcW_Orig = nullptr;
LRESULT WINAPI DefWindowProcW_Hook(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) {
    static UINT s_MsgCloak = RegisterWindowMessageW(L"WindowAnimationCloakTrigger");
    if (Msg == s_MsgCloak) {
        int cloak = wParam ? 1 : 0;
        DwmSetWindowAttribute(hWnd, 13, &cloak, sizeof(cloak));
        return 0;
    }
    return DefWindowProcW_Orig ? DefWindowProcW_Orig(hWnd, Msg, wParam, lParam) : 0;
}

typedef LRESULT(WINAPI* DefWindowProcA_t)(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
DefWindowProcA_t DefWindowProcA_Orig = nullptr;
LRESULT WINAPI DefWindowProcA_Hook(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) {
    static UINT s_MsgCloak = RegisterWindowMessageW(L"WindowAnimationCloakTrigger");
    if (Msg == s_MsgCloak) {
        int cloak = wParam ? 1 : 0;
        DwmSetWindowAttribute(hWnd, 13, &cloak, sizeof(cloak));
        return 0;
    }
    return DefWindowProcA_Orig ? DefWindowProcA_Orig(hWnd, Msg, wParam, lParam) : 0;
}

BOOL Wh_ModInit(void) {
    if (!CheckCrashLoopFailsafe()) return FALSE;

    WCHAR processName[MAX_PATH];
    GetModuleFileNameW(NULL, processName, MAX_PATH);
    if (!wcsstr(processName, L"dwm.exe")) {
        HMODULE hUser32 = GetModuleHandleW(L"user32.dll");
        if (hUser32) {
            void* pDefWindowProcW = (void*)GetProcAddress(hUser32, "DefWindowProcW");
            if (pDefWindowProcW) Wh_SetFunctionHook(pDefWindowProcW, (void*)DefWindowProcW_Hook, (void**)&DefWindowProcW_Orig);
            void* pDefWindowProcA = (void*)GetProcAddress(hUser32, "DefWindowProcA");
            if (pDefWindowProcA) Wh_SetFunctionHook(pDefWindowProcA, (void*)DefWindowProcA_Hook, (void**)&DefWindowProcA_Orig);
        }
        return TRUE; 
    }

    LoadModSettings(); GHinst = GetModuleHandle(NULL);
    GUMsgAnimateWindow = RegisterWindowMessageW(L"WindowAnimationTrigger");
    GUMsgInstantTeardown = RegisterWindowMessageW(L"WindowAnimationInstantTeardown");
    GUMsgAnimTick = RegisterWindowMessageW(L"WindowAnimationTick");
    GRevealOffsetInfo = { 0, 0 };

    HMODULE HDwmApi = GetModuleHandleW(L"dwmapi.dll");
    if (!HDwmApi) HDwmApi = LoadLibraryW(L"dwmapi.dll");
    HMODULE HWin32u = GetModuleHandleW(L"win32u.dll");
    if (!HWin32u) HWin32u = LoadLibraryW(L"win32u.dll");
    HMODULE HUser32 = GetModuleHandleW(L"user32.dll");
    if (!HUser32) HUser32 = LoadLibraryW(L"user32.dll");
    HMODULE HUxtheme = GetModuleHandleW(L"uxtheme.dll");
    if (!HUxtheme) HUxtheme = LoadLibraryW(L"uxtheme.dll");

    if (HDwmApi) {
        PDwmpCreateSharedThumbnailVisual = (DwmpCreateSharedThumbnailVisual_t)GetProcAddress(HDwmApi, (LPCSTR)147);
        if (!PDwmpCreateSharedThumbnailVisual) PDwmpCreateSharedThumbnailVisual = (DwmpCreateSharedThumbnailVisual_t)GetProcAddress(HDwmApi, (LPCSTR)163);
        PDwmUnregisterThumbnail = (DwmUnregisterThumbnail_t)GetProcAddress(HDwmApi, "DwmUnregisterThumbnail");
        PDwmUpdateThumbnailProperties = (DwmUpdateThumbnailProperties_t)GetProcAddress(HDwmApi, "DwmUpdateThumbnailProperties");
    }

    if (HWin32u) PNtUserGetWindowMinimizeRect = (NtUserGetWindowMinimizeRect_t)GetProcAddress(HWin32u, "NtUserGetWindowMinimizeRect");
    if (!PNtUserGetWindowMinimizeRect && HUser32) PNtUserGetWindowMinimizeRect = (NtUserGetWindowMinimizeRect_t)GetProcAddress(HUser32, "GetWindowMinimizeRect");

    HKEY HKey;
    if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows\\Dwm", 0, KEY_READ, &HKey) == ERROR_SUCCESS) {
        DWORD Val = 0; DWORD Size = sizeof(Val);
        if (RegQueryValueExW(HKey, L"AnimationsShiftKey", NULL, NULL, (LPBYTE)&Val, &Size) == ERROR_SUCCESS) GAnimationsShiftKeyEnabled = (Val != 0);
        RegCloseKey(HKey);
    }

    if (HUxtheme) {
        void* PGetThemeAnimationProperty = (void*)GetProcAddress(HUxtheme, "GetThemeAnimationProperty");
        if (PGetThemeAnimationProperty) Wh_SetFunctionHook(PGetThemeAnimationProperty, (void*)GetThemeAnimationProperty_Hook, (void**)&PGetThemeAnimationPropertyOrig);
        void* PGetThemeAnimationTransform = (void*)GetProcAddress(HUxtheme, "GetThemeAnimationTransform");
        if (PGetThemeAnimationTransform) Wh_SetFunctionHook(PGetThemeAnimationTransform, (void*)GetThemeAnimationTransform_Hook, (void**)&PGetThemeAnimationTransformOrig);
    }

    HMODULE uDWM = GetModuleHandleW(L"uDWM.dll");
    if (!uDWM) uDWM = LoadLibraryW(L"uDWM.dll");
    WindhawkUtils::SYMBOL_HOOK uDWMHooks[] = {
        { { L"private: long __cdecl CTopLevelWindow3D::StartAnimation(enum CTopLevelWindow3D::WindowAnimationType)", L"public: long __cdecl CTopLevelWindow3D::StartAnimation(enum CTopLevelWindow3D::WindowAnimationType)" }, (void**)&CTopLevelWindow3D_StartAnimation_Orig, (void*)CTopLevelWindow3D_StartAnimation_Hook, false },
        { { L"public: long __cdecl CTopLevelWindow3D::StopAnimation(void)", L"private: long __cdecl CTopLevelWindow3D::StopAnimation(void)" }, (void**)&CTopLevelWindow3D_StopAnimation_Orig, (void*)CTopLevelWindow3D_StopAnimation_Hook, false }
    };

    bool hooksOk = WindhawkUtils::HookSymbols(uDWM, uDWMHooks, ARRAYSIZE(uDWMHooks));
    if (!hooksOk) return FALSE;

    if (!GHAnimThread) {
        HANDLE HEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
        GHAnimThread = CreateThread(NULL, 0, CDesktopManager::DesktopThreadProc, HEvent, 0, &GHAnimThreadId);
        if (HEvent) { WaitForSingleObject(HEvent, 5000); CloseHandle(HEvent); }
    }

    return TRUE;
}

void Wh_ModUninit(void) {
    g_ModUnloading.store(true);
    if (CDesktopManager::GDcompModule) {
        FreeLibrary(CDesktopManager::GDcompModule);
        CDesktopManager::GDcompModule = NULL;
    }

    GCommitHooked = false;
                
    
    HMODULE hNtdll = GetModuleHandleW(L"ntdll.dll");
    if (hNtdll) {
        auto pRtlDllShutdownInProgress = (BOOLEAN (NTAPI *)())GetProcAddress(hNtdll, "RtlDllShutdownInProgress");
        if (pRtlDllShutdownInProgress && pRtlDllShutdownInProgress()) {
            if (GHAnimThread) CloseHandle(GHAnimThread);
            return;
        }
    }
    
    if (GHAnimThread) {
        PostThreadMessageW(GHAnimThreadId, WM_QUIT, 0, 0);
        if (GHwndAnimController && ::IsWindow(GHwndAnimController)) {
            PostMessageW(GHwndAnimController, WM_CLOSE, 0, 0);
        }
        
        ULONGLONG WaitStart = GetTickCount64();
        while (true) {
            ULONGLONG Elapsed = GetTickCount64() - WaitStart;
            if (Elapsed >= 3000) break;
            
            DWORD WaitResult = MsgWaitForMultipleObjects(1, &GHAnimThread, FALSE, (DWORD)(3000 - Elapsed), QS_ALLINPUT);
            if (WaitResult == WAIT_OBJECT_0) {
                break;
            } else if (WaitResult == WAIT_OBJECT_0 + 1) {
                MSG Msg;
                while (PeekMessageW(&Msg, NULL, 0, 0, PM_REMOVE)) {
                    TranslateMessage(&Msg);
                    DispatchMessageW(&Msg);
                }
            } else {
                break;
            }
        }
        
        CloseHandle(GHAnimThread);
        GHAnimThread = NULL;
    }
}