{ self, ... }: {
  flake.nixosModules.desktopHyprland =
    { config, options, lib, pkgs, ... }:
    let
      cfg = config.chiasson.desktop;
      hmAvailable = lib.hasAttrByPath [ "home-manager" "sharedModules" ] options;
    in
    {
      options.chiasson.desktop.hyprland = {
        enable = lib.mkOption {
          type = lib.types.bool;
          default = false;
          description = "Hyprland session + HM wiring.";
        };
        settings = lib.mkOption {
          type = lib.types.attrs;
          default = { };
          description = "Extra `wayland.windowManager.hyprland.settings` merged with defaults.";
        };
      };

      config = lib.mkMerge [
        (lib.mkIf cfg.hyprland.enable {
          programs.hyprland.enable = true;
        })
        (lib.mkIf (cfg.hyprland.enable && hmAvailable) {
          "home-manager".sharedModules = [ self.homeManagerModules.desktopHyprland ];
        })
      ];
    };

  flake.homeManagerModules.desktopHyprland = {
    config,
    lib,
    osConfig ? { },
    pkgs,
    ...
  }:
  let
    hyprlandEnabled = osConfig.chiasson.desktop.hyprland.enable or false;
    keyringEnabled = osConfig.chiasson.desktop.keyring.enable or false;
    # nixpkgs hyprland-plugins pin is stale for current Hyprland — override to a known-good rev.
    hyprbarsPatched =
      let
        hyprlandPluginsSrc = pkgs.fetchFromGitHub {
          owner = "hyprwm";
          repo = "hyprland-plugins";
          rev = "b85a56b9531013c79f2f3846fd6ee2ff014b8960";
          hash = "sha256-xwNa+1D8WPsDnJtUofDrtyDCZKZotbUymzV/R5s+M0I=";
        };
      in
      pkgs.hyprlandPlugins.hyprbars.overrideAttrs (_: {
        version = "unstable-2026-02-23";
        src = "${hyprlandPluginsSrc}/hyprbars";
      });
  in
  {
    config = lib.mkIf hyprlandEnabled {
      wayland.windowManager.hyprland = {
        enable = true;
        # null = use NixOS Hyprland/xdg-desktop-portal-hyprland (same versions as the session).
        package = null;
        portalPackage = null;
        plugins = [ hyprbarsPatched ];
        extraConfig = ''
          source = ~/.config/hypr/colors.conf
        '';

        settings = lib.mkMerge [
          (lib.mkIf keyringEnabled {
            exec-once = lib.mkBefore [
              "dbus-update-activation-environment --systemd --all"
            ];
          })
          {
            monitor = [ ",preferred,auto,auto" ];
            general = {
              gaps_in = 8;
              gaps_out = 4;
              border_size = 2;
              allow_tearing = false;
            };
            cursor.no_hardware_cursors = true;
            env = [
              "XCURSOR_THEME,phinger-cursors-dark"
              "XCURSOR_SIZE,32"
            ];
            input = {
              kb_layout = "ca";
              kb_variant = "";
              numlock_by_default = true;
            };
            binds.scroll_event_delay = 50;
            exec-once = [
              "nm-applet --indicator &"
              "sleep 1 && hyprctl reload"
            ];

            # Default keybinds
            bind =
              [
                "SUPER,T,exec,kitty -e fish"
                "ControlSuper,T,exec,konsole"
                "SUPER,D,exec,rofi -show drun"
                "ControlSuper,D,exec,rofi -show window"
                "SUPER,E,exec,dolphin"
                "Super, Q, killactive"
                "ControlSuper, Q, exec, hyprctl kill"
                "Super, F, fullscreen, 0"
                "Super, G, fullscreen, 1"
                "ShiftSuper, F, fullscreenstate, 0 3"
                "Super, Minus, splitratio, -0.1"
                "Super, Equal, splitratio, 0.1"
                "AltSuper, Space, togglefloating"
                "Super, P, pin"
                "Super, Space, exec, dms ipc call spotlight toggle"
                "Super, I, exec, dms ipc call settings focusOrToggle"
                "Super, N, exec, dms ipc call notepad toggle"
                "ShiftSuper, N, exec, dms ipc call notifications toggle"
                "Super, M, exec, dms ipc call processlist focusOrToggle"
                "Super, L, exec, dms ipc call lock lock"
                "ShiftSuper, V, exec, dms ipc call clipboard toggle"
                "Super, Tab, cyclenext"
                "Super, Tab, bringactivetotop"
                "Super, left, movefocus, l"
                "Super, right, movefocus, r"
                "Super, up, movefocus, u"
                "Super, down, movefocus, d"
                "ShiftSuper, left, movewindow, l"
                "ShiftSuper, right, movewindow, r"
                "ShiftSuper, up, movewindow, u"
                "ShiftSuper, down, movewindow, d"
              ]
              ++ (builtins.map (i: "Super, ${toString i}, workspace, ${toString i}") (builtins.genList (n: n + 1) 9))
              ++ (builtins.map (i: "ControlSuper, ${toString i}, focusworkspaceoncurrentmonitor, ${toString i}") (builtins.genList (n: n + 1) 9))
              ++ (builtins.map (i: "ShiftSuper, ${toString i}, movetoworkspacesilent, ${toString i}") (builtins.genList (n: n + 1) 9));

            bindm = [
              " , mouse:282, movewindow"
              "Super, mouse:272, movewindow"
              "Super, mouse:273, resizewindow"
            ];

            bindl = [
              "Super, mouse_up, splitratio, -0.1"
              "Super, mouse_down, splitratio, 0.1"
              " , XF86AudioPlay, exec, playerctl play-pause"
              " , XF86AudioPrev, exec, playerctl previous"
              " , XF86AudioNext, exec, playerctl next"
              " , XF86AudioMute, exec, wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle"
              " , XF86MonBrightnessDown, exec, brightnessctl s 10%-"
              " , XF86MonBrightnessUp, exec, brightnessctl s +10%"
            ];

            bindel = [
              " , XF86AudioRaiseVolume, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%+"
              " , XF86AudioLowerVolume, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%-"
            ];

            # Decoration / blur
            decoration = {
              rounding = 10;
              active_opacity = 0.95;
              inactive_opacity = 0.85;
              shadow = {
                enabled = true;
                range = 5;
                render_power = 8;
              };
              blur = {
                enabled = true;
                new_optimizations = true;
                xray = false;
                size = 2;
                passes = 4;
                vibrancy = 10;
              };
            };
            misc = {
              disable_hyprland_logo = true;
              disable_splash_rendering = true;
            };
            plugin.hyprbars = {
              enabled = true;
              bar_height = 30;
              bar_blur = true;
              bar_padding = 10;
              bar_button_padding = 7;
              bar_precedence_over_border = true;
              bar_part_of_window = true;
              bar_title_enabled = true;
              bar_text_size = 10;
              bar_text_font = "Sans";
              bar_text_align = "center";
              bar_buttons_alignment = "left";
              icon_on_hover = true;
              "hyprbars-button" = [
                "rgb(ed6a5f), 12, 󰖭, hyprctl dispatch killactive, rgb(460804)"
                "rgb(f6be50), 12, 󰖰, hyprctl dispatch movetoworkspacesilent special:minimized, rgb(90591d)"
                "rgb(61c555), 12, 󰘖, hyprctl dispatch fullscreen 1, rgb(2a6218)"
              ];
            };

            windowrule = [
              "sync_fullscreen 0, match:class ^(?i)microsoft-edge|Spotify|org.kde.gwenview|zen-beta$"
              "opacity 1.0 override 0.95 override, match:class ^(?i)microsoft-edge$"
              "opacity 1.0 override 1.00 override, match:class ^(?i)com.stremio.stremio$"
              "opacity 1.0 override 0.85 override, match:class ^(?i)zen-beta$"
              "no_screen_share on, match:class ^(?i)(microsoft-edge|zen-beta)$, match:title ^(?i).*(scotiabank|paypal).*"
              "no_screen_share on, match:class ^(?i)microsoft-edge$, match:initial_title ^(?i).*(?i)personal 2.*edge.*$"
              "hyprbars:no_bar on, match:class ^(?i)(microsoft-edge|Cursor|Flow|looking-glass-client|localsend_app)$"
            ];
          }
          (osConfig.chiasson.desktop.hyprland.settings or { })
        ];
      };
    };
  };
}
