{ config, pkgs, lib, inputs, ... }:
{
  # Imported for all hosts via flake.nix extraModules.
  # Desktop hosts use stylix (unstable), Mediaserver uses stylix-stable (25.11).

  config = {
    stylix = {
      enable = true;
      # builtins.path hashes only the image content, not the whole flake tree,
      # so palette.json is only rebuilt when the wallpaper itself changes.
      image = builtins.path {
        name = "wallpaper.png";
        path = inputs.self + "/walls/wallpaper.png";
      };
      polarity = "dark";

      # Let stylix theme every target it supports. Per-target opt-outs go
      # under home-manager.users.fred.stylix.targets.<x>.enable = false.
      autoEnable = true;

      cursor = {
        package = pkgs.bibata-cursors;
        name = "Bibata-Modern-Ice";
        size = 24;
      };

      fonts = {
        monospace = {
          package = pkgs.nerd-fonts.fira-mono;
          name = "FiraMono Nerd Font";
        };
        sansSerif = {
          package = pkgs.inter;
          name = "Inter";
        };
        serif = {
          package = pkgs.inter;
          name = "Inter";
        };
      };
    };

    home-manager.users.fred = { config, lib, pkgs, osConfig, ... }: let
      isDesktop = lib.elem osConfig.networking.hostName [ "FredOS-Gaming" "FredOS-Macbook" ];
      c = config.lib.stylix.colors;

      # Pure-Nix hex parsing for color distance calculation.
      hexDigit = ch: {
        "0"=0;"1"=1;"2"=2;"3"=3;"4"=4;"5"=5;"6"=6;"7"=7;
        "8"=8;"9"=9;"a"=10;"b"=11;"c"=12;"d"=13;"e"=14;"f"=15;
      }.${ch};
      hexByte = s: hexDigit (builtins.substring 0 1 s) * 16
                 + hexDigit (builtins.substring 1 1 s);
      hexToRgb = hex: let h = lib.toLower hex; in {
        r = hexByte (builtins.substring 0 2 h);
        g = hexByte (builtins.substring 2 2 h);
        b = hexByte (builtins.substring 4 2 h);
      };

      # papirus-folders named palette → representative hex values.
      pfPalette = {
        adwaita="3584e4"; black="000000"; bluegrey="607d8b"; breeze="1d99f3";
        brown="795548"; cyan="00bcd4"; darkcyan="00838f"; deeporange="ff5722";
        green="4caf50"; grey="9e9e9e"; indigo="3f51b5"; magenta="e91e63";
        nordic="5e81ac"; orange="ff9800"; palebrown="a1887f"; palegreen="8bc34a";
        pink="f06292"; red="f44336"; teal="009688"; violet="9c27b0";
        white="ffffff"; yellow="ffeb3b";
      };

      # Closest papirus-folders color to stylix's accent (base0D), chosen at
      # eval time via squared RGB distance — no runtime script needed.
      closestPfColor =
        let
          sq   = x: x * x;
          dist = a: b: sq (a.r - b.r) + sq (a.g - b.g) + sq (a.b - b.b);
          accent = hexToRgb c.base0D;
          ranked = map (n: { name = n; d = dist accent (hexToRgb pfPalette.${n}); })
                       (builtins.attrNames pfPalette);
        in (builtins.foldl' (best: x: if x.d < best.d then x else best)
                            (builtins.head ranked)
                            (builtins.tail ranked)).name;

      # Papirus-Dark with folders recolored to the closest matching color.
      # Replicates papirus-folders' change_color logic directly: for each
      # colored variant (folder-{color}-*.svg), symlink the generic name
      # (folder-*.svg) to it. No papirus-folders binary needed.
      papirusDark = pkgs.runCommand "papirus-dark-${closestPfColor}" {} ''
        # Copy full icon tree so Papirus-Dark's ../Papirus/… symlinks resolve.
        tmpthemes=$(mktemp -d)
        cp -r ${pkgs.papirus-icon-theme}/share/icons/. "$tmpthemes/"
        chmod -R u+w "$tmpthemes"

        # Recolor folders. Papirus-Dark delegates 48x48 etc. to ../Papirus via
        # symlinks, so we operate through those resolved paths in the temp tree.
        for size in 22x22 24x24 32x32 48x48 64x64; do
          places="$tmpthemes/Papirus-Dark/$size/places"
          [ -d "$places" ] || continue
          for f in \
            "$places/folder-${closestPfColor}"-*.svg \
            "$places/folder-${closestPfColor}.svg" \
            "$places/user-${closestPfColor}"-*.svg \
            "$places/user-${closestPfColor}.svg"; do
            [ -f "$f" ] || continue
            fname=$(basename "$f")
            ln -sf "$fname" "$places/''${fname/-${closestPfColor}/}"
          done
        done

        # Copy Papirus-Dark with -L to dereference all symlinks, so the output
        # is self-contained — no dangling ../Papirus/… pointers.
        mkdir -p $out/share/icons
        cp -rL "$tmpthemes/Papirus-Dark" $out/share/icons/
      '';

      # Map Material You placeholders to the closest base16 slot in stylix's
      # palette. The mapping is approximate (Material You has more semantic
      # colours than base16), but covers the placeholders used in our Zen
      # userChrome and Vesktop quickCss templates.
      stylixize = builtins.replaceStrings
        [
          "{{colors.primary.default.hex}}"
          "{{colors.primary_container.default.hex}}"
          "{{colors.secondary_container.default.hex}}"
          "{{colors.tertiary_container.default.hex}}"
          "{{colors.surface.default.hex}}"
          "{{colors.surface_container.default.hex}}"
          "{{colors.surface_container_low.default.hex}}"
          "{{colors.surface_container_high.default.hex}}"
          "{{colors.on_surface.default.hex}}"
          "{{colors.on_surface_variant.default.hex}}"
          "{{colors.outline.default.hex}}"
          "{{colors.outline_variant.default.hex}}"
        ]
        [
          "#${c.base0D}" # primary accent
          "#${c.base02}" # primary container
          "#${c.base0C}" # secondary container (cyan)
          "#${c.base0E}" # tertiary container (purple)
          "#${c.base00}" # surface (main bg)
          "#${c.base01}" # surface container
          "#${c.base00}" # surface container low
          "#${c.base02}" # surface container high
          "#${c.base05}" # on surface (fg)
          "#${c.base04}" # on surface variant (muted fg)
          "#${c.base03}" # outline
          "#${c.base02}" # outline variant
        ];
    in lib.mkMerge [
      # Desktop-only: Zen/Vesktop CSS and GTK icon theme
      (lib.mkIf isDesktop {
        home.file.".zen/fraudek5.Default Profile/chrome/userChrome.css".text =
          stylixize (builtins.readFile "${inputs.self}/templates/zen-userChrome.css");

        home.file.".config/vesktop/settings/quickCss.css".text =
          stylixize (builtins.readFile "${inputs.self}/templates/vesktop-quickCss.css");

        gtk.iconTheme = {
          package = papirusDark;
          name    = "Papirus-Dark";
        };
      })
    ];
  };
}
