{"webLayers":[{"_id":"6862a356ce623f4f19e39fd3","date_filter":{"enabled":false,"from_date":null,"to_date":null},"trigger":{"include_pages":[{"type":"any"}],"exclude_pages":null},"smart_trigger":null,"device_target":{"type":"any"},"frequency":"always","uses_personalization":true,"data":"","variables_target":{"conditions":[{"attribute":{"id":"687777bbd6d560fc90693882","type":"page_variable"},"constraint":{"operands":[{"type":"constant","value":"product || category"}],"operator":"regex","type":"string"}},{"attribute":{"id":"6862a355ce623f4f19e39fc9","type":"page_variable"},"constraint":{"operator":"is","type":"boolean","value":"true"}},{"attribute":{"id":"687777bbd6d560fc90693886","type":"page_variable"},"constraint":{"operands":[{"type":"constant","value":"de34bs"},{"type":"constant","value":"mybb21"},{"type":"constant","value":"destyle21"},{"type":"constant","value":"mybb"},{"type":"constant","value":"defb99"},{"type":"constant","value":"desc99"},{"type":"constant","value":"dedc99"},{"type":"constant","value":"deyt99"},{"type":"constant","value":"depm99"},{"type":"constant","value":"debi99"},{"type":"constant","value":"denb99"},{"type":"constant","value":"degd99"},{"type":"constant","value":"defbta"},{"type":"constant","value":"nbfdcr"},{"type":"constant","value":"fbfdcr"},{"type":"constant","value":"bgfdcr"},{"type":"constant","value":"gofdcr"},{"type":"constant","value":"defbnw"},{"type":"constant","value":"decr01"},{"type":"constant","value":"degnbt"},{"type":"constant","value":"degnbtc"},{"type":"constant","value":"defbre"},{"type":"constant","value":"deac1"},{"type":"constant","value":"defb99a"},{"type":"constant","value":"defb99b"},{"type":"constant","value":"denbai"},{"type":"constant","value":"denbam"}],"operator":"not in","type":"string"}}]},"page_vars":[{"id":"6870cfc582729abfafd29d0c"},{"id":"686bda9631a9bc8251208077"}]},{"_id":"68667741b83d181ea5a3898c","date_filter":{"enabled":false,"from_date":null,"to_date":null},"trigger":{"include_pages":[{"url":"birthday-signup","type":"contains"}],"exclude_pages":null},"smart_trigger":null,"device_target":{"type":"any"},"frequency":"always","uses_personalization":true,"data":"","variables_target":null,"page_vars":[{"id":"6870cfc682729abfafd29d10"},{"id":"6870cfc582729abfafd29d0c"}]},{"_id":"6870cfc682729abfafd29d15","date_filter":{"enabled":false,"from_date":null,"to_date":null},"trigger":{"include_pages":[{"url":"appointment-feedback","type":"contains"}],"exclude_pages":null},"smart_trigger":null,"device_target":{"type":"any"},"frequency":"until_visitor_interacts","uses_personalization":true,"data":"","variables_target":{"conditions":[{"attribute":{"id":"6870cfc582729abfafd29d0c","type":"page_variable"},"constraint":{"operands":[{"type":"constant","value":"UK"}],"operator":"equals","type":"string"}}]},"page_vars":[{"id":"6870cfc682729abfafd29d10"}]},{"_id":"6870cfc682729abfafd29d1a","date_filter":{"enabled":false,"from_date":null,"to_date":null},"trigger":{"include_pages":[{"url":"appointment-feedback","type":"contains"}],"exclude_pages":null},"smart_trigger":null,"device_target":{"type":"any"},"frequency":"until_visitor_interacts","uses_personalization":true,"data":"","variables_target":{"conditions":[{"attribute":{"id":"6870cfc582729abfafd29d0c","type":"page_variable"},"constraint":{"operands":[{"type":"constant","value":"US"}],"operator":"equals","type":"string"}}]},"page_vars":[{"id":"6870cfc682729abfafd29d10"}]},{"_id":"687777bbd6d560fc9069388f","date_filter":{"enabled":false,"from_date":null,"to_date":1755730799},"trigger":{"include_pages":[{"type":"any"}],"exclude_pages":[{"url":"/it_IT/","type":"contains"},{"url":"/es_ES/","type":"contains"}]},"smart_trigger":null,"device_target":{"type":"any"},"frequency":"only_once","uses_personalization":true,"data":"","variables_target":{"conditions":[{"attribute":{"id":"687777bbd6d560fc90693882","type":"page_variable"},"constraint":{"operands":[{"type":"constant","value":"product"},{"type":"constant","value":"category"}],"operator":"in","type":"string"}},{"attribute":{"id":"687777bbd6d560fc90693886","type":"page_variable"},"constraint":{"operands":[{"type":"constant","value":"gbpdefault"},{"type":"constant","value":"frdefault"},{"type":"constant","value":"frdefault"},{"type":"constant","value":"xbrdefault"},{"type":"constant","value":"eurdefault"},{"type":"constant","value":"nldefault"},{"type":"constant","value":"chdefault"},{"type":"constant","value":"caddefault"},{"type":"constant","value":"dmdefault"},{"type":"constant","value":"auddefault"},{"type":"constant","value":"ukgob"},{"type":"constant","value":"shareuk1"},{"type":"constant","value":"gegob"}],"operator":"in","type":"string"}},{"attribute":{"id":"6870cfc582729abfafd29d0c","type":"page_variable"},"constraint":{"operands":[{"type":"constant","value":"UK"},{"type":"constant","value":"DE"},{"type":"constant","value":"FR"},{"type":"constant","value":"EU"},{"type":"constant","value":"XBR"},{"type":"constant","value":"NL"},{"type":"constant","value":"CH"}],"operator":"in","type":"string"}}]},"page_vars":[{"id":"686bda9631a9bc8251208077"},{"id":"6870cfc582729abfafd29d0c"}]},{"_id":"68c04fe19e95add84bba00ec","date_filter":{"enabled":false,"from_date":null,"to_date":1755730799},"trigger":{"include_pages":[{"type":"any"}],"exclude_pages":null},"smart_trigger":null,"device_target":{"type":"any"},"frequency":"always","uses_personalization":true,"data":"","variables_target":{"conditions":[{"attribute":{"id":"687777bbd6d560fc90693886","type":"page_variable"},"constraint":{"operands":[{"type":"constant","value":"gbpdefault"},{"type":"constant","value":"frdefault"},{"type":"constant","value":"frdefault"},{"type":"constant","value":"xbrdefault"},{"type":"constant","value":"eurdefault"},{"type":"constant","value":"dmdefault"},{"type":"constant","value":"nldefault"},{"type":"constant","value":"chdefault"},{"type":"constant","value":"auddefault"}],"operator":"in","type":"string"}},{"attribute":{"id":"6870cfc582729abfafd29d0c","type":"page_variable"},"constraint":{"operands":[{"type":"constant","value":"UK"},{"type":"constant","value":"EU"},{"type":"constant","value":"FR"},{"type":"constant","value":"XBR"},{"type":"constant","value":"DE"},{"type":"constant","value":"NL"},{"type":"constant","value":"CH"},{"type":"constant","value":"AU"}],"operator":"in","type":"string"}},{"attribute":{"id":"689254c63d8b6aa8df033691","type":"page_variable"},"constraint":{"operands":[{"type":"constant","value":"category"}],"operator":"does not equal","type":"string"}}]},"page_vars":[{"id":"686bda9631a9bc8251208077"}]},{"_id":"68c15d24ade3bacdc717ba6c","date_filter":{"enabled":false,"from_date":null,"to_date":1755730799},"trigger":{"include_pages":[{"type":"any"}],"exclude_pages":null},"smart_trigger":null,"device_target":{"type":"any"},"frequency":"always","uses_personalization":true,"data":"","variables_target":{"conditions":[{"attribute":{"id":"687777bbd6d560fc90693886","type":"page_variable"},"constraint":{"operands":[{"type":"constant","value":"gbpdefault"},{"type":"constant","value":"frdefault"},{"type":"constant","value":"frdefault"},{"type":"constant","value":"xbrdefault"},{"type":"constant","value":"eurdefault"},{"type":"constant","value":"dmdefault"},{"type":"constant","value":"nldefault"},{"type":"constant","value":"chdefault"},{"type":"constant","value":"auddefault"}],"operator":"not in","type":"string"}},{"attribute":{"id":"6870cfc582729abfafd29d0c","type":"page_variable"},"constraint":{"operands":[{"type":"constant","value":"UK"},{"type":"constant","value":"EU"},{"type":"constant","value":"FR"},{"type":"constant","value":"XBR"},{"type":"constant","value":"DE"},{"type":"constant","value":"NL"},{"type":"constant","value":"CH"},{"type":"constant","value":"AU"}],"operator":"in","type":"string"}},{"attribute":{"id":"687777bbd6d560fc90693882","type":"page_variable"},"constraint":{"operands":[{"type":"constant","value":"category"}],"operator":"does not equal","type":"string"}}]},"page_vars":[{"id":"686bda9631a9bc8251208077"}]},{"_id":"691252145672b96383dbac6d","date_filter":{"enabled":false,"from_date":null,"to_date":1755730799},"trigger":{"include_pages":[{"type":"any"}],"exclude_pages":[{"url":"?currentPageNum=","type":"contains"}]},"smart_trigger":null,"device_target":{"type":"any"},"frequency":"only_once","uses_personalization":true,"data":"","variables_target":{"conditions":[{"attribute":{"id":"687777bbd6d560fc90693882","type":"page_variable"},"constraint":{"operands":[{"type":"constant","value":"Homepage"},{"type":"constant","value":"homepage"},{"type":"constant","value":"category"},{"type":"constant","value":"product"}],"operator":"in","type":"string"}},{"attribute":{"id":"6870cfc582729abfafd29d0c","type":"page_variable"},"constraint":{"operands":[{"type":"constant","value":"US"}],"operator":"equals","type":"string"}}]},"page_vars":[]},{"_id":"69235bd9ade5a94d1ab9cb4c","date_filter":{"enabled":false,"from_date":null,"to_date":1755730799},"trigger":{"include_pages":[{"type":"any"}],"exclude_pages":[{"url":"?currentPageNum=","type":"contains"}]},"smart_trigger":null,"device_target":{"type":"any"},"frequency":"only_once","uses_personalization":true,"data":"","variables_target":{"conditions":[{"attribute":{"id":"687777bbd6d560fc90693882","type":"page_variable"},"constraint":{"operands":[{"type":"constant","value":"product"}],"operator":"in","type":"string"}},{"attribute":{"id":"6870cfc582729abfafd29d0c","type":"page_variable"},"constraint":{"operands":[{"type":"constant","value":"US"}],"operator":"equals","type":"string"}}]},"page_vars":[]},{"_id":"6924c4fbebe486e2b50e54fe","date_filter":{"enabled":false,"from_date":null,"to_date":1755730799},"trigger":{"include_pages":[{"type":"any"}],"exclude_pages":null},"smart_trigger":null,"device_target":{"type":"any"},"frequency":"once_per_visit","uses_personalization":true,"data":"","variables_target":{"conditions":[{"attribute":{"id":"687777bbd6d560fc90693882","type":"page_variable"},"constraint":{"operands":[{"type":"constant","value":"basket"}],"operator":"equals","type":"string"}},{"attribute":{"id":"6870cfc582729abfafd29d0c","type":"page_variable"},"constraint":{"operands":[{"type":"constant","value":"US"}],"operator":"equals","type":"string"}},{"attribute":{"id":"687777bbd6d560fc90693886","type":"page_variable"},"constraint":{"operands":[{"type":"constant","value":"usddefault"}],"operator":"equals","type":"string"}}]},"page_vars":[]},{"_id":"69329c43a9cdb0ba473a5698","date_filter":{"enabled":false,"from_date":null,"to_date":null},"trigger":{"include_pages":[{"type":"any"}],"exclude_pages":[{"url":"?currentPageNum=","type":"contains"}]},"smart_trigger":null,"device_target":{"type":"any"},"frequency":"only_once","uses_personalization":true,"data":"","variables_target":{"conditions":[{"attribute":{"id":"687777bbd6d560fc90693882","type":"page_variable"},"constraint":{"operands":[{"type":"constant","value":"product"},{"type":"constant","value":"category"}],"operator":"in","type":"string"}},{"attribute":{"id":"687777bbd6d560fc90693886","type":"page_variable"},"constraint":{"operands":[{"type":"constant","value":"ukpm99"},{"type":"constant","value":"ukfb1c"},{"type":"constant","value":"uksc99"},{"type":"constant","value":"ukreact"},{"type":"constant","value":"ukdg99"},{"type":"constant","value":"ukcv39"},{"type":"constant","value":"fbreact"},{"type":"constant","value":"uknbam"},{"type":"constant","value":"uknbai"},{"type":"constant","value":"ukbn99"},{"type":"constant","value":"ukept1"},{"type":"constant","value":"ukdgcss"},{"type":"constant","value":"eufb20"},{"type":"constant","value":"eupm99"},{"type":"constant","value":"irefb2"},{"type":"constant","value":"irepx"},{"type":"constant","value":"irenb"},{"type":"constant","value":"eunbaw"},{"type":"constant","value":"iregdg"},{"type":"constant","value":"frpx99"},{"type":"constant","value":"frfb99"},{"type":"constant","value":"frnbai"},{"type":"constant","value":"frbr99"},{"type":"constant","value":"frnb99"},{"type":"constant","value":"frabs"},{"type":"constant","value":"depm99"},{"type":"constant","value":"defb99"},{"type":"constant","value":"degd99"},{"type":"constant","value":"desc99"},{"type":"constant","value":"deon1"},{"type":"constant","value":"deac1"},{"type":"constant","value":"denbai"},{"type":"constant","value":"debi99"},{"type":"constant","value":"nlfbdu"},{"type":"constant","value":"nlpmen"}],"operator":"in","type":"string"}},{"attribute":{"id":"6870cfc582729abfafd29d0c","type":"page_variable"},"constraint":{"operands":[{"type":"constant","value":"EU"},{"type":"constant","value":"FR"},{"type":"constant","value":"DE"},{"type":"constant","value":"NL"},{"type":"constant","value":"UK"}],"operator":"in","type":"string"}}]},"page_vars":[{"id":"686bda9631a9bc8251208077"},{"id":"6870cfc582729abfafd29d0c"}]},{"_id":"693c3a5bd4f5fe6c721c167c","date_filter":{"enabled":false,"from_date":null,"to_date":null},"trigger":{"include_pages":[{"type":"any"}],"exclude_pages":null},"smart_trigger":null,"device_target":{"type":"any"},"frequency":"always","uses_personalization":true,"data":"","variables_target":{"conditions":[{"attribute":{"id":"689254c63d8b6aa8df033691","type":"page_variable"},"constraint":{"operands":[{"type":"constant","value":"category"}],"operator":"equals","type":"string"}},{"attribute":{"id":"6870cfc682729abfafd29d10","type":"page_variable"},"constraint":{"operands":[{"type":"constant","value":"Mobile View"},{"type":"constant","value":"Desktop View"}],"operator":"in","type":"string"}}]},"page_vars":[{"id":"6870cfc682729abfafd29d10"},{"id":"686bda9631a9bc8251208077"},{"id":"687f5904f7fcebf3eaf07fef"}]},{"_id":"693c4b002d480c5c435edc75","date_filter":{"enabled":false,"from_date":null,"to_date":null},"trigger":{"include_pages":[{"type":"any"}],"exclude_pages":null},"smart_trigger":null,"device_target":{"type":"any"},"frequency":"always","uses_personalization":true,"data":"","variables_target":{"conditions":[{"attribute":{"id":"689254c63d8b6aa8df033691","type":"page_variable"},"constraint":{"operands":[{"type":"constant","value":"product"}],"operator":"equals","type":"string"}}]},"page_vars":[{"id":"6870cfc582729abfafd29d0c"},{"id":"687e48e9e79652fed545563f"},{"id":"686bda9631a9bc8251208077"},{"id":"6870cfc682729abfafd29d10"}]},{"_id":"693c4c81079b0eb6ee3aa925","date_filter":{"enabled":false,"from_date":null,"to_date":null},"trigger":{"include_pages":[{"type":"any"}],"exclude_pages":null},"smart_trigger":null,"device_target":{"type":"any"},"frequency":"always","uses_personalization":true,"data":"","variables_target":{"conditions":[{"attribute":{"id":"689254c63d8b6aa8df033691","type":"page_variable"},"constraint":{"operands":[{"type":"constant","value":"product"}],"operator":"equals","type":"string"}}]},"page_vars":[{"id":"6870cfc582729abfafd29d0c"},{"id":"687e48e9e79652fed545563f"},{"id":"686bda9631a9bc8251208077"},{"id":"6870cfc682729abfafd29d10"}]},{"_id":"693c5116a4ab3f17e2ac6194","date_filter":{"enabled":false,"from_date":null,"to_date":null},"trigger":{"include_pages":[{"type":"any"}],"exclude_pages":null},"smart_trigger":null,"device_target":{"type":"any"},"frequency":"always","uses_personalization":true,"data":"","variables_target":{"conditions":[{"attribute":{"id":"689254c63d8b6aa8df033691","type":"page_variable"},"constraint":{"operands":[{"type":"constant","value":"basket"}],"operator":"equals","type":"string"}}]},"page_vars":[{"id":"6870cfc582729abfafd29d0c"},{"id":"687f9ebffac7bd368375478a"},{"id":"6870cfc682729abfafd29d10"},{"id":"686bda9631a9bc8251208077"}]},{"_id":"694146309036c3f6a6bf5873","date_filter":{"enabled":false,"from_date":null,"to_date":1755730799},"trigger":{"include_pages":[{"type":"any"}],"exclude_pages":null},"smart_trigger":null,"device_target":{"type":"any"},"frequency":"once_per_visit","uses_personalization":true,"data":"","variables_target":{"conditions":[{"attribute":{"id":"687777bbd6d560fc90693882","type":"page_variable"},"constraint":{"operands":[{"type":"constant","value":"basket"}],"operator":"equals","type":"string"}},{"attribute":{"id":"6870cfc582729abfafd29d0c","type":"page_variable"},"constraint":{"operands":[{"type":"constant","value":"US"}],"operator":"equals","type":"string"}},{"attribute":{"id":"687777bbd6d560fc90693886","type":"page_variable"},"constraint":{"operands":[{"type":"constant","value":"usddefault"}],"operator":"equals","type":"string"}}]},"page_vars":[]},{"_id":"6953dc616dff8cd51d9a37ee","date_filter":{"enabled":false,"from_date":null,"to_date":1755730799},"trigger":{"include_pages":[{"type":"any"}],"exclude_pages":null},"smart_trigger":null,"device_target":{"type":"any"},"frequency":"always","uses_personalization":true,"data":"","variables_target":{"conditions":[{"attribute":{"id":"687777bbd6d560fc90693886","type":"page_variable"},"constraint":{"operands":[{"type":"constant","value":"usddefault"}],"operator":"in","type":"string"}},{"attribute":{"id":"6870cfc582729abfafd29d0c","type":"page_variable"},"constraint":{"operands":[{"type":"constant","value":"US"}],"operator":"in","type":"string"}},{"attribute":{"id":"687777bbd6d560fc90693882","type":"page_variable"},"constraint":{"operands":[{"type":"constant","value":"category"}],"operator":"does not equal","type":"string"}}]},"page_vars":[{"id":"686bda9631a9bc8251208077"}]},{"_id":"6978c3248d6d75a802a26f64","date_filter":{"enabled":false,"from_date":null,"to_date":1755730799},"trigger":{"include_pages":[{"type":"any"}],"exclude_pages":null},"smart_trigger":null,"device_target":{"type":"any"},"frequency":"only_once","uses_personalization":true,"data":"","variables_target":{"conditions":[{"attribute":{"id":"687777bbd6d560fc90693882","type":"page_variable"},"constraint":{"operands":[{"type":"constant","value":"basket"},{"type":"constant","value":"Homepage"}],"operator":"in","type":"string"}},{"attribute":{"id":"687777bbd6d560fc90693886","type":"page_variable"},"constraint":{"operands":[{"type":"constant","value":"gbpdefault"},{"type":"constant","value":"frdefault"},{"type":"constant","value":"frdefault"},{"type":"constant","value":"xbrdefault"},{"type":"constant","value":"eurdefault"},{"type":"constant","value":"dmdefault"},{"type":"constant","value":"nldefault"},{"type":"constant","value":"chdefault"},{"type":"constant","value":"caddefault"},{"type":"constant","value":"auddefault"}],"operator":"in","type":"string"}},{"attribute":{"id":"6870cfc582729abfafd29d0c","type":"page_variable"},"constraint":{"operands":[{"type":"constant","value":"UK"}],"operator":"in","type":"string"}}]},"page_vars":[{"id":"686bda9631a9bc8251208077"},{"id":"6870cfc582729abfafd29d0c"}]},{"_id":"69b1449cedc1cc4a07d8957e","date_filter":{"enabled":false,"from_date":null,"to_date":null},"trigger":{"include_pages":[{"type":"any"}],"exclude_pages":null},"smart_trigger":null,"device_target":{"type":"any"},"frequency":"always","uses_personalization":true,"data":"","variables_target":{"conditions":[{"attribute":{"id":"689254c63d8b6aa8df033691","type":"page_variable"},"constraint":{"operands":[{"type":"constant","value":"product"}],"operator":"contains","type":"string"}}]},"page_vars":[{"id":"686bda9631a9bc8251208077"}]},{"_id":"69bd1027315e83420ec6b8dd","date_filter":{"enabled":false,"from_date":null,"to_date":1755730799},"trigger":{"include_pages":[{"type":"any"}],"exclude_pages":null},"smart_trigger":null,"device_target":{"type":"any"},"frequency":"only_once","uses_personalization":true,"data":"","variables_target":{"conditions":[{"attribute":{"id":"687777bbd6d560fc90693882","type":"page_variable"},"constraint":{"operands":[{"type":"constant","value":"basket"},{"type":"constant","value":"Homepage"}],"operator":"in","type":"string"}},{"attribute":{"id":"687777bbd6d560fc90693886","type":"page_variable"},"constraint":{"operands":[{"type":"constant","value":"ukpm99"},{"type":"constant","value":"ukfb1c"},{"type":"constant","value":"uksc99"},{"type":"constant","value":"ukreact"},{"type":"constant","value":"ukdg99"},{"type":"constant","value":"ukcv39"},{"type":"constant","value":"fbreact"},{"type":"constant","value":"uknbam"},{"type":"constant","value":"uknbai"},{"type":"constant","value":"ukbn99"},{"type":"constant","value":"ukept1"},{"type":"constant","value":"ukdgcss"},{"type":"constant","value":"eufb20"},{"type":"constant","value":"eupm99"},{"type":"constant","value":"irefb2"},{"type":"constant","value":"irepx"},{"type":"constant","value":"irenb"},{"type":"constant","value":"eunbaw"},{"type":"constant","value":"iregdg"},{"type":"constant","value":"frpx99"},{"type":"constant","value":"frfb99"},{"type":"constant","value":"frnbai"},{"type":"constant","value":"frbr99"},{"type":"constant","value":"frnb99"},{"type":"constant","value":"frabs"},{"type":"constant","value":"depm99"},{"type":"constant","value":"defb99"},{"type":"constant","value":"degd99"},{"type":"constant","value":"desc99"},{"type":"constant","value":"deon1"},{"type":"constant","value":"deac1"},{"type":"constant","value":"denbai"},{"type":"constant","value":"debi99"},{"type":"constant","value":"nlfbdu"},{"type":"constant","value":"nlpmen"}],"operator":"in","type":"string"}},{"attribute":{"id":"6870cfc582729abfafd29d0c","type":"page_variable"},"constraint":{"operands":[{"type":"constant","value":"UK"}],"operator":"in","type":"string"}}]},"page_vars":[{"id":"686bda9631a9bc8251208077"}]},{"_id":"69e9e7b05e3914bc26bc532a","date_filter":{"enabled":false,"from_date":null,"to_date":1755730799},"trigger":{"include_pages":[{"type":"any"}],"exclude_pages":null},"smart_trigger":null,"device_target":{"type":"any"},"frequency":"only_once","uses_personalization":true,"data":"","variables_target":{"conditions":[{"attribute":{"id":"687777bbd6d560fc90693882","type":"page_variable"},"constraint":{"operands":[{"type":"constant","value":"basket"},{"type":"constant","value":"Homepage"}],"operator":"in","type":"string"}},{"attribute":{"id":"6870cfc582729abfafd29d0c","type":"page_variable"},"constraint":{"operands":[{"type":"constant","value":"US"}],"operator":"in","type":"string"}}]},"page_vars":[{"id":"686bda9631a9bc8251208077"}]},{"_id":"69f211a739ce20f58e3c25df","date_filter":{"enabled":false,"from_date":null,"to_date":null},"trigger":{"include_pages":[{"type":"any"}],"exclude_pages":null},"smart_trigger":null,"device_target":{"type":"any"},"frequency":"always","uses_personalization":true,"data":"","variables_target":{"conditions":[{"attribute":{"id":"6870cfc582729abfafd29d0c","type":"page_variable"},"constraint":{"operands":[{"type":"constant","value":"US"}],"operator":"equals","type":"string"}},{"attribute":{"id":"689254c63d8b6aa8df033691","type":"page_variable"},"constraint":{"operands":[{"type":"constant","value":"checkout"}],"operator":"does not contain","type":"string"}}]},"page_vars":[{"id":"686bda9631a9bc8251208077"}]},{"_id":"6a103852bc82a239b6352681","date_filter":{"enabled":false,"from_date":null,"to_date":null},"trigger":{"include_pages":[{"url":"sms-signup","type":"contains"}],"exclude_pages":null},"smart_trigger":null,"device_target":{"type":"any"},"frequency":"always","uses_personalization":true,"data":"","variables_target":{"conditions":[{"attribute":{"id":"6870cfc582729abfafd29d0c","type":"page_variable"},"constraint":{"operands":[{"type":"constant","value":"UK"}],"operator":"equals","type":"string"}}]},"page_vars":[{"id":"6870cfc582729abfafd29d0c"}]},{"_id":"6a1d9614581d0dd7d87ac918","date_filter":{"enabled":false,"from_date":null,"to_date":null},"trigger":{"include_pages":[{"type":"any"}],"exclude_pages":null},"smart_trigger":null,"device_target":{"type":"any"},"frequency":"always","uses_personalization":true,"data":"","variables_target":null,"page_vars":[]},{"_id":"6a3cf33d28b27115967c0ef0","date_filter":{"enabled":false,"from_date":null,"to_date":1755730799},"trigger":{"include_pages":[{"type":"any"}],"exclude_pages":[{"url":"?currentPageNum=","type":"contains"}]},"smart_trigger":null,"device_target":{"type":"any"},"frequency":"only_once","uses_personalization":true,"data":"","variables_target":{"conditions":[{"attribute":{"id":"687777bbd6d560fc90693882","type":"page_variable"},"constraint":{"operands":[{"type":"constant","value":"Homepage"},{"type":"constant","value":"homepage"},{"type":"constant","value":"category"},{"type":"constant","value":"product"}],"operator":"in","type":"string"}},{"attribute":{"id":"6870cfc582729abfafd29d0c","type":"page_variable"},"constraint":{"operands":[{"type":"constant","value":"CA"},{"type":"constant","value":"AU"}],"operator":"in","type":"string"}},{"attribute":{"id":"686bda9631a9bc8251208077","type":"page_variable"},"constraint":{"operands":[{"type":"constant","value":"fr_CA"}],"operator":"does not equal","type":"string"}}]},"page_vars":[]},{"_id":"6a3cf34f681009f8fd4887d6","date_filter":{"enabled":false,"from_date":null,"to_date":1755730799},"trigger":{"include_pages":[{"type":"any"}],"exclude_pages":null},"smart_trigger":null,"device_target":{"type":"any"},"frequency":"once_per_visit","uses_personalization":true,"data":"","variables_target":{"conditions":[{"attribute":{"id":"687777bbd6d560fc90693882","type":"page_variable"},"constraint":{"operands":[{"type":"constant","value":"basket"}],"operator":"equals","type":"string"}},{"attribute":{"id":"6870cfc582729abfafd29d0c","type":"page_variable"},"constraint":{"operands":[{"type":"constant","value":"CA"},{"type":"constant","value":"AU"}],"operator":"in","type":"string"}},{"attribute":{"id":"687777bbd6d560fc90693886","type":"page_variable"},"constraint":{"operands":[{"type":"constant","value":"caddefault"},{"type":"constant","value":"auddefault"}],"operator":"in","type":"string"}},{"attribute":{"id":"686bda9631a9bc8251208077","type":"page_variable"},"constraint":{"operands":[{"type":"constant","value":"fr_CA"}],"operator":"does not equal","type":"string"}}]},"page_vars":[]},{"_id":"6a3cf35cfb691956b275ed6d","date_filter":{"enabled":false,"from_date":null,"to_date":1755730799},"trigger":{"include_pages":[{"type":"any"}],"exclude_pages":[{"url":"?currentPageNum=","type":"contains"}]},"smart_trigger":null,"device_target":{"type":"any"},"frequency":"only_once","uses_personalization":true,"data":"","variables_target":{"conditions":[{"attribute":{"id":"687777bbd6d560fc90693882","type":"page_variable"},"constraint":{"operands":[{"type":"constant","value":"product"}],"operator":"in","type":"string"}},{"attribute":{"id":"6870cfc582729abfafd29d0c","type":"page_variable"},"constraint":{"operands":[{"type":"constant","value":"CA"},{"type":"constant","value":"AU"}],"operator":"in","type":"string"}},{"attribute":{"id":"686bda9631a9bc8251208077","type":"page_variable"},"constraint":{"operands":[{"type":"constant","value":"fr_CA"}],"operator":"does not equal","type":"string"}}]},"page_vars":[]},{"_id":"6a60ca994b51cde2943b7290","date_filter":{"enabled":false,"from_date":null,"to_date":null},"trigger":{"include_pages":[{"type":"any"}],"exclude_pages":null},"smart_trigger":null,"device_target":{"type":"any"},"frequency":"always","uses_personalization":true,"data":"","variables_target":{"conditions":[{"attribute":{"id":"687777bbd6d560fc90693882","type":"page_variable"},"constraint":{"operands":[{"type":"constant","value":"product"}],"operator":"in","type":"string"}},{"attribute":{"id":"6870cfc582729abfafd29d0c","type":"page_variable"},"constraint":{"operands":[{"type":"constant","value":"EU"},{"type":"constant","value":"IT"},{"type":"constant","value":"ES"},{"type":"constant","value":"FR"}],"operator":"in","type":"string"}}]},"page_vars":[{"id":"687e48e9e79652fed545563f"}]},{"_id":"6a82c9b40cf84b05bfa1a8cd","date_filter":{"enabled":false,"from_date":null,"to_date":null},"trigger":{"include_pages":[{"type":"any"}],"exclude_pages":null},"smart_trigger":null,"device_target":{"type":"any"},"frequency":"always","uses_personalization":true,"data":"","variables_target":{"conditions":[{"attribute":{"id":"689254c63d8b6aa8df033691","type":"page_variable"},"constraint":{"operands":[{"type":"constant","value":"category"}],"operator":"equals","type":"string"}},{"attribute":{"id":"68c91ba91c00bfc935319bd9","type":"page_variable"},"constraint":{"operands":[{"type":"constant","value":"bestsellers"}],"operator":"does not equal","type":"string"}}]},"page_vars":[{"id":"687f5904f7fcebf3eaf07fef"},{"id":"686bda9631a9bc8251208077"},{"id":"687777bbd6d560fc90693886"}]},{"_id":"6a82d44a0cf84b05bfa1b8d2","date_filter":{"enabled":false,"from_date":null,"to_date":null},"trigger":{"include_pages":[{"type":"any"}],"exclude_pages":null},"smart_trigger":null,"device_target":{"type":"any"},"frequency":"always","uses_personalization":true,"data":"","variables_target":{"conditions":[{"attribute":{"id":"687777bbd6d560fc90693882","type":"page_variable"},"constraint":{"operands":[{"type":"constant","value":"product"}],"operator":"equals","type":"string"}},{"attribute":{"id":"6870cfc582729abfafd29d0c","type":"page_variable"},"constraint":{"operands":[{"type":"constant","value":"US"},{"type":"constant","value":"DE"},{"type":"constant","value":"EU"},{"type":"constant","value":"FR"},{"type":"constant","value":"CA"},{"type":"constant","value":"AU"},{"type":"constant","value":"CH"},{"type":"constant","value":"NL"},{"type":"constant","value":"XBR"},{"type":"constant","value":"UK"}],"operator":"in","type":"string"}}]},"page_vars":[{"id":"687f5904f7fcebf3eaf07fef"},{"id":"686bda9631a9bc8251208077"},{"id":"687777bbd6d560fc90693886"},{"id":"687e48e9e79652fed545563f"}]}],"experiments":[{"_id":"6a461cd6f08798deafd57a4b","date_filter":{"enabled":false,"from_date":null,"to_date":1784933999},"trigger":{"include_pages":[{"url":"home?newHPTest","type":"contains"}],"exclude_pages":null},"trigger_event":{"type":"page_load"},"device_target":{"type":"any"},"frequency":"always","variables_target":{"conditions":[{"attribute":{"id":"689254c63d8b6aa8df033691","type":"page_variable"},"constraint":{"operands":[{"type":"constant","value":"Homepage"}],"operator":"equals","type":"string"}},{"attribute":{"id":"6870cfc582729abfafd29d0c","type":"page_variable"},"constraint":{"operands":[{"type":"constant","value":"UK"},{"type":"constant","value":"US"}],"operator":"in","type":"string"}},{"attribute":{"id":"6870cfc682729abfafd29d10","type":"page_variable"},"constraint":{"operands":[{"type":"constant","value":"Tablet"}],"operator":"does not contain","type":"string"}}]},"page_vars":[]},{"_id":"6a5f2b7a8a8218d0e3bc3390","date_filter":{"enabled":false,"from_date":null,"to_date":null},"trigger":{"include_pages":[{"type":"any"}],"exclude_pages":null},"trigger_event":{"type":"page_load"},"device_target":{"type":"any"},"frequency":"always","variables_target":{"conditions":[{"attribute":{"id":"6870cfc582729abfafd29d0c","type":"page_variable"},"constraint":{"operands":[{"type":"constant","value":"AU"}],"operator":"in","type":"string"}},{"attribute":{"id":"687777bbd6d560fc90693886","type":"page_variable"},"constraint":{"operands":[{"type":"constant","value":"auddefault"},{"type":"constant","value":"augb"}],"operator":"in","type":"string"}}]},"page_vars":[]},{"_id":"6a6cb68241c17b91ab6435d6","date_filter":{"enabled":false,"from_date":null,"to_date":null},"trigger":{"include_pages":[{"url":"/uk/","type":"contains"}],"exclude_pages":null},"trigger_event":{"type":"page_load"},"device_target":{"type":"any"},"frequency":"always","variables_target":{"conditions":[{"attribute":{"id":"689254c63d8b6aa8df033691","type":"page_variable"},"constraint":{"operands":[{"type":"constant","value":"product"}],"operator":"in","type":"string"}},{"attribute":{"id":"69b7e0c12a7591e216cdb2de","type":"page_variable"},"constraint":{"operands":[{"type":"constant","value":"UK"}],"operator":"in","type":"string"}}]},"page_vars":[]},{"_id":"6a7987d2203f799bf1935dee","date_filter":{"enabled":false,"from_date":null,"to_date":null},"trigger":{"include_pages":[{"url":"/uk/","type":"contains"},{"url":"/us/","type":"contains"}],"exclude_pages":null},"trigger_event":{"type":"page_load"},"device_target":{"type":"any"},"frequency":"always","variables_target":{"conditions":[{"attribute":{"id":"689254c63d8b6aa8df033691","type":"page_variable"},"constraint":{"operands":[{"type":"constant","value":"Homepage"}],"operator":"equals","type":"string"}},{"attribute":{"id":"69b7e0c12a7591e216cdb2de","type":"page_variable"},"constraint":{"operands":[{"type":"constant","value":"UK"},{"type":"constant","value":"US"}],"operator":"in","type":"string"}}]},"page_vars":[]},{"_id":"6a7996e2819ad3b0102a4f8a","date_filter":{"enabled":false,"from_date":null,"to_date":null},"trigger":{"include_pages":[{"url":"/us/","type":"contains"}],"exclude_pages":null},"trigger_event":{"type":"page_load"},"device_target":{"type":"any"},"frequency":"always","variables_target":{"conditions":[{"attribute":{"id":"689254c63d8b6aa8df033691","type":"page_variable"},"constraint":{"operands":[{"type":"constant","value":"category"}],"operator":"equals","type":"string"}},{"attribute":{"id":"6870cfc582729abfafd29d0c","type":"page_variable"},"constraint":{"operands":[{"type":"constant","value":"US"}],"operator":"equals","type":"string"}},{"attribute":{"id":"6870cfc682729abfafd29d10","type":"page_variable"},"constraint":{"operands":[{"type":"constant","value":"Mobile"}],"operator":"contains","type":"string"}}]},"page_vars":[]},{"_id":"6a7ed835f74916aeb04921ff","date_filter":{"enabled":false,"from_date":null,"to_date":null},"trigger":{"include_pages":[{"url":"/uk/","type":"contains"}],"exclude_pages":null},"trigger_event":{"type":"page_load"},"device_target":{"type":"any"},"frequency":"always","variables_target":{"conditions":[{"attribute":{"id":"689254c63d8b6aa8df033691","type":"page_variable"},"constraint":{"operands":[{"type":"constant","value":"product"}],"operator":"equals","type":"string"}},{"attribute":{"id":"6870cfc682729abfafd29d10","type":"page_variable"},"constraint":{"operands":[{"type":"constant","value":"Mobile"}],"operator":"contains","type":"string"}},{"attribute":{"id":"6870cfc582729abfafd29d0c","type":"page_variable"},"constraint":{"operands":[{"type":"constant","value":"UK"}],"operator":"equals","type":"string"}}]},"page_vars":[]},{"_id":"6a82cff0b69affcd5d614d88","date_filter":{"enabled":false,"from_date":null,"to_date":null},"trigger":{"include_pages":[{"type":"any"}],"exclude_pages":null},"trigger_event":{"type":"page_load"},"device_target":{"type":"any"},"frequency":"always","variables_target":{"conditions":[{"attribute":{"id":"689254c63d8b6aa8df033691","type":"page_variable"},"constraint":{"operands":[{"type":"constant","value":"basket"}],"operator":"equals","type":"string"}},{"attribute":{"id":"6870cfc582729abfafd29d0c","type":"page_variable"},"constraint":{"operands":[{"type":"constant","value":"UK"},{"type":"constant","value":"US"}],"operator":"in","type":"string"}}]},"page_vars":[]}],"constantManagedTags":[{"uses_overlay":false,"type":"js","parametrized_definition":"(function() {\n    /*\n     jQuery v1.9.1 (c) 2005, 2012\n     jQuery Foundation, Inc. jquery.org/license.\n    */\n    var g = /\\[object (Boolean|Number|String|Function|Array|Date|RegExp)\\]/;\n\n    function h(a) {\n        return null == a ? String(a) : (a = g.exec(Object.prototype.toString.call(Object(a)))) ? a[1].toLowerCase() : \"object\"\n    }\n\n    function k(a, b) {\n        return Object.prototype.hasOwnProperty.call(Object(a), b)\n    }\n\n    function m(a) {\n        if (!a || \"object\" != h(a) || a.nodeType || a == a.window) return !1;\n        try {\n            if (a.constructor \u0026\u0026 !k(a, \"constructor\") \u0026\u0026 !k(a.constructor.prototype, \"isPrototypeOf\")) return !1\n        } catch (b) {\n            return !1\n        }\n        for (var c in a);\n        return void 0 === c || k(a, c)\n    };\n    /*\n     Copyright 2012 Google Inc. All rights reserved. */\n    function n(a, b, c) {\n        this.b = a;\n        this.f = b || function() {};\n        this.d = !1;\n        this.a = {};\n        this.c = [];\n        this.e = p(this);\n        r(this, a, !c);\n        var d = a.push,\n            e = this;\n        a.push = function() {\n            var b = [].slice.call(arguments, 0),\n                c = d.apply(a, b);\n            r(e, b);\n            return c\n        }\n    }\n    window.DataLayerHelper = n;\n    n.prototype.get = function(a) {\n        var b = this.a;\n        a = a.split(\".\");\n        for (var c = 0; c \u003c a.length; c++) {\n            if (void 0 === b[a[c]]) return;\n            b = b[a[c]]\n        }\n        return b\n    };\n    n.prototype.flatten = function() {\n        this.b.splice(0, this.b.length);\n        this.b[0] = {};\n        s(this.a, this.b[0])\n    };\n\n    function r(a, b, c) {\n        for (a.c.push.apply(a.c, b); !1 === a.d \u0026\u0026 0 \u003c a.c.length;) {\n            b = a.c.shift();\n            if (\"array\" == h(b)) a: {\n                var d = b,\n                    e = a.a;\n                if (\"string\" == h(d[0])) {\n                    for (var f = d[0].split(\".\"), u = f.pop(), d = d.slice(1), l = 0; l \u003c f.length; l++) {\n                        if (void 0 === e[f[l]]) break a;\n                        e = e[f[l]]\n                    }\n                    try {\n                        e[u].apply(e, d)\n                    } catch (v) {}\n                }\n            }\n            else if (\"function\" == typeof b) try {\n                    b.call(a.e)\n                } catch (w) {} else if (m(b))\n                    for (var q in b) s(t(q, b[q]), a.a);\n                else continue;\n            c || (a.d = !0, a.f(a.a, b), a.d = !1)\n        }\n    }\n\n    function p(a) {\n        return {\n            set: function(b, c) {\n                s(t(b, c), a.a)\n            },\n            get: function(b) {\n                return a.get(b)\n            }\n        }\n    }\n\n    function t(a, b) {\n        for (var c = {}, d = c, e = a.split(\".\"), f = 0; f \u003c e.length - 1; f++) d = d[e[f]] = {};\n        d[e[e.length - 1]] = b;\n        return c\n    }\n\n    function s(a, b) {\n        for (var c in a)\n            if (k(a, c)) {\n                var d = a[c];\n                \"array\" == h(d) ? (\"array\" == h(b[c]) || (b[c] = []), s(d, b[c])) : m(d) ? (m(b[c]) || (b[c] = {}), s(d, b[c])) : b[c] = d\n            }\n    };\n})();\n\nfunction process(model, m) {\n\tif (m.namespace == \"exponea\") {\n\t\t\n\t\t/*\n\t\t*\tMODIFY EVENT PROPERTIES\n\t\t*/\n\t\t\n\t\t// switch(m.event_name){\n\t\t// \tcase \"view_item\":\n\t\t// \t\tm.event_properties.price = parseFloat(price.split(\"€\")[0]);\n\t\t// \t\tbreak;\n\t\t// \tdefault:\n\t\t// \t\tbreak;\n\t\t// }\n\t\t\n\t\texponea.track(m.event_name,m.event_properties);\n\t}\n}\n\nnew DataLayerHelper(dataLayer, process, true);","trigger":{"include_pages":[{"type":"any"}],"exclude_pages":null},"_id":"68a5a9e5b22980546c5c175a"},{"uses_overlay":false,"type":"js","parametrized_definition":"(() =\u003e {\n  \"use strict\";\n\n  const RUN_FLAG = \"__CT_USP_STRIP_V3_ALL_MARKETS__\";\n  if (window[RUN_FLAG]) return;\n  window[RUN_FLAG] = true;\n\n  // ---------------- Poll helper ----------------\n  function poll(selector, cb, timeout, max) {\n    max--;\n    if (document.querySelector(selector) \u0026\u0026 typeof window.utag_data === \"object\") {\n      cb();\n    } else if (max \u003e 0) {\n      setTimeout(function () { poll(selector, cb, timeout, max); }, timeout);\n    }\n  }\n\n  // ---------------- Shared helpers ----------------\n  const isPDP = () =\u003e (window.utag_data?.page?.type || \"\").toLowerCase() === \"product\";\n  const isMobileBP = () =\u003e {\n  const ut = (window.utag_data?.page?.responsive_design_type || \"\").toLowerCase();\n\n\t  // If CT is flagging a specific view, treat mobile/tablet as \"mobile treatment\"\n\t  if (ut) {\n\t    if (ut === \"mobile view\" || ut === \"tablet view\") return true;\n\t    return false;\n\t  }\n\t\n\t  // Fallback: viewport width breakpoint (1024px and below)\n\t  return window.matchMedia?.(\"(max-width: 1024px)\")?.matches || false;\n\t};\n\n  const prefersReduced = () =\u003e\n    window.matchMedia?.(\"(prefers-reduced-motion: reduce)\")?.matches;\n\n  const waitFor = (sel, { timeout = 10000 } = {}) =\u003e\n    new Promise((resolve, reject) =\u003e {\n      const hit = document.querySelector(sel);\n      if (hit) return resolve(hit);\n      const mo = new MutationObserver(() =\u003e {\n        const found = document.querySelector(sel);\n        if (found) {\n          mo.disconnect();\n          resolve(found);\n        }\n      });\n      mo.observe(document.documentElement, { childList: true, subtree: true });\n      setTimeout(() =\u003e {\n        mo.disconnect();\n        reject(new Error(\"waitFor timeout: \" + sel));\n      }, timeout);\n    });\n\n  // ==================================================\n  // UK / US module (variation-based)\n  // ==================================================\n  const module365 = {\n    variationId: 3, // zero-based index into the content buckets\n\n    variations: {\n      uk: {\n        def: [\n          [\n            { copy: 'Designed To Impress, \u003cspan class=\"bold\"\u003eBuilt To Last\u003c/span\u003e', image: 'flag' },\n            { copy: 'Shop Confidently With \u003cspan class=\"bold\"\u003e6 Months To Decide\u003c/span\u003e', image: 'medal' },\n            { copy: '\u003cspan class=\"bold\"\u003eAward Winning\u003c/span\u003e Customer Service, Here For You', image: 'phone' }\n          ],\n          [\n            { copy: 'Timeless \u003cspan class=\"bold\"\u003eBritish Style\u003c/span\u003e, Tailored To You', image: 'flag' },\n            { copy: 'Quality Products \u003cspan class=\"bold\"\u003eMade To Last\u003c/span\u003e', image: 'medal' },\n            { copy: '\u003cspan class=\"bold\"\u003eAward Winning\u003c/span\u003e Customer Service, Here For You', image: 'phone' }\n          ],\n          [\n            { copy: 'Timeless \u003cspan class=\"bold\"\u003eBritish Style\u003c/span\u003e, Made to Last', image: 'flag' },\n            { copy: '\u003cspan class=\"bold\"\u003eEasy \u003cspan class=\"bold\"\u003e6 Month Returns\u003c/span\u003e, No Questions Asked.', image: 'medal' },\n            { copy: 'Trusted \u003cspan class=\"bold\"\u003eBritish Heritage\u003c/span\u003e Since 1986', image: 'flag' }\n          ],\n          [\n            { copy: 'Classic \u003cspan class=\"bold\"\u003eBritish Design\u003c/span\u003e. Timeless Quality.', image: 'flag' },\n            { copy: 'Easy \u003cspan class=\"bold\"\u003e6 Month Returns\u003c/span\u003e, No Questions Asked.', image: 'medal' },\n            { copy: '\u003cspan class=\"bold\"\u003eAward Winning\u003c/span\u003e Customer Service, Here For You', image: 'phone' }\n          ],\n          [\n            { copy: 'Timeless \u003cspan class=\"bold\"\u003eBritish Style\u003c/span\u003e, Tailored To You', image: 'flag' },\n            { copy: '\u003cspan class=\"bold\"\u003eSize and Fit\u003c/span\u003e promise with \u003cspan class=\"bold\"\u003e6-month\u003c/span\u003e returns window', image: 'medal' },\n            { copy: '\u003cspan class=\"bold\"\u003eAward Winning\u003c/span\u003e Customer Service, Here For You', image: 'phone' }\n          ]\n        ],\n        acq: [\n          [\n            { copy: '\u003cspan class=\"bold\"\u003eFree Shipping\u003c/span\u003e On Orders Above £50', image: 'shipping' },\n            { copy: 'Designed To Impress, \u003cspan class=\"bold\"\u003eBuilt To Last\u003c/span\u003e', image: 'tape' },\n            { copy: 'Shop Confidently With \u003cspan class=\"bold\"\u003e6 Months To Decide\u003c/span\u003e', image: 'medal' }\n          ],\n          [\n            { copy: '\u003cspan class=\"bold\"\u003eFree Delivery\u003c/span\u003e On Orders Above £50', image: 'shipping' },\n            { copy: 'Timeless \u003cspan class=\"bold\"\u003eBritish Style\u003c/span\u003e, Tailored To You', image: 'flag' },\n            { copy: 'Easy \u003cspan class=\"bold\"\u003e6 Month Returns\u003c/span\u003e, No Questions Asked.', image: 'medal' }\n          ],\n          [\n            { copy: 'Enjoy \u003cspan class=\"bold\"\u003eFree Delivery\u003c/span\u003e When You Spend £50', image: 'shipping' },\n            { copy: 'Timeless \u003cspan class=\"bold\"\u003eBritish Style\u003c/span\u003e, Made to Last', image: 'flag' },\n            { copy: 'Easy \u003cspan class=\"bold\"\u003e6 Month Returns\u003c/span\u003e, No Questions Asked.', image: 'medal' }\n          ],\n          [\n            { copy: '\u003cspan class=\"bold\"\u003eFree UK Delivery\u003c/span\u003e for Orders Over £50', image: 'shipping' },\n            { copy: 'Designed To Impress, \u003cspan class=\"bold\"\u003eBuilt To Last\u003c/span\u003e', image: 'tape' },\n            { copy: 'Easy \u003cspan class=\"bold\"\u003e6 Month Returns\u003c/span\u003e, No Questions Asked.', image: 'medal' }\n          ],\n          [\n            { copy: '\u003cspan class=\"bold\"\u003eFree UK Delivery\u003c/span\u003e for Orders Over £50', image: 'shipping' },\n            { copy: 'Quality British Design, \u003cspan class=\"bold\"\u003eMade to Last\u003c/span\u003e', image: 'flag' },\n            { copy: '\u003cspan class=\"bold\"\u003eSize and Fit\u003c/span\u003e promise with \u003cspan class=\"bold\"\u003e6-month\u003c/span\u003e returns window', image: 'medal' }\n          ]\n        ]\n      },\n      us: {\n        def: [\n          [\n            { copy: 'Timeless \u003cspan class=\"bold\"\u003eBritish Style\u003c/span\u003e, Built to Last', image: 'flag' },\n            { copy: 'Shop Confidently With \u003cspan class=\"bold\"\u003e6 Months To Decide\u003c/span\u003e', image: 'medal' },\n            { copy: '\u003cspan class=\"bold\"\u003eAward Winning\u003c/span\u003e Customer Service, Here For You', image: 'phone' }\n          ],\n          [\n            { copy: 'Timeless \u003cspan class=\"bold\"\u003eBritish Style\u003c/span\u003e, Tailored To You', image: 'flag' },\n            { copy: 'Quality Products \u003cspan class=\"bold\"\u003eMade To Last\u003c/span\u003e', image: 'medal' },\n            { copy: '\u003cspan class=\"bold\"\u003eAward Winning\u003c/span\u003e Customer Service, Here For You', image: 'phone' }\n          ],\n          [\n            { copy: 'Timeless \u003cspan class=\"bold\"\u003eBritish Style\u003c/span\u003e, Made to Last', image: 'medal' },\n             { copy: 'Easy \u003cspan class=\"bold\"\u003e6 Month Returns\u003c/span\u003e, No Questions Asked.', image: 'medal' },\n            { copy: 'Trusted British Heritage \u003cspan class=\"bold\"\u003eSince 1986\u003c/span\u003e', image: 'flag' }\n          ],\n          [\n            { copy: '\u003cspan class=\"bold\"\u003eClassic British Design\u003c/span\u003e. Timeless Quality.', image: 'flag' },\n            { copy: 'Easy \u003cspan class=\"bold\"\u003e6 Month Returns\u003c/span\u003e, No Questions Asked.', image: 'medal' },\n            { copy: '\u003cspan class=\"bold\"\u003eAward Winning\u003c/span\u003e Customer Service, Here For You', image: 'phone' }\n          ],\n          [\n            { copy: 'Timeless \u003cspan class=\"bold\"\u003eBritish Style\u003c/span\u003e,Tailored To You', image: 'flag' },\n            { copy: '\u003cspan class=\"bold\"\u003eSize and Fit\u003c/span\u003e promise with \u003cspan class=\"bold\"\u003e6-month\u003c/span\u003e returns window', image: 'medal' },\n            { copy: '\u003cspan class=\"bold\"\u003eAward Winning\u003c/span\u003e Customer Service, Here For You', image: 'phone' }\n          ]\n        ],\n        acq: [\n          [\n            { copy: '\u003cspan class=\"bold\"\u003eFree Standard Shipping\u003c/span\u003e On All Orders', image: 'shipping' },\n            { copy: 'Timeless \u003cspan class=\"bold\"\u003eBritish Style\u003c/span\u003e, Built to Last', image: 'flag' },\n            { copy: 'Shop Confidently With \u003cspan class=\"bold\"\u003e6 Months To Decide\u003c/span\u003e', image: 'medal' }\n          ],\n          [\n            { copy: '\u003cspan class=\"bold\"\u003eFree Shipping\u003c/span\u003e For All Orders', image: 'shipping' },\n            { copy: 'Timeless \u003cspan class=\"bold\"\u003eBritish Style\u003c/span\u003e, Tailored To You', image: 'flag' },\n            { copy: 'Easy \u003cspan class=\"bold\"\u003e6 Month Returns\u003c/span\u003e, No Questions Asked.', image: 'medal' }\n          ],\n          [\n            { copy: 'Enjoy \u003cspan class=\"bold\"\u003eFree Shipping\u003c/span\u003e On All Orders', image: 'shipping' },\n            { copy: 'Timeless \u003cspan class=\"bold\"\u003eBritish Style\u003c/span\u003e, Made to Last', image: 'flag' },\n            { copy: 'Easy \u003cspan class=\"bold\"\u003e6 Month Returns\u003c/span\u003e, No Questions Asked.', image: 'medal' }\n          ],\n          [\n            { copy: '\u003cspan class=\"bold\"\u003eFree Shipping\u003c/span\u003e On All Orders', image: 'shipping' },\n            { copy: 'Designed To Impress, \u003cspan class=\"bold\"\u003eBuilt To Last\u003c/span\u003e', image: 'flag' },\n            { copy: 'Easy \u003cspan class=\"bold\"\u003e6 Month Returns\u003c/span\u003e, No Questions Asked.', image: 'medal' }\n          ],\n          [\n            { copy: '\u003cspan class=\"bold\"\u003eFree Shipping\u003c/span\u003e For All Orders', image: 'shipping' },\n            { copy: 'Quality British Design, \u003cspan class=\"bold\"\u003eMade to Last\u003c/span\u003e', image: 'flag' },\n            { copy: '\u003cspan class=\"bold\"\u003eSize and Fit\u003c/span\u003e promise with \u003cspan class=\"bold\"\u003e6-month\u003c/span\u003e returns window', image: 'medal' }\n          ]\n        ]\n      }\n    },\n\n    buildUSPs: function () {\n      if (document.getElementById(\"speero-365-usp\")) return false;\n\n      const ud = window.utag_data || {};\n      const g = (ud.global || {});\n      const p = (ud.page || {});\n      const countryRaw = g.sfcc_country;     // 'UK', 'US'\n      const campaignSite = g.campaign_site;  // site key\n      const pageType = p.type || '';         // 'product' for PDP\n\n      if (String(pageType).toLowerCase() !== 'product') return false;\n      if (!countryRaw || !['uk', 'us'].includes(String(countryRaw).toLowerCase())) return false;\n      if (!campaignSite) return false;\n\n      const defaultCampaignSites = [\n        'usddefault','gbpdefault','dmdefault','ukgob','auddefault','usgob','xbrdefault','frdefault','eurdefault','caddefault',\n        'gegob','nldefault','shareuk1','uscjdl','chdefault','augb','usbrt1','eugob','usafcj','ukbng','xbrgb','affide1',\n        'debng','shareau1','sharefr1','eushare1','xbraff1','pinterest','auctbf','devip'\n      ];\n\n      const isDefault = defaultCampaignSites.includes(String(campaignSite));\n      const acqKey = isDefault ? 'def' : 'acq';\n\n      const countryKey = String(countryRaw).toLowerCase();\n      const countrySet = this.variations \u0026\u0026 this.variations[countryKey];\n\n      if (!countrySet \u0026\u0026 !(this.variations \u0026\u0026 this.variations.uk)) return false;\n\n      const useSet = countrySet || this.variations.uk;\n      const buckets = useSet[acqKey];\n      if (!Array.isArray(buckets)) return false;\n\n      const idx = (this.variationId | 0);\n      const uspContent = buckets[idx];\n      if (!Array.isArray(uspContent)) return false;\n\n      const target = document.querySelector('.pdp-main__more-info');\n      if (!target) return false;\n\n      target.insertAdjacentHTML('beforebegin', `\n        \u003cdiv id=\"speero-365-usp\" class=\"d-flex flex-direction-column\"\n             style=\"font-size:1.6rem;font-family:'Futura'; gap:12px; margin-top:20px; color:#373737; width:100%\"\u003e\n          ${uspContent.map(c =\u003e `\n            \u003cdiv class=\"d-flex\" style=\"gap:8px; align-items:center\"\u003e\n              \u003cimg src=\"/on/demandware.static/-/Library-Sites-CTShirtsSharedLibrary/default/images/usp-icons/${c.image}-icon.svg\"\n                   style=\"width:24px; height:24px\" alt=\"\"\u003e\n              \u003cspan\u003e${c.copy}\u003c/span\u003e\n            \u003c/div\u003e\n          `).join('')}\n        \u003c/div\u003e\n      `);\n\n      return true;\n    }\n  };\n\n  // ==================================================\n  // Non-UK/US module (USP_BY_LANG)\n  // ==================================================\n  const USP_BY_LANG = {\n    \"de_DE\": [\n      { img: \"tape\",  text: 'Langlebiges Design, \u003cspan class=\"bold\"\u003edas begeistert\u003c/span\u003e' },\n      { img: \"medal\", text: 'Shoppen Sie sorglos mit \u003cspan class=\"bold\"\u003e6 Monaten Bedenkzeit\u003c/span\u003e', cls: \"returns-usp\" },\n      { img: \"phone\", text: '\u003cspan class=\"bold\"\u003ePreisgekrönter Kundenservice, \u003c/span\u003eimmer für Sie da' }\n    ],\n    \"fr_FR\": [\n      { img: \"tape\",  text: 'Pensé pour plaire, \u003cspan class=\"bold\"\u003econçu pour durer\u003c/span\u003e' },\n      { img: \"medal\", text: 'Achetez en toute confiance, \u003cspan class=\"bold\"\u003evous avez 6 mois pour changer d\\'avis\u003c/span\u003e', cls: \"returns-usp\" },\n      { img: \"phone\", text: '\u003cspan class=\"bold\"\u003eUn service client récompensé, \u003c/span\u003eà votre écoute' }\n    ],\n    \"en_AU\": [\n      { img: \"flag\",  text: 'Timeless British Style, \u003cspan class=\"bold\"\u003eBuilt to Last\u003c/span\u003e' },\n      { img: \"medal\", text: 'Shop Confidently With \u003cspan class=\"bold\"\u003e6 Months To Decide\u003c/span\u003e', cls: \"returns-usp\" },\n      { img: \"phone\", text: '\u003cspan class=\"bold\"\u003eAward Winning\u003c/span\u003e Customer Service, Here For You' }\n    ],\n    \"en_CA\": [\n      { img: \"flag\",  text: 'Timeless British Style, \u003cspan class=\"bold\"\u003eBuilt to Last\u003c/span\u003e' },\n      { img: \"medal\", text: 'Shop Confidently With \u003cspan class=\"bold\"\u003e6 Months To Decide\u003c/span\u003e', cls: \"returns-usp\" },\n      { img: \"phone\", text: '\u003cspan class=\"bold\"\u003eAward Winning\u003c/span\u003e Customer Service, Here For You' }\n    ],\n    \"fr_CA\": [\n      { img: \"flag\",  text: 'Le style anglais intemporel, \u003cspan class=\"bold\"\u003econçu pour durer\u003c/span\u003e' },\n      { img: \"medal\", text: 'Achetez en toute confiance avec \u003cspan class=\"bold\"\u003e6 mois pour décider\u003c/span\u003e', cls: \"returns-usp\" },\n      { img: \"phone\", text: '\u003cspan class=\"bold\"\u003eUn service client récompensé, \u003c/span\u003eà votre écoute' }\n    ],\n    \"en_CH\": [\n      { img: \"tape\",  text: 'Designed To Impress, \u003cspan class=\"bold\"\u003eBuilt To Last\u003c/span\u003e' },\n      { img: \"medal\", text: 'Shop Confidently With \u003cspan class=\"bold\"\u003e6 Months To Decide\u003c/span\u003e', cls: \"returns-usp\" },\n      { img: \"lock\",  text: 'Easy Payments With \u003cimg src=\"/on/demandware.static/-/Library-Sites-CTShirtsSharedLibrary/default/images/usp-icons/twint-logo.svg\" style=\"width:53px; height:21px\"\u003e' }\n    ],\n    \"fr_CH\": [\n      { img: \"tape\",  text: 'Pensé pour plaire, \u003cspan class=\"bold\"\u003econçu pour durer\u003c/span\u003e' },\n      { img: \"medal\", text: 'Achetez en toute confiance avec \u003cspan class=\"bold\"\u003e6 mois pour décider\u003c/span\u003e', cls: \"returns-usp\" },\n      { img: \"lock\",  text: 'Achetez en toute confiance avec \u003cimg src=\"/on/demandware.static/-/Library-Sites-CTShirtsSharedLibrary/default/images/usp-icons/twint-logo.svg\" style=\"width:53px; height:21px\"\u003e' }\n    ],\n    \"de_CH\": [\n      { img: \"tape\",  text: 'Langlebiges Design, \u003cspan class=\"bold\"\u003edas begeistert\u003c/span\u003e' },\n      { img: \"medal\", text: 'Shoppen Sie sorglos mit \u003cspan class=\"bold\"\u003e6 Monaten Bedenkzeit\u003c/span\u003e', cls: \"returns-usp\" },\n      { img: \"lock\",  text: 'Shoppen Sie sorglos mit \u003cimg src=\"/on/demandware.static/-/Library-Sites-CTShirtsSharedLibrary/default/images/usp-icons/twint-logo.svg\" style=\"width:53px; height:21px\"\u003e' }\n    ],\n    \"en_NL\": [\n      { img: \"tape\",  text: 'Designed To Impress, \u003cspan class=\"bold\"\u003eBuilt To Last\u003c/span\u003e' },\n      { img: \"medal\", text: 'Shop Confidently With \u003cspan class=\"bold\"\u003e6 Months To Decide\u003c/span\u003e', cls: \"returns-usp\" },\n      { img: \"phone\", text: '\u003cspan class=\"bold\"\u003eAward Winning\u003c/span\u003e Customer Service, Here For You' }\n    ],\n    \"en_IE\": [\n      { img: \"tape\",  text: 'Designed To Impress,\u003cspan class=\"bold\"\u003e Built To Last\u003c/span\u003e' },\n      { img: \"medal\", text: 'Shop Confidently With \u003cspan class=\"bold\"\u003e6 Months To Decide\u003c/span\u003e', cls: \"returns-usp\" },\n      { img: \"phone\", text: '\u003cspan class=\"bold\"\u003eAward Winning\u003c/span\u003e Customer Service, Here For You' }\n    ],\n    \"nl_NL\": [\n      { img: \"tape\",  text: 'Ontworpen om indruk te maken, \u003cspan class=\"bold\"\u003egebouwd om lang mee te gaan\u003c/span\u003e' },\n      { img: \"medal\", text: 'Koop met vertrouwen met \u003cspan class=\"bold\"\u003e6 maanden de tijd om te beslissen\u003c/span\u003e', cls: \"returns-usp\" },\n      { img: \"phone\", text: '\u003cspan class=\"bold\"\u003eBekroonde\u003c/span\u003e klantenservice, er voor u' }\n    ]\n  };\n\n  function renderIntlItems(items) {\n    return items.map(function (item) {\n      return '' +\n        '\u003cdiv class=\"d-flex' + (item.cls ? ' ' + item.cls : '') + '\" style=\"gap:8px; align-items:center\"\u003e' +\n          '\u003cimg src=\"/on/demandware.static/-/Library-Sites-CTShirtsSharedLibrary/default/images/usp-icons/' + item.img + '-icon.svg\" style=\"width:24px; height:24px\"\u003e' +\n          '\u003cspan\u003e' + item.text + '\u003c/span\u003e' +\n        '\u003c/div\u003e';\n    }).join('');\n  }\n\n  function buildIntlUSPs() {\n    if (document.getElementById(\"USP-Slice-Container\")) return false;\n\n    const ud = window.utag_data || {};\n    const g  = ud.global || {};\n    const p  = ud.page || {};\n    const pageType   = (p.type || '').toLowerCase();\n    const countryRaw = (g.sfcc_country || '').toUpperCase();\n    const siteLang   = g.site_language || '';\n\n    if (pageType !== 'product') return false;\n    if (countryRaw === 'UK' || countryRaw === 'US') return false;\n\n    const items = USP_BY_LANG[siteLang];\n    if (!items) return false;\n\n    const target = document.querySelector('.pdp-main__more-info');\n    if (!target) return false;\n\n    const html = '' +\n      '\u003cdiv id=\"USP-Slice-Container\" class=\"d-flex flex-direction-column\" ' +\n           'style=\"font-size:1.6rem; gap:12px; margin-top:20px; margin-bottom:20px; color:#373737; width:100%\"\u003e' +\n        renderIntlItems(items) +\n      '\u003c/div\u003e';\n\n    target.insertAdjacentHTML('beforebegin', html);\n    return true;\n  }\n\n  // ==================================================\n  // Strip / carousel module (consumes either source)\n  // ==================================================\n  const ID     = \"ct-usp-strip\";\n  const DEBUG  = false;\n  const log    = (...a) =\u003e DEBUG \u0026\u0026 console.log(\"[CT USP Strip]\", ...a);\n\n  const cleanText = (html) =\u003e\n    (html || \"\")\n      // turn bold spans into \u003cb\u003e\n      .replace(/\u003cspan[^\u003e]*class=[\"']?bold[\"']?[^\u003e]*\u003e/gi, \"\u003cb\u003e\")\n      .replace(/\u003c\\/span\u003e/gi, \"\u003c/b\u003e\")\n      // TWINT logo → literal TWINT text so we don't lose meaning\n      .replace(/\u003cimg[^\u003e]*twint-logo[^\u003e]*\u003e/gi, \" TWINT\")\n      // strip all other tags except \u003cb\u003e\n      .replace(/\u003c(?!\\/?b\\b)[^\u003e]+\u003e/gi, \"\")\n      .replace(/\\s+/g, \" \")\n      .trim()\n      .replace(/[.;,:]\\s*$/, \"\");\n\n  const extractItems = (srcEl) =\u003e\n    Array.from(srcEl?.querySelectorAll(\":scope \u003e div.d-flex\") || [])\n      .map((row) =\u003e {\n        const img = row.querySelector(\"img\");\n        const span = row.querySelector(\"span\");\n        const icon = img?.getAttribute(\"src\") || \"\";\n        const alt = img?.getAttribute(\"alt\") || \"\";\n        const label = cleanText(span?.innerHTML || \"\");\n        return icon \u0026\u0026 label ? { icon, alt, label } : null;\n      })\n      .filter(Boolean);\n\n  const injectStyles = () =\u003e {\n    const SID = ID + \"-css\";\n    if (document.getElementById(SID)) return;\n    const css = `\n      #${ID}{\n        font-family: inherit; font-size:14px; line-height:normal; color:#373737;\n        position:relative; z-index:3; border-bottom:1px solid #f5f5f5;\n        contain: layout paint style; isolation:isolate; width:100%;\n      }\n      #${ID} .inner{ max-width:1280px; margin:0 auto; padding:5px 16px; }\n\n      /* Desktop static row */\n      #${ID}.is-desktop .ct-static{ display:flex; align-items:center; justify-content:space-between; gap:12px; }\n      #${ID}.is-desktop .ct-static__item{\n        display:flex; align-items:center; justify-content:center; gap:8px;\n        flex:1 1 0; min-width:0; padding:4px 8px; white-space:nowrap;max-height:28px;\n      }\n      #${ID}.is-desktop .ct-static__item + .ct-static__item{ border-left:1px solid #e8e8e8; }\n\n      #${ID} .ct-usp__icon{ width:20px; height:20px; flex:0 0 20px; display:block; }\n      #${ID} .ct-usp__label{ display:inline; font-size:14px; line-height:normal; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }\n      #${ID} b{ font-weight:600; }\n\n           /* Mobile / tablet carousel (≤1024px) */\n      @media (max-width:1024px){\n        #${ID}{ border-bottom:none; }\n        #${ID} .inner{\n          max-width:none; padding:0;\n          margin-left: calc(50% - 50vw);\n          margin-right: calc(50% - 50vw);\n          width:100vw;\n        }\n        #${ID} .ct-carousel{ position:relative; overflow:hidden; width:100vw; }\n        #${ID} .ct-track{ display:flex; will-change: transform; transition: transform 300ms ease; }\n        #${ID} .ct-slide{\n          width:100vw; flex:0 0 100vw; display:flex; align-items:center; justify-content:center;\n          padding:10px 16px;max-height:28px;\n        }\n        #${ID} .ct-usp-item{ display:inline-flex; align-items:center; gap:8px; white-space:nowrap; }\n      }\n    `;\n    const style = document.createElement(\"style\");\n    style.id = SID;\n    style.textContent = css;\n    document.head.appendChild(style);\n  };\n\n  const buildShell = () =\u003e {\n    const wrap = document.createElement(\"div\");\n    wrap.id = ID;\n    wrap.setAttribute(\"role\", \"region\");\n    wrap.setAttribute(\"aria-label\", \"Key benefits\");\n    wrap.innerHTML = `\n      \u003cdiv class=\"inner\"\u003e\n        \u003cul class=\"ct-static m-ends-z list list--no-bullet\" aria-hidden=\"false\"\u003e\u003c/ul\u003e\n        \u003cdiv class=\"ct-carousel\" style=\"display:none\" aria-roledescription=\"carousel\" aria-label=\"Key benefits\"\u003e\n          \u003cdiv class=\"ct-track\" role=\"group\"\u003e\u003c/div\u003e\n        \u003c/div\u003e\n      \u003c/div\u003e\n    `;\n    return wrap;\n  };\n\n  const itemHTML = (it, isDesktop) =\u003e {\n    const cls = isDesktop ? \"ct-static__item\" : \"ct-usp-item\";\n    return `\n      \u003cli class=\"${cls}\"\u003e\n        \u003cimg class=\"ct-usp__icon\" src=\"${it.icon}\" alt=\"\"\u003e\n        \u003cspan class=\"ct-usp__label\"\u003e${it.label}\u003c/span\u003e\n      \u003c/li\u003e\n    `;\n  };\n\n  const renderDesktop = (items) =\u003e {\n    const box = document.querySelector(`#${ID} .ct-static`);\n    if (box) box.innerHTML = items.map((it) =\u003e itemHTML(it, true)).join(\"\");\n  };\n\n  const renderMobile = (items) =\u003e {\n    const track = document.querySelector(`#${ID} .ct-track`);\n    if (!track) return;\n    track.innerHTML = items\n      .map(\n        (it, i) =\u003e `\n        \u003cdiv class=\"ct-slide\" role=\"group\" aria-roledescription=\"slide\" aria-label=\"${i + 1} of ${items.length}\"\u003e\n          ${itemHTML(it, false)}\n        \u003c/div\u003e\n      `\n      )\n      .join(\"\");\n  };\n\n  // Carousel state\n  let idx = 0;\n  let timer = null;\n  const AUTO_MS = 3000;\n  let paused = false;\n  let startX = 0, dx = 0, dragging = false;\n\n  const getEls = () =\u003e {\n    const wrap = document.getElementById(ID);\n    return {\n      wrap,\n      carousel: wrap?.querySelector(\".ct-carousel\"),\n      track: wrap?.querySelector(\".ct-track\"),\n      slides: wrap?.querySelectorAll(\".ct-slide\") || [],\n    };\n  };\n\n  const applyTransform = (i, animate = true) =\u003e {\n    const { track } = getEls();\n    if (!track) return;\n    track.style.transition = animate ? \"transform 300ms ease\" : \"none\";\n    track.style.transform = `translate3d(${-i * window.innerWidth}px,0,0)`;\n  };\n\n  const next = (len) =\u003e {\n    idx = (idx + 1) % len;\n    applyTransform(idx);\n  };\n  const prev = (len) =\u003e {\n    idx = (idx - 1 + len) % len;\n    applyTransform(idx);\n  };\n\n  const stopAuto = () =\u003e {\n    if (timer) clearInterval(timer);\n    timer = null;\n  };\n\n  const startAuto = (len) =\u003e {\n    if (prefersReduced()) return;\n    stopAuto();\n    if (paused) return;\n    timer = setInterval(() =\u003e next(len), AUTO_MS);\n  };\n\n  const bindMobileInteractions = (len) =\u003e {\n    const { carousel, track } = getEls();\n    if (!carousel || !track) return;\n\n    const pause = () =\u003e {\n      paused = true;\n      stopAuto();\n    };\n    const resume = () =\u003e {\n      paused = false;\n      startAuto(len);\n    };\n\n    carousel.addEventListener(\"mouseenter\", pause, { passive: true });\n    carousel.addEventListener(\"mouseleave\", resume, { passive: true });\n    carousel.addEventListener(\"focusin\", pause, { passive: true });\n    carousel.addEventListener(\"focusout\", resume, { passive: true });\n\n    const onStart = (x) =\u003e {\n      dragging = true;\n      startX = x;\n      dx = 0;\n      stopAuto();\n      track.style.transition = \"none\";\n    };\n    const onMove = (x) =\u003e {\n      if (!dragging) return;\n      dx = x - startX;\n      track.style.transform = `translate3d(${\n        -idx * window.innerWidth + dx\n      }px,0,0)`;\n    };\n    const onEnd = () =\u003e {\n      if (!dragging) return;\n      dragging = false;\n      const threshold = Math.min(120, window.innerWidth * 0.2);\n      if (dx \u003c= -threshold) next(len);\n      else if (dx \u003e= threshold) prev(len);\n      else applyTransform(idx);\n      if (!prefersReduced() \u0026\u0026 !paused) startAuto(len);\n    };\n\n    carousel.addEventListener(\"touchstart\", (e) =\u003e onStart(e.touches[0].clientX), { passive: true });\n    carousel.addEventListener(\"touchmove\", (e) =\u003e onMove(e.touches[0].clientX), { passive: true });\n    carousel.addEventListener(\"touchend\", onEnd, { passive: true });\n\n    document.addEventListener(\"visibilitychange\", () =\u003e {\n      if (document.hidden) stopAuto();\n      else if (!paused \u0026\u0026 isMobileBP()) startAuto(len);\n    });\n  };\n\n  const applyMode = (items) =\u003e {\n    const wrap = document.getElementById(ID);\n    if (!wrap) return;\n    const carousel = wrap.querySelector(\".ct-carousel\");\n    const staticBox = wrap.querySelector(\".ct-static\");\n\n    if (isMobileBP()) {\n      wrap.classList.remove(\"is-desktop\");\n      staticBox.style.display = \"none\";\n      carousel.style.display = \"block\";\n      renderMobile(items);\n      idx = 0;\n      applyTransform(idx, false);\n      bindMobileInteractions(items.length);\n      startAuto(items.length);\n    } else {\n      wrap.classList.add(\"is-desktop\");\n      stopAuto();\n      if (carousel) carousel.style.display = \"none\";\n      staticBox.style.display = \"flex\";\n      renderDesktop(items);\n    }\n  };\n\n  async function initStrip() {\n    if (!isPDP()) return;\n\n    const src =\n      document.getElementById(\"speero-365-usp\") ||\n      document.getElementById(\"USP-Slice-Container\");\n\n    if (!src) return;\n\n    const items = extractItems(src);\n    if (!items.length) return;\n\n    injectStyles();\n    const shell = buildShell();\n\n    if (isMobileBP()) {\n      try {\n        const mobileAnchor = await waitFor(\".js-header-wrapper\");\n        mobileAnchor.insertAdjacentElement(\"afterend\", shell);\n        log(\"Injected after .js-header-wrapper (mobile)\");\n      } catch (e) {\n        return;\n      }\n    } else {\n      const header = document.querySelector(\"#header\");\n      if (!header) return;\n      header.appendChild(shell);\n      log(\"Injected inside #header (desktop)\");\n    }\n\n    try {\n      src.remove();\n    } catch (_) {}\n\n    applyMode(items);\n\n    window.addEventListener(\n      \"resize\",\n      () =\u003e {\n        applyMode(items);\n        if (isMobileBP()) applyTransform(idx, false);\n      },\n      { passive: true }\n    );\n  }\n\n  // ==================================================\n  // Run\n  // ==================================================\n  if (!isPDP()) return;\n\n  poll(\".pdp-main__more-info\", () =\u003e {\n    const ud = window.utag_data || {};\n    const g  = ud.global || {};\n    const countryRaw = (g.sfcc_country || \"\").toUpperCase();\n\n    let built = false;\n    if (countryRaw === \"UK\" || countryRaw === \"US\") {\n      built = module365.buildUSPs();\n    } else {\n      built = buildIntlUSPs();\n    }\n\n    if (built) {\n      initStrip();\n    }\n  }, 30, 200);\n})();\n","trigger":{"include_pages":[{"type":"any"}],"exclude_pages":null},"_id":"68adffa7ca8a419f161f3127"},{"uses_overlay":false,"type":"js","parametrized_definition":"/* CT — DigitalGenius Chat: unified loader for country groups\n   - US: page-type specific proactive config + delayed (60s) enable\n   - UK/DE/AU/EU: country-specific widgetId/locale (no proactive)\n   - Injects #dg-chat z-index fix\n   - Creates required DOM nodes\n*/\n(function () {\n  const FLAG = \"__CT_DG_CHAT_UNIFIED__\";\n  if (window[FLAG]) return;\n  window[FLAG] = true;\n\n  // ---- Helpers --------------------------------------------------------------\n  function get(obj, path, fallback) {\n    try {\n      return path.split(\".\").reduce((o, k) =\u003e (o == null ? o : o[k]), obj) ?? fallback;\n    } catch (e) {\n      return fallback;\n    }\n  }\n\n  function loadScriptOnce(src, id) {\n    return new Promise((resolve, reject) =\u003e {\n      if (document.getElementById(id)) return resolve(\"exists\");\n      const s = document.createElement(\"script\");\n      s.id = id;\n      s.async = true;\n      s.src = src;\n      s.onload = () =\u003e resolve(\"loaded\");\n      s.onerror = (e) =\u003e reject(e);\n      document.head.appendChild(s);\n    });\n  }\n\n  function ensureNode(selector, createFn) {\n    let el = document.querySelector(selector);\n    if (!el) {\n      el = createFn();\n      document.body.appendChild(el);\n    }\n    return el;\n  }\n\n  function injectStyle(css, id) {\n    if (id \u0026\u0026 document.getElementById(id)) return;\n    const st = document.createElement(\"style\");\n    if (id) st.id = id;\n    st.textContent = css;\n    document.head.appendChild(st);\n  }\n\n  // ---- Context --------------------------------------------------------------\n  const ud = window.utag_data || {};\n  const pageType = get(ud, \"page.type\", \"\");\n  const pageName = get(ud, \"page.name\", \"\");\n  const country = get(ud, \"global.sfcc_country\", \"UK\");\n\n  const isUS = country === \"US\";\n  const isAllowedROW = [\"UK\", \"DE\", \"AU\", \"EU\"].includes(country);\n\n  // If not in any supported country, do nothing.\n  if (!isUS \u0026\u0026 !isAllowedROW) return;\n\n  // ---- Required DOM ---------------------------------------------------------\n  // Matches originals: a static-position div and the DG container.\n  ensureNode(\"#dg-chat-container\", () =\u003e {\n    const d = document.createElement(\"div\");\n    d.id = \"dg-chat-container\";\n    return d;\n  });\n  // The US snippet had an extra static div; harmless everywhere.\n  ensureNode(\"div[data-ct-dg-static]\", () =\u003e {\n    const d = document.createElement(\"div\");\n    d.setAttribute(\"data-ct-dg-static\", \"true\");\n    d.setAttribute(\"style\", \"position: static !important;\");\n    return d;\n  });\n\n  // ---- Config per region ----------------------------------------------------\n  const DG_BASE = {\n    env: \"eu\"\n  };\n\n  // US: page-type specific proactive message text (enabled after 60s)\n  if (isUS) {\n    let proactiveQuestions = null;\n\n    if ([\"product\", \"product set\", \"category\"].includes(pageType)) {\n      proactiveQuestions = [\"Do you have any questions about our products or sizing? We are here to help!\"];\n    } else if (pageName === \"basket\" || pageType === \"checkout\") {\n      proactiveQuestions = [\"You’re almost there! Is there anything we can help with?\"];\n    }\n\n    window.DG_CHAT_WIDGET_CONFIG = {\n      widgetId: \"ce95e9a2-4c33-4344-8aac-877b7d00890a\",\n      env: DG_BASE.env,\n      callbacks: {\n        onChatLauncherClick: () =\u003e {\n           exponea.track('Open Chat', {\n        \t\taction: 'conversation_started',\n\n    \t\t});\n        }\n      },\n      locale: \"en-US\",\n      metadata: { countryCode: \"US\" },\n      generalSettings: {},\n      ...(proactiveQuestions\n        ? {\n            proactiveButtonsSettings: {\n              isEnabled: false,\n              questions: proactiveQuestions\n            }\n          }\n        : {})\n    };\n  }\n\n  // UK/DE/AU/EU: country-mapped widget/locale, no proactive\n  if (isAllowedROW) {\n    let storedWidgetId = \"\";\n    let storedLocale = \"\";\n    let storedCountryCode = \"\";\n\n    switch (country) {\n      case \"DE\":\n        storedWidgetId = \"656e5a02-b271-456a-920f-7300034b542a\";\n        storedLocale = \"de-DE\";\n        storedCountryCode = \"DE\";\n        break;\n      case \"UK\":\n        storedWidgetId = \"ce95e9a2-4c33-4344-8aac-877b7d00890a\";\n        storedLocale = \"en-GB\";\n        storedCountryCode = \"GB\";\n        break;\n      case \"EU\":\n        storedWidgetId = \"ce95e9a2-4c33-4344-8aac-877b7d00890a\";\n        storedLocale = \"en-GB\";\n        storedCountryCode = \"EU\";\n        break;\n      case \"AU\":\n        storedWidgetId = \"ce95e9a2-4c33-4344-8aac-877b7d00890a\";\n        storedLocale = \"en-GB\";\n        storedCountryCode = \"AUS\";\n        break;\n    }\n\n    // Only set if not US (to keep US-specific config intact)\n    if (!isUS) {\n      window.DG_CHAT_WIDGET_CONFIG = {\n        widgetId: storedWidgetId,\n        env: DG_BASE.env,\n        locale: storedLocale,\n          callbacks: {\n        onChatLauncherClick: () =\u003e {\n            exponea.track('Open Chat', {\n        \t\taction: 'conversation_started',\n\n    \t\t});\n        }\n      },\n        metadata: { countryCode: storedCountryCode }\n      };\n    }\n  }\n\n  // ---- Load + init ----------------------------------------------------------\n  loadScriptOnce(\"https://chat.digitalgenius.com/init.js\", \"ct-dg-init-js\")\n    .then(() =\u003e {\n      if (window.dgchat \u0026\u0026 typeof window.dgchat.init === \"function\") {\n        window.dgchat.init();\n      }\n\n      // z-index CSS fix (global)\n      injectStyle(\"#dg-chat { z-index:22 !important; }\", \"ct-dg-zfix\");\n\n      // US: After 60s on PDP/PLP/Basket/Checkout, enable proactive buttons \u0026 re-init\n      if (isUS) {\n        const shouldEnableLater =\n          [\"product\", \"product set\", \"category\"].includes(pageType) ||\n          pageName === \"basket\" ||\n          pageType === \"checkout\";\n\n        if (shouldEnableLater) {\n          setTimeout(function () {\n            try {\n              if (!window.DG_CHAT_WIDGET_CONFIG.proactiveButtonsSettings) return;\n              window.DG_CHAT_WIDGET_CONFIG.proactiveButtonsSettings.isEnabled = false;\n              if (window.dgchat?.methods?.initProactiveButtons) {\n                window.dgchat.methods.initProactiveButtons();\n              }\n            } catch (e) {\n              // swallow\n            }\n          }, 60000);\n        }\n      }\n    })\n    .catch((e) =\u003e {\n      // fail silently but log to console for QA\n      if (window.console \u0026\u0026 console.error) {\n        console.error(\"[CT DG Chat] failed to load init.js\", e);\n      }\n    });\n     const css = `\n    @media only screen and (max-width: 800px) {\n      #dg-chat-widget, #dg-chat-widget-placeholder {\n        left: 10% !important;\n        width: 80% !important;\n        border-radius: 0.5rem !important;\n      }\n    }\n  `;\n  $('\u003cstyle\u003e', { text: css }).appendTo('head');\n})();\n","trigger":{"include_pages":[{"type":"any"}],"exclude_pages":[{"url":"/it_IT/","type":"contains"},{"url":"/es_ES/","type":"contains"}]},"_id":"68beaab72ff853b5879139b2"},{"uses_overlay":false,"type":"js","parametrized_definition":"(function () {\n  const ID = \"ct-oc-appointment-banner\";\n  const STYLE_ID = ID + \"-styles\";\n  const BG_URL = \"https://www.charlestyrwhitt.com/dw/image/v2/AAWJ_PRD/on/demandware.static/-/Library-Sites-CTShirtsSharedLibrary/default/dw9aeaf8bd/merchAssets/content/new-homepage/hp4-storeapp-desktop.jpg?sw=1440\";\n  const LINK = \"https://www.charlestyrwhitt.com/uk/store-appointments.html\";\n\n  // ====== Gating ======\n  if (!(window.utag_data \u0026\u0026 utag_data.global \u0026\u0026 utag_data.page)) return;\n  if (utag_data.global.sfcc_country !== \"UK\") return;\n  if (utag_data.page.name !== \"Checkout-Confirmation\") return;\n\n  const target = document.querySelector(\".js-save-details-content\");\n  if (!target) return;\n\n  const bag = Array.isArray(utag_data.bag) ? utag_data.bag : [];\n  const hasSuit = bag.some((it) =\u003e {\n    const id = String(it?.id || \"\").toUpperCase();\n    const cat = String(it?.category || it?.category_name || \"\").toLowerCase();\n    const type = String(it?.product_type || \"\").toLowerCase();\n    const name = String(it?.name || \"\").toLowerCase();\n    return (\n      id.includes(\"SUT\") ||\n      cat.includes(\"suit\") ||\n      type.includes(\"suit\") ||\n      name.includes(\"suit\")\n    );\n  });\n  if (hasSuit) return;\n\n  document.getElementById(ID)?.remove();\n  document.getElementById(STYLE_ID)?.remove();\n\n  // ====== Styles ======\n  const css = `\n    #${ID} {\n      width: 100%;\n      border-radius: 8px;\n      overflow: hidden;\n      margin: 16px 0;\n    }\n    #${ID} .${ID}-link {\n      display: block;\n      text-decoration: none;\n      color: inherit;\n      cursor: pointer;\n    }\n    #${ID} .${ID}-bg {\n      position: relative;\n      width: 100%;\n      min-height: 220px;\n      background-image: url(\"${BG_URL}\");\n      background-size: cover;\n      background-position: center;\n    }\n    #${ID} .${ID}-overlay {\n      position: absolute;\n      inset: 0;\n      background: rgba(55,55,55,0.4);\n      display: flex;\n      align-items: center;\n      justify-content: center;\n      text-align: center;\n      padding: 24px;\n    }\n    #${ID} .${ID}-text {\n      color: #fff;\n      max-width: 1000px;\n      width: 100%;\n    }\n    #${ID} .${ID}-headline,\n    #${ID} .ct-oc-appointment-banner-headline {\n      text-transform: uppercase;\n      font-size: 28px;\n      line-height: 1.1;\n      font-weight: 700;\n      letter-spacing: 0.2px;\n    }\n    #${ID} .${ID}-subline {\n      margin-top: 8px;\n      font-size: 20px;\n      font-weight: 400;\n    }\n    #${ID} .${ID}-subline strong {\n      font-weight: 500;\n    }\n    #${ID} .${ID}-disclaimer {\n      margin-top: 6px;\n      font-size: 14px;\n      font-weight: 300;\n      opacity: 0.9;\n    }\n    #${ID} .${ID}-cta { margin-top: 16px; }\n    #${ID} .${ID}-cta .btn {\n      display: inline-block;\n      width: 220px;\n      padding: 12px 16px;\n      background: #373737;\n      color: #fff;\n      text-align: center;\n      border: none;\n      border-radius: 3px;\n    }\n    @media (min-width: 768px) {\n      #${ID} .${ID}-bg { min-height: 260px; }\n      #${ID} .${ID}-headline,\n      #${ID} .ct-oc-appointment-banner-headline { font-size: 48px; }\n    }\n  `;\n  const style = document.createElement(\"style\");\n  style.id = STYLE_ID;\n  style.textContent = css;\n  document.head.appendChild(style);\n\n  // ====== Markup ======\n  const wrap = document.createElement(\"div\");\n  wrap.id = ID;\n  wrap.setAttribute(\"role\", \"region\");\n  wrap.setAttribute(\"aria-label\", \"In-store appointment promotion\");\n\n  wrap.innerHTML = `\n    \u003ca class=\"${ID}-link\" href=\"${LINK}\" aria-label=\"Book an in-store appointment\"\u003e\n      \u003cdiv class=\"${ID}-bg\"\u003e\n        \u003cdiv class=\"${ID}-overlay\"\u003e\n          \u003cdiv class=\"${ID}-text\"\u003e\n            \u003cdiv class=\"${ID}-headline ct-oc-appointment-banner-headline\"\u003e10% Off Suits\u003c/div\u003e\n            \u003cdiv class=\"${ID}-subline\"\u003e\n              Book an appointment and \u003cstrong\u003euse code APPT10 in store to claim\u003c/strong\u003e\n            \u003c/div\u003e\n            \u003cdiv class=\"${ID}-disclaimer\"\u003eOffer code only valid in store\u003c/div\u003e\n            \u003cdiv class=\"${ID}-cta\"\u003e\n              \u003cspan class=\"btn\" role=\"presentation\"\u003eBook Appointment\u003c/span\u003e\n            \u003c/div\u003e\n          \u003c/div\u003e\n        \u003c/div\u003e\n      \u003c/div\u003e\n    \u003c/a\u003e\n  `;\n\n  target.parentNode.insertBefore(wrap, target);\n\n  // ====== Tracking ======\n  const linkEl = wrap.querySelector(`.${ID}-link`);\n  const trackClick = () =\u003e {\n    try {\n      if (window.exponea \u0026\u0026 typeof exponea.track === \"function\") {\n        exponea.track(\"Clicked Order Conf CTA\", {});\n      }\n    } catch (e) { /* no-op */ }\n  };\n  linkEl.addEventListener(\"click\", trackClick, { capture: true, passive: true });\n})();\n","trigger":{"include_pages":[{"type":"any"}],"exclude_pages":null},"_id":"68bf4243529553f95e296a65"},{"uses_overlay":false,"type":"js","parametrized_definition":"// (function () {\n//   const ID = \"ct-custom-plp\";\n//   const STYLE_ID = ID + \"-styles\";\n//   const LOG = (...a) =\u003e console.debug(`[${ID}]`, ...a);\n\n//   // ===== Guards =====\n//   if (!window.utag_data || !utag_data.page || !utag_data.global) return;\n//   if (utag_data.page.name !== \"made-with-liberty-fabric\" \u0026\u0026 utag_data.page.name !== \"custom\") return;\n\n//   const country = utag_data.global.sfcc_country;\n//   if (country !== \"UK\" \u0026\u0026 country !== \"US\") return;\n\n//   // ===== Styles =====\n//   if (!document.getElementById(STYLE_ID)) {\n//     const link = document.createElement(\"link\");\n//     link.rel = \"stylesheet\";\n//     link.href = \"https://fonts.googleapis.com/css2?family=Lato:wght@400;700;900\u0026display=swap\";\n//     document.head.appendChild(link);\n\n//     const style = document.createElement(\"style\");\n//     style.id = STYLE_ID;\n//     style.textContent = `\n//       .custom-plp-tag{\n//         display:inline-block;position:relative;padding:2px 2rem;border-radius:18px;\n//         color:#373737;font-weight:700;font-family:Lato,sans-serif;font-size:12px;\n//         width:fit-content;margin-top:8px;text-decoration:none !important;\n//         background:linear-gradient(#fff,#fff) padding-box,\n//                   linear-gradient(90deg,#F4B877 0%,#EC967D 15%,#D06D88 30%,#A6699F 45%,#7B63AE 60%,#5757B1 75%,#4852B1 100%) border-box;\n//         border:2px solid transparent;\n//       }\n//       .js-thumb-was-price{\n//       \tdisplay: none;\n//       }\n//     `;\n//     document.head.appendChild(style);\n//   }\n\n//   // ===== URL base =====\n//   const { origin } = window.location;\n\n//   // Force /uk/ or /us/ in the base\n//   let baseURL = origin;\n//   if (country === \"UK\") {\n//     baseURL += \"/uk\";\n//   } else if (country === \"US\") {\n//     baseURL += \"/us\";\n//   }\n\n\n//   // ===== Catalog =====\n//   const customProducts = {\n//   product1: {\n//     id: \"CFN0003WHT\",\n//     image: \"/on/demandware.static/-/Library-Sites-CTShirtsSharedLibrary/default/merchAssets/content/custom/Pre%2Dbuilt/prebuilt1%5FFULL.jpg\",\n//     link: baseURL + \"/custom/build-your-shirt?pid=CFN0003WHT\u0026Quantity=1\u0026csBackStyle=NA\u0026csSizeAndFit=NA\u0026csButton=white\u0026csCollarStyle=classic\u0026csContrastFabric=Y\u0026csContrastFabricLocation=inside-collar-cuff\u0026csContrastFabricReference=CFL0024NAV\u0026csContrastStitch=Y\u0026csContrastStitchColour=silver\u0026csContrastStitchLocation=all-button-holes\u0026csCuffAdjustment=Y\u0026csCuffStyle=rounded-onebutton\u0026csEngravingCollarStay=NA\u0026csGauntletButton=Y\u0026csLeftCuffWatch=NA\u0026csMonogram=NA\u0026monograminitials=NA\u0026csMonogramColour=NA\u0026csMonogramFont=NA\u0026csMonogramLocation=NA\u0026csPiping=Y\u0026csPipingColour=silver\u0026csPipingLocation=collar-cuff\u0026csPlacketStyle=NA\u0026csPocketStyle=NA\u0026csRightCuffWatch=NA\u0026source=cart\u0026pf=PLP-custom-product-tile-1\u0026pf=cs_otp\u0026cm_sp=CS_PLP_Product_Tile\",\n//     UKprice: \"£79\",\n//     USprice: \"$129\"\n//   },\n\n//   product2: {\n//     id: \"CFL0021WHT\",\n//     image: \"/on/demandware.static/-/Library-Sites-CTShirtsSharedLibrary/default/merchAssets/content/custom/Pre%2Dbuilt/prebuilt_NEW_FULL.jpg\",\n//     link: baseURL + \"/custom/build-your-shirt?pid=CFN0046LLC\u0026Quantity=1\u0026csBackStyle=back-pleat\u0026csSizeAndFit=NA\u0026csButton=light-blue\u0026csCollarStyle=cutaway\u0026csContrastFabric=Y\u0026csContrastFabricLocation=inside-collar-cuff\u0026csContrastFabricReference=CFB0036STL\u0026csContrastStitch=Y\u0026csContrastStitchColour=lavender\u0026csContrastStitchLocation=all-button-holes\u0026csCuffAdjustment=NA\u0026csCuffStyle=rounded-one-button\u0026csEngravingCollarStay=NA\u0026csGauntletButton=NA\u0026csLeftCuffWatch=NA\u0026csMonogram=NA\u0026monograminitials=NA\u0026csMonogramColour=NA\u0026csMonogramFont=NA\u0026csMonogramLocation=NA\u0026csPiping=Y\u0026csPipingColour=silver\u0026csPipingLocation=collar-cuff\u0026csPlacketStyle=standard\u0026csPocketStyle=NA\u0026csRightCuffWatch=NA\u0026source=cart\u0026pf=cs_edit\u0026cm_sp=CS_PLP_Product_Tile\",\n//     UKprice: \"£79\",\n//     USprice: \"$129\"\n//   },\n\n//   product3: {\n//     id: \"CFN0053LBU\",\n//     image: \"/on/demandware.static/-/Library-Sites-CTShirtsSharedLibrary/default/merchAssets/content/custom/Pre%2Dbuilt/prebuilt3%5FFULL.jpg\",\n//     link: baseURL + \"/custom/build-your-shirt?pid=CFN0053LBU\u0026Quantity=1\u0026csBackStyle=NA\u0026csSizeAndFit=NA\u0026csButton=white\u0026csCollarStyle=semi-cutaway\u0026csContrastFabric=Y\u0026csContrastFabricLocation=inside-collar-cuff\u0026csContrastFabricReference=CFN0052SPK\u0026csContrastStitch=Y\u0026csContrastStitchColour=pink\u0026csContrastStitchLocation=all-cross-stitch-buttons\u0026csCuffAdjustment=Y\u0026csCuffStyle=rounded-onebutton\u0026csEngravingCollarStay=NA\u0026csGauntletButton=NA\u0026csLeftCuffWatch=NA\u0026csMonogram=NA\u0026monograminitials=NA\u0026csMonogramColour=NA\u0026csMonogramFont=NA\u0026csMonogramLocation=NA\u0026csPiping=Y\u0026csPipingColour=pink\u0026csPipingLocation=collar-cuff\u0026csPlacketStyle=NA\u0026csPocketStyle=NA\u0026csRightCuffWatch=NA\u0026source=cart\u0026pf=PLP-custom-product-tile-3\u0026pf=cs_otp\u0026cm_sp=CS_PLP_Product_Tile\",\n//     UKprice: \"£99\",\n//     USprice: \"$149\"\n//   },\n\n//   product4: {\n//     id: \"CFR0006BLK\",\n//     image: \"/on/demandware.static/-/Library-Sites-CTShirtsSharedLibrary/default/merchAssets/content/custom/Pre%2Dbuilt/prebuilt4%5FFULL.jpg\",\n//     link: baseURL + \"/custom/build-your-shirt?pid=CFR0006BLK\u0026Quantity=1\u0026csBackStyle=NA\u0026csSizeAndFit=NA\u0026csButton=charcoal\u0026csCollarStyle=classic\u0026csContrastFabric=NA\u0026csContrastStitch=Y\u0026csContrastStitchColour=silver\u0026csContrastStitchLocation=all-button-holes\u0026csCuffAdjustment=Y\u0026csCuffStyle=rounded-onebutton\u0026csEngravingCollarStay=NA\u0026csGauntletButton=NA\u0026csLeftCuffWatch=NA\u0026csMonogram=NA\u0026monograminitials=NA\u0026csMonogramColour=NA\u0026csMonogramFont=NA\u0026csMonogramLocation=NA\u0026csPiping=Y\u0026csPipingColour=silver\u0026csPipingLocation=collar-cuff\u0026csPlacketStyle=french\u0026csPocketStyle=NA\u0026csRightCuffWatch=NA\u0026source=cart\u0026pf=PLP-custom-product-tile-4\u0026pf=cs_otp\u0026cm_sp=CS_PLP_Product_Tile\",\n//     UKprice: \"£99\",\n//     USprice: \"$149\"\n//   },\n\n//   product5: {\n//     id: \"CFN0009SKY\",\n//     image: \"/on/demandware.static/-/Library-Sites-CTShirtsSharedLibrary/default/merchAssets/content/custom/Pre%2Dbuilt/prebuilt5%5FFULL.jpg\",\n//     link: baseURL + \"/custom/build-your-shirt?pid=CFN0009SKY\u0026Quantity=1\u0026csBackStyle=NA\u0026csSizeAndFit=NA\u0026csButton=white\u0026csCollarStyle=classic\u0026csContrastFabric=Y\u0026csContrastFabricLocation=outside-collar-cuff\u0026csContrastFabricReference=CFN0002WHT\u0026csContrastStitch=Y\u0026csContrastStitchColour=navy\u0026csContrastStitchLocation=all-button-holes\u0026csCuffAdjustment=Y\u0026csCuffStyle=french-square\u0026csEngravingCollarStay=NA\u0026csGauntletButton=NA\u0026csLeftCuffWatch=NA\u0026csMonogram=NA\u0026monograminitials=NA\u0026csMonogramColour=NA\u0026csMonogramFont=NA\u0026csMonogramLocation=NA\u0026csPiping=Y\u0026csPipingColour=navy\u0026csPipingLocation=collar-cuff\u0026csPlacketStyle=standard\u0026csPocketStyle=NA\u0026csRightCuffWatch=NA\u0026source=cart\u0026pf=PLP-custom-product-tile-5\u0026pf=cs_otp\u0026cm_sp=CS_PLP_Product_Tile\",\n//     UKprice: \"£99\",\n//     USprice: \"$129\"\n//   },\n\n//   product6: {\n//     id: \"CFR0020NKB\",\n//     image: \"/on/demandware.static/-/Library-Sites-CTShirtsSharedLibrary/default/merchAssets/content/custom/Pre%2Dbuilt/prebuilt6%5FFULL.jpg\",\n//     link: baseURL + \"/custom/build-your-shirt?pid=CFR0020NKB\u0026Quantity=1\u0026csBackStyle=NA\u0026csSizeAndFit=NA\u0026csButton=charcoal\u0026csCollarStyle=classic\u0026csContrastFabric=Y\u0026csContrastFabricLocation=inside-collar-cuff\u0026csContrastFabricReference=CFL0027NKB\u0026csContrastStitch=NA\u0026csContrastStitchColour=NA\u0026csContrastStitchLocation=NA\u0026csCuffAdjustment=Y\u0026csCuffStyle=rounded-two-buttons\u0026csEngravingCollarStay=NA\u0026csGauntletButton=NA\u0026csLeftCuffWatch=NA\u0026csMonogram=NA\u0026monograminitials=NA\u0026csMonogramColour=NA\u0026csMonogramFont=NA\u0026csMonogramLocation=NA\u0026csPiping=Y\u0026csPipingColour=navy\u0026csPipingLocation=collar-cuff\u0026csPlacketStyle=french\u0026csPocketStyle=NA\u0026csRightCuffWatch=NA\u0026source=cart\u0026pf=PLP-custom-product-tile-6\u0026pf=cs_otp\u0026cm_sp=CS_PLP_Product_Tile\",\n//     UKprice: \"£79\",\n//     USprice: \"$149\"\n//   },\n\n//   product7: {\n//     id: \"CFN0024WHT\",\n//     image: \"/on/demandware.static/-/Library-Sites-CTShirtsSharedLibrary/default/merchAssets/content/custom/Pre%2Dbuilt/prebuilt7%5FFULL.jpg\",\n//     link: baseURL + \"/custom/build-your-shirt?pid=CFN0024WHT\u0026Quantity=1\u0026csBackStyle=NA\u0026csSizeAndFit=NA\u0026csButton=white\u0026csCollarStyle=button-down\u0026csContrastFabric=Y\u0026csContrastFabricLocation=inside-collar-cuff\u0026csContrastFabricReference=CFB0036STL\u0026csContrastStitch=Y\u0026csContrastStitchColour=brown\u0026csContrastStitchLocation=all-cross-stitch-buttons\u0026csCuffAdjustment=Y\u0026csCuffStyle=mitered-one-buttons\u0026csEngravingCollarStay=NA\u0026csGauntletButton=NA\u0026csLeftCuffWatch=NA\u0026csMonogram=NA\u0026monograminitials=NA\u0026csMonogramColour=NA\u0026csMonogramFont=NA\u0026csMonogramLocation=NA\u0026csPiping=Y\u0026csPipingColour=brown\u0026csPipingLocation=collar-cuff\u0026csPlacketStyle=french\u0026csPocketStyle=NA\u0026csRightCuffWatch=NA\u0026source=cart\u0026pf=PLP-custom-product-tile-7\u0026pf=cs_otp\u0026cm_sp=CS_PLP_Product_Tile\",\n//     UKprice: \"£79\",\n//     USprice: \"$149\"\n//   },\n\n//   product8: {\n//     id: \"CFN0003PNK\",\n//     image: \"/on/demandware.static/-/Library-Sites-CTShirtsSharedLibrary/default/merchAssets/content/custom/Pre%2Dbuilt/prebuilt8%5FFULL.jpg\",\n//     link: baseURL + \"/custom/build-your-shirt?pid=CFN0003PNK\u0026Quantity=1\u0026csBackStyle=NA\u0026csSizeAndFit=NA\u0026csButton=white\u0026csCollarStyle=classic\u0026csContrastFabric=Y\u0026csContrastFabricLocation=outside-collar-cuff\u0026csContrastFabricReference=CFN0002WHT\u0026csContrastStitch=Y\u0026csContrastStitchColour=pink\u0026csContrastStitchLocation=all-button-holes\u0026csCuffAdjustment=Y\u0026csCuffStyle=french-rounded\u0026csEngravingCollarStay=NA\u0026csGauntletButton=NA\u0026csLeftCuffWatch=NA\u0026csMonogram=NA\u0026monograminitials=NA\u0026csMonogramColour=NA\u0026csMonogramFont=NA\u0026csMonogramLocation=NA\u0026csPiping=NA\u0026csPipingColour=NA\u0026csPipingLocation=NA\u0026csPlacketStyle=standard\u0026csPocketStyle=NA\u0026csRightCuffWatch=NA\u0026source=cart\u0026pf=PLP-custom-product-tile-8\u0026pf=cs_otp\u0026cm_sp=CS_PLP_Product_Tile\",\n//     UKprice: \"£79\",\n//     USprice: \"$129\"\n//   },\n\n//   product9: {\n//     id: \"CFL0027VRY\",\n//     image: \"/on/demandware.static/-/Library-Sites-CTShirtsSharedLibrary/default/merchAssets/content/custom/Pre%2Dbuilt/prebuilt9%5FFULL.jpg\",\n//     link: baseURL + \"/custom/build-your-shirt?pid=CFL0027VRY\u0026Quantity=1\u0026csBackStyle=NA\u0026csSizeAndFit=NA\u0026csButton=light-brown\u0026csCollarStyle=classic\u0026csContrastStitch=Y\u0026csContrastStitchColour=maroon\u0026csContrastStitchLocation=all-button-holes\u0026csCuffAdjustment=Y\u0026csCuffStyle=rounded-onebutton\u0026csEngravingCollarStay=NA\u0026csGauntletButton=NA\u0026csLeftCuffWatch=NA\u0026csMonogram=NA\u0026monograminitials=NA\u0026csMonogramColour=NA\u0026csMonogramFont=NA\u0026csMonogramLocation=NA\u0026csPiping=NA\u0026csPipingColour=NA\u0026csPipingLocation=NA\u0026csPlacketStyle=standard\u0026csPocketStyle=NA\u0026csRightCuffWatch=NA\u0026source=cart\u0026pf=PLP-custom-product-tile-9\u0026pf=cs_otp\u0026cm_sp=CS_PLP_Product_Tile\",\n//     UKprice: \"£139\",\n//     USprice: \"$179\"\n//   },\n\n//   product10: {\n//     id: \"CFB0038SGE\",\n//     image: \"/on/demandware.static/-/Library-Sites-CTShirtsSharedLibrary/default/merchAssets/content/custom/Pre%2Dbuilt/prebuilt10%5FFULL.jpg\",\n//     link: baseURL + \"/custom/build-your-shirt?pid=CFB0038SGE\u0026Quantity=1\u0026csBackStyle=NA\u0026csSizeAndFit=NA\u0026csButton=mid-brown\u0026csCollarStyle=classic\u0026csContrastStitch=Y\u0026csContrastStitchColour=maroon\u0026csContrastStitchLocation=all-button-holes\u0026csCuffAdjustment=Y\u0026csCuffStyle=square-two-buttons\u0026csEngravingCollarStay=NA\u0026csGauntletButton=NA\u0026csLeftCuffWatch=NA\u0026csMonogram=NA\u0026monograminitials=NA\u0026csMonogramColour=NA\u0026csMonogramFont=NA\u0026csMonogramLocation=NA\u0026csPiping=NA\u0026csPipingColour=NA\u0026csPipingLocation=NA\u0026csPlacketStyle=standard\u0026csPocketStyle=NA\u0026csRightCuffWatch=NA\u0026source=cart\u0026pf=PLP-custom-product-tile-10\u0026pf=cs_otp\u0026cm_sp=CS_PLP_Product_Tile\",\n//     UKprice: \"£79\",\n//     USprice: \"$129\"\n//   },\n\n//   product11: {\n//     id: \"CFN0022WSK\",\n//     image: \"/on/demandware.static/-/Library-Sites-CTShirtsSharedLibrary/default/merchAssets/content/custom/Pre%2Dbuilt/preBuiltCFN0022WSK.jpg\",\n//     link: baseURL + \"/custom/build-your-shirt?pid=CFN0022WSK\u0026Quantity=1\u0026csBackStyle=back-pleat\u0026csSizeAndFit=NA\u0026csButton=white\u0026csCollarSize=16.5\u0026csCollarStyle=classic\u0026csContrastFabric=Y\u0026csContrastFabricLocation=outside-collar-cuff\u0026csContrastFabricReference=CFN0002WHT\u0026csContrastStitch=Y\u0026csContrastStitchColour=light-blue\u0026csContrastStitchLocation=all-button-holes\u0026csCuffAdjustment=NA\u0026csCuffStyle=french-rounded\u0026csEngravingCollarStay=NA\u0026csFit=slim-fit\u0026csGauntletButton=NA\u0026csLeftCuffWatch=NA\u0026csMonogram=NA\u0026monograminitials=NA\u0026csMonogramColour=NA\u0026csMonogramFont=NA\u0026csMonogramLocation=NA\u0026csPiping=Y\u0026csPipingColour=navy\u0026csPipingLocation=collar-cuff\u0026csPlacketStyle=standard\u0026csPocketStyle=NA\u0026csRightCuffWatch=NA\u0026csSleeveLength=34\u0026source=cart\u0026pf=cs_edit\u0026cm_sp=CS_PLP_Product_Tile\",\n//     UKprice: \"£79\",\n//     USprice: \"$129\"\n//   },\n\n//   product12: {\n//     id: \"CFN0039HEB\",\n//     image: \"/on/demandware.static/-/Library-Sites-CTShirtsSharedLibrary/default/merchAssets/content/custom/Pre%2Dbuilt/prebuiltNew.jpg\",\n//     link: baseURL + \"/custom/build-your-shirt?pid=CFN0039HEB\u0026Quantity=1\u0026csBackStyle=back-pleat\u0026csSizeAndFit=NA\u0026csButton=smoke\u0026csCollarSize=15\u0026csCollarStyle=cutaway\u0026csContrastFabric=Y\u0026csContrastFabricLocation=inside-collar-cuff\u0026csContrastFabricReference=CFL0029MBU\u0026csContrastStitch=Y\u0026csContrastStitchColour=grey\u0026csContrastStitchLocation=all-button-holes\u0026csCuffAdjustment=NA\u0026csCuffStyle=mitered-one-button\u0026csEngravingCollarStay=NA\u0026csFit=slim-fit\u0026csGauntletButton=NA\u0026csLeftCuffWatch=NA\u0026csMonogram=NA\u0026monograminitials=NA\u0026csMonogramColour=NA\u0026csMonogramFont=NA\u0026csMonogramLocation=NA\u0026csPiping=Y\u0026csPipingColour=silver\u0026csPipingLocation=collar-cuff\u0026csPlacketStyle=standard\u0026csPocketStyle=NA\u0026csRightCuffWatch=NA\u0026csSleeveLength=32.5\u0026source=cart\u0026pf=cs_edit\u0026cm_sp=CS_PLP_Product_Tile\",\n//     UKprice: \"£79\",\n//     USprice: \"$129\"\n//   }\n// };\n\n\n//   // ===== Utils =====\n//   const qs = (root, sel) =\u003e (root || document).querySelector(sel);\n//   const qsa = (root, sel) =\u003e Array.from((root || document).querySelectorAll(sel));\n\n//   // Keep your original function (requested)\n//   function replaceImgKeepAttrs(img, newSrc) {\n//     if (!img) return;\n//     const clone = img.cloneNode(true); // drops JS listeners\n//     clone.setAttribute(\"data-thumb-roll-over\", (img.getAttribute(\"src\") || \"\").split(\"?\")[0]);\n//     clone.setAttribute(\"data-hi-res-thumb-roll-over\", (img.getAttribute(\"src\") || \"\").split(\"?\")[0]);\n//     clone.setAttribute(\"data-thumb\", newSrc);\n//     clone.src = newSrc;\n//     img.replaceWith(clone);\n//   }\n\n//   function getDisplayPrice(product) {\n//     const raw = (country === \"UK\" ? product.UKprice : product.USprice) || \"\";\n//     const numeric = (raw.match(/[\\d.,]+/) || [\"\"])[0].replace(\",\", \"\");\n//     const currencyCode = raw.trim().startsWith(\"£\") ? \"GBP\"\n//       : raw.trim().startsWith(\"$\") ? \"USD\"\n//         : (country === \"UK\" ? \"GBP\" : \"USD\");\n//     return { raw, numeric, currencyCode };\n//   }\n\n//   function setPriceFromProduct(root, product) {\n//     if (!root || !product) return;\n//     const { raw, numeric, currencyCode } = getDisplayPrice(product);\n\n//     const was = qs(root, \".js-thumb-was-price span[aria-hidden='true'], .was-price span[aria-hidden='true']\");\n//     const now = qs(root, \".js-thumb-now-price span[aria-hidden='true'], .now-price span[aria-hidden='true']\");\n//     const wasA11y = qs(root, \".js-thumb-was-price .accessibility-hidden, .was-price .accessibility-hidden\");\n//     const nowA11y = qs(root, \".js-thumb-now-price .accessibility-hidden, .now-price .accessibility-hidden\");\n\n//     // Mobile wraps the price value in a nested \u003cspan class=\"js-showonminicart-price\"\u003e.\n//     // Write to that inner node when present so the minicart hook is preserved.\n//     if (now) {\n//       const inner = now.querySelector(\".js-showonminicart-price\");\n//       if (inner) {\n//         if (inner.textContent !== raw) inner.textContent = raw;\n//       } else if (now.textContent !== raw) {\n//         now.textContent = raw;\n//       }\n//     }\n//     if (nowA11y \u0026\u0026 nowA11y.textContent !== `now ${raw}`) nowA11y.textContent = `now ${raw}`;\n//     if (was \u0026\u0026 was.textContent !== raw) was.textContent = raw;\n//     if (wasA11y \u0026\u0026 wasA11y.textContent !== `was ${raw}`) wasA11y.textContent = `was ${raw}`;\n\n//     const currencyInput = qs(root, \"input#productPriceCurrency\");\n//     const wasInput = qs(root, \"input#productWasPrice\");\n//     const nowInput = qs(root, \"input#productNowPrice\");\n//     if (currencyInput \u0026\u0026 currencyInput.value !== currencyCode) currencyInput.value = currencyCode;\n//     if (wasInput \u0026\u0026 wasInput.value !== numeric) wasInput.value = numeric || \"\";\n//     if (nowInput \u0026\u0026 nowInput.value !== numeric) nowInput.value = numeric || \"\";\n//   }\n\n//   function ensureBadgeAfter(el, href) {\n//     if (!el) return;\n//     const next = el.nextElementSibling;\n//     if (next \u0026\u0026 next.classList \u0026\u0026 next.classList.contains(\"custom-plp-tag\")) return;\n//     const a = document.createElement(\"a\");\n//     a.className = \"custom-plp-tag\";\n//     a.href = href;\n//     a.textContent = \"Custom\";\n//     el.insertAdjacentElement(\"afterend\", a);\n//   }\n\n//   let isPatching = false;\n\n//   // ===== Core: update a tile (idempotent + loop-proof) =====\n//   function updateTile(tile, product) {\n//     if (!tile || !product) return;\n\n//     // If already applied, just keep links/prices in sync (no heavy DOM)\n//     if (tile.dataset.ctCustomApplied === \"1\") {\n//       const allLinks = qsa(tile, \"a.js-thumb-link, a.product-tile__img-link, a.product-tile__name-link\");\n//       allLinks.forEach(a =\u003e { if (a.href !== product.link) a.href = product.link; });\n//       setPriceFromProduct(tile, product);\n//       return;\n//     }\n\n//     isPatching = true;\n\n//     const img = qs(tile, \"img.js-thumb-img\");\n//     const pic = qs(tile, \"picture\");\n//     const allLinks = qsa(tile, \"a.js-thumb-link, a.product-tile__img-link, a.product-tile__name-link\");\n\n//     const newImageSrc = origin + product.image;\n//     // Only replace if different to avoid extra mutations\n//     if (img \u0026\u0026 img.getAttribute(\"src\") !== newImageSrc) {\n//       replaceImgKeepAttrs(img, newImageSrc);\n//     }\n//     if (pic) {\n//       [[\"data-hiressrc\", newImageSrc], [\"data-iessrc\", newImageSrc], [\"data-iesrc\", newImageSrc]]\n//         .forEach(([k, v]) =\u003e { if (pic.getAttribute(k) !== v) pic.setAttribute(k, v); });\n//     }\n\n//     // Update all tile links\n//     allLinks.forEach(a =\u003e { if (a.href !== product.link) a.href = product.link; });\n\n//     // Badge + price\n//     ensureBadgeAfter(tile, product.link);\n//     setPriceFromProduct(tile, product);\n\n//     const promo = qs(tile, \".product-tile__promo\");\n//     if (promo \u0026\u0026 promo.textContent !== \"Buy 2, Save 10%\") promo.textContent = \"Buy 2, Save 10%\";\n\n\n\n//     tile.dataset.ctCustomApplied = \"1\";\n//     isPatching = false;\n\n//     LOG(\"Updated tile\", product.id);\n//   }\n\n//   // ===== Apply to PLP tiles =====\n//   // The custom page renders the same product in multiple modules (grid, carousel,\n//   // featured block) and across responsive variants, so a product id can resolve to\n//   // several nodes. Patch every match, not just the first.\n//   function editCustomPlpTiles() {\n//     if (isPatching) return;\n//     Object.values(customProducts).forEach((product) =\u003e {\n//       const tiles = document.querySelectorAll(`[data-prod-id=\"${product.id}\"]`);\n//       tiles.forEach((tile) =\u003e updateTile(tile, product));\n//     });\n//   }\n\n//   // Observe late renders (debounced)\n//   let raf = 0;\n//   const observer = new MutationObserver(() =\u003e {\n//     if (isPatching) return;\n//     if (raf) cancelAnimationFrame(raf);\n//     raf = requestAnimationFrame(editCustomPlpTiles);\n//   });\n//   observer.observe(document.body, { childList: true, subtree: true });\n\n//   // Initial pass\n//   editCustomPlpTiles();\n\n//   // Rename across every instance of the product, not just the first node.\n//   function overrideProductName(prodId, newName) {\n// \t  const tiles = document.querySelectorAll(`[data-prod-id=\"${prodId}\"]`);\n// \t  if (!tiles.length) return false;\n\n// \t  let changed = false;\n// \t  tiles.forEach((tile) =\u003e {\n// \t    const nameEl = tile.querySelector(\".js-thumb-name\");\n// \t    if (nameEl) {\n// \t      nameEl.textContent = newName;\n// \t      changed = true;\n// \t    }\n// \t  });\n// \t  return changed;\n// \t}\n// \toverrideProductName(\"CFL0021WHT\", \"Non-Iron Twill - Lilac Purple\");\n// })();\n\n\n(function () {\n  const ID = \"ct-custom-plp\";\n  const STYLE_ID = ID + \"-styles\";\n  const LOG = (...a) =\u003e console.debug(`[${ID}]`, ...a);\n\n  // ===== Run flag — prevents double-execution =====\n  const RUN_FLAG = \"__CT_CUSTOM_PLP__\";\n  if (window[RUN_FLAG]) return;\n  window[RUN_FLAG] = true;\n\n  // ===== Guards =====\n  if (!window.utag_data || !utag_data.global) return;\n  if (!window.location.pathname.includes(\"/custom\") \u0026\u0026 !window.location.pathname.includes(\"/made-with-liberty-fabric\")) return;\n\n  const country = utag_data.global.sfcc_country;\n  if (country !== \"UK\" \u0026\u0026 country !== \"US\") return;\n\n  LOG(\"Guard passed — page:\", window.location.pathname, \"| country:\", country);\n\n  // ===== Styles =====\n  if (!document.getElementById(STYLE_ID)) {\n    const link = document.createElement(\"link\");\n    link.rel = \"stylesheet\";\n    link.href = \"https://fonts.googleapis.com/css2?family=Lato:wght@400;700;900\u0026display=swap\";\n    document.head.appendChild(link);\n\n    const style = document.createElement(\"style\");\n    style.id = STYLE_ID;\n    style.textContent = `\n      .custom-plp-tag{\n        display:inline-block;position:relative;padding:2px 2rem;border-radius:18px;\n        color:#373737;font-weight:700;font-family:Lato,sans-serif;font-size:12px;\n        width:fit-content;margin-top:8px;text-decoration:none !important;\n        background:linear-gradient(#fff,#fff) padding-box,\n                  linear-gradient(90deg,#F4B877 0%,#EC967D 15%,#D06D88 30%,#A6699F 45%,#7B63AE 60%,#5757B1 75%,#4852B1 100%) border-box;\n        border:2px solid transparent;\n      }\n      .js-thumb-was-price{\n        display: none;\n      }\n    `;\n    document.head.appendChild(style);\n  }\n\n  // ===== URL base =====\n  const { origin } = window.location;\n\n  // Force /uk/ or /us/ in the base\n  let baseURL = origin;\n  if (country === \"UK\") {\n    baseURL += \"/uk\";\n  } else if (country === \"US\") {\n    baseURL += \"/us\";\n  }\n\n  // ===== Catalog =====\n  const customProducts = {\n    product1: {\n      id: \"CFN0003WHT\",\n      image: \"/on/demandware.static/-/Library-Sites-CTShirtsSharedLibrary/default/merchAssets/content/custom/Pre%2Dbuilt/prebuilt1%5FFULL.jpg\",\n      link: baseURL + \"/custom/build-your-shirt?pid=CFN0003WHT\u0026Quantity=1\u0026csBackStyle=NA\u0026csSizeAndFit=NA\u0026csButton=white\u0026csCollarStyle=classic\u0026csContrastFabric=Y\u0026csContrastFabricLocation=inside-collar-cuff\u0026csContrastFabricReference=CFL0024NAV\u0026csContrastStitch=Y\u0026csContrastStitchColour=silver\u0026csContrastStitchLocation=all-button-holes\u0026csCuffAdjustment=Y\u0026csCuffStyle=rounded-onebutton\u0026csEngravingCollarStay=NA\u0026csGauntletButton=Y\u0026csLeftCuffWatch=NA\u0026csMonogram=NA\u0026monograminitials=NA\u0026csMonogramColour=NA\u0026csMonogramFont=NA\u0026csMonogramLocation=NA\u0026csPiping=Y\u0026csPipingColour=silver\u0026csPipingLocation=collar-cuff\u0026csPlacketStyle=NA\u0026csPocketStyle=NA\u0026csRightCuffWatch=NA\u0026source=cart\u0026pf=PLP-custom-product-tile-1\u0026pf=cs_otp\u0026cm_sp=CS_PLP_Product_Tile\",\n      UKprice: \"£79\",\n      USprice: \"$129\"\n    },\n\n    product2: {\n      id: \"CFL0021WHT\",\n      image: \"/on/demandware.static/-/Library-Sites-CTShirtsSharedLibrary/default/merchAssets/content/custom/Pre%2Dbuilt/prebuilt_NEW_FULL.jpg\",\n      link: baseURL + \"/custom/build-your-shirt?pid=CFN0046LLC\u0026Quantity=1\u0026csBackStyle=back-pleat\u0026csSizeAndFit=NA\u0026csButton=light-blue\u0026csCollarStyle=cutaway\u0026csContrastFabric=Y\u0026csContrastFabricLocation=inside-collar-cuff\u0026csContrastFabricReference=CFB0036STL\u0026csContrastStitch=Y\u0026csContrastStitchColour=lavender\u0026csContrastStitchLocation=all-button-holes\u0026csCuffAdjustment=NA\u0026csCuffStyle=rounded-one-button\u0026csEngravingCollarStay=NA\u0026csGauntletButton=NA\u0026csLeftCuffWatch=NA\u0026csMonogram=NA\u0026monograminitials=NA\u0026csMonogramColour=NA\u0026csMonogramFont=NA\u0026csMonogramLocation=NA\u0026csPiping=Y\u0026csPipingColour=silver\u0026csPipingLocation=collar-cuff\u0026csPlacketStyle=standard\u0026csPocketStyle=NA\u0026csRightCuffWatch=NA\u0026source=cart\u0026pf=cs_edit\u0026cm_sp=CS_PLP_Product_Tile\",\n      UKprice: \"£79\",\n      USprice: \"$129\"\n    },\n\n    product3: {\n      id: \"CFN0053LBU\",\n      image: \"/on/demandware.static/-/Library-Sites-CTShirtsSharedLibrary/default/merchAssets/content/custom/Pre%2Dbuilt/prebuilt3%5FFULL.jpg\",\n      link: baseURL + \"/custom/build-your-shirt?pid=CFN0053LBU\u0026Quantity=1\u0026csBackStyle=NA\u0026csSizeAndFit=NA\u0026csButton=white\u0026csCollarStyle=semi-cutaway\u0026csContrastFabric=Y\u0026csContrastFabricLocation=inside-collar-cuff\u0026csContrastFabricReference=CFN0052SPK\u0026csContrastStitch=Y\u0026csContrastStitchColour=pink\u0026csContrastStitchLocation=all-cross-stitch-buttons\u0026csCuffAdjustment=Y\u0026csCuffStyle=rounded-onebutton\u0026csEngravingCollarStay=NA\u0026csGauntletButton=NA\u0026csLeftCuffWatch=NA\u0026csMonogram=NA\u0026monograminitials=NA\u0026csMonogramColour=NA\u0026csMonogramFont=NA\u0026csMonogramLocation=NA\u0026csPiping=Y\u0026csPipingColour=pink\u0026csPipingLocation=collar-cuff\u0026csPlacketStyle=NA\u0026csPocketStyle=NA\u0026csRightCuffWatch=NA\u0026source=cart\u0026pf=PLP-custom-product-tile-3\u0026pf=cs_otp\u0026cm_sp=CS_PLP_Product_Tile\",\n      UKprice: \"£99\",\n      USprice: \"$149\"\n    },\n\n    product4: {\n      id: \"CFR0006BLK\",\n      image: \"/on/demandware.static/-/Library-Sites-CTShirtsSharedLibrary/default/merchAssets/content/custom/Pre%2Dbuilt/prebuilt4%5FFULL.jpg\",\n      link: baseURL + \"/custom/build-your-shirt?pid=CFR0006BLK\u0026Quantity=1\u0026csBackStyle=NA\u0026csSizeAndFit=NA\u0026csButton=charcoal\u0026csCollarStyle=classic\u0026csContrastFabric=NA\u0026csContrastStitch=Y\u0026csContrastStitchColour=silver\u0026csContrastStitchLocation=all-button-holes\u0026csCuffAdjustment=Y\u0026csCuffStyle=rounded-onebutton\u0026csEngravingCollarStay=NA\u0026csGauntletButton=NA\u0026csLeftCuffWatch=NA\u0026csMonogram=NA\u0026monograminitials=NA\u0026csMonogramColour=NA\u0026csMonogramFont=NA\u0026csMonogramLocation=NA\u0026csPiping=Y\u0026csPipingColour=silver\u0026csPipingLocation=collar-cuff\u0026csPlacketStyle=french\u0026csPocketStyle=NA\u0026csRightCuffWatch=NA\u0026source=cart\u0026pf=PLP-custom-product-tile-4\u0026pf=cs_otp\u0026cm_sp=CS_PLP_Product_Tile\",\n      UKprice: \"£99\",\n      USprice: \"$149\"\n    },\n\n    product5: {\n      id: \"CFN0009SKY\",\n      image: \"/on/demandware.static/-/Library-Sites-CTShirtsSharedLibrary/default/merchAssets/content/custom/Pre%2Dbuilt/prebuilt5%5FFULL.jpg\",\n      link: baseURL + \"/custom/build-your-shirt?pid=CFN0009SKY\u0026Quantity=1\u0026csBackStyle=NA\u0026csSizeAndFit=NA\u0026csButton=white\u0026csCollarStyle=classic\u0026csContrastFabric=Y\u0026csContrastFabricLocation=outside-collar-cuff\u0026csContrastFabricReference=CFN0002WHT\u0026csContrastStitch=Y\u0026csContrastStitchColour=navy\u0026csContrastStitchLocation=all-button-holes\u0026csCuffAdjustment=Y\u0026csCuffStyle=french-square\u0026csEngravingCollarStay=NA\u0026csGauntletButton=NA\u0026csLeftCuffWatch=NA\u0026csMonogram=NA\u0026monograminitials=NA\u0026csMonogramColour=NA\u0026csMonogramFont=NA\u0026csMonogramLocation=NA\u0026csPiping=Y\u0026csPipingColour=navy\u0026csPipingLocation=collar-cuff\u0026csPlacketStyle=standard\u0026csPocketStyle=NA\u0026csRightCuffWatch=NA\u0026source=cart\u0026pf=PLP-custom-product-tile-5\u0026pf=cs_otp\u0026cm_sp=CS_PLP_Product_Tile\",\n      UKprice: \"£99\",\n      USprice: \"$129\"\n    },\n\n    product6: {\n      id: \"CFR0020NKB\",\n      image: \"/on/demandware.static/-/Library-Sites-CTShirtsSharedLibrary/default/merchAssets/content/custom/Pre%2Dbuilt/prebuilt6%5FFULL.jpg\",\n      link: baseURL + \"/custom/build-your-shirt?pid=CFR0020NKB\u0026Quantity=1\u0026csBackStyle=NA\u0026csSizeAndFit=NA\u0026csButton=charcoal\u0026csCollarStyle=classic\u0026csContrastFabric=Y\u0026csContrastFabricLocation=inside-collar-cuff\u0026csContrastFabricReference=CFL0027NKB\u0026csContrastStitch=NA\u0026csContrastStitchColour=NA\u0026csContrastStitchLocation=NA\u0026csCuffAdjustment=Y\u0026csCuffStyle=rounded-two-buttons\u0026csEngravingCollarStay=NA\u0026csGauntletButton=NA\u0026csLeftCuffWatch=NA\u0026csMonogram=NA\u0026monograminitials=NA\u0026csMonogramColour=NA\u0026csMonogramFont=NA\u0026csMonogramLocation=NA\u0026csPiping=Y\u0026csPipingColour=navy\u0026csPipingLocation=collar-cuff\u0026csPlacketStyle=french\u0026csPocketStyle=NA\u0026csRightCuffWatch=NA\u0026source=cart\u0026pf=PLP-custom-product-tile-6\u0026pf=cs_otp\u0026cm_sp=CS_PLP_Product_Tile\",\n      UKprice: \"£79\",\n      USprice: \"$149\"\n    },\n\n    product7: {\n      id: \"CFN0024WHT\",\n      image: \"/on/demandware.static/-/Library-Sites-CTShirtsSharedLibrary/default/merchAssets/content/custom/Pre%2Dbuilt/prebuilt7%5FFULL.jpg\",\n      link: baseURL + \"/custom/build-your-shirt?pid=CFN0024WHT\u0026Quantity=1\u0026csBackStyle=NA\u0026csSizeAndFit=NA\u0026csButton=white\u0026csCollarStyle=button-down\u0026csContrastFabric=Y\u0026csContrastFabricLocation=inside-collar-cuff\u0026csContrastFabricReference=CFB0036STL\u0026csContrastStitch=Y\u0026csContrastStitchColour=brown\u0026csContrastStitchLocation=all-cross-stitch-buttons\u0026csCuffAdjustment=Y\u0026csCuffStyle=mitered-one-buttons\u0026csEngravingCollarStay=NA\u0026csGauntletButton=NA\u0026csLeftCuffWatch=NA\u0026csMonogram=NA\u0026monograminitials=NA\u0026csMonogramColour=NA\u0026csMonogramFont=NA\u0026csMonogramLocation=NA\u0026csPiping=Y\u0026csPipingColour=brown\u0026csPipingLocation=collar-cuff\u0026csPlacketStyle=french\u0026csPocketStyle=NA\u0026csRightCuffWatch=NA\u0026source=cart\u0026pf=PLP-custom-product-tile-7\u0026pf=cs_otp\u0026cm_sp=CS_PLP_Product_Tile\",\n      UKprice: \"£79\",\n      USprice: \"$149\"\n    },\n\n    product8: {\n      id: \"CFN0003PNK\",\n      image: \"/on/demandware.static/-/Library-Sites-CTShirtsSharedLibrary/default/merchAssets/content/custom/Pre%2Dbuilt/prebuilt8%5FFULL.jpg\",\n      link: baseURL + \"/custom/build-your-shirt?pid=CFN0003PNK\u0026Quantity=1\u0026csBackStyle=NA\u0026csSizeAndFit=NA\u0026csButton=white\u0026csCollarStyle=classic\u0026csContrastFabric=Y\u0026csContrastFabricLocation=outside-collar-cuff\u0026csContrastFabricReference=CFN0002WHT\u0026csContrastStitch=Y\u0026csContrastStitchColour=pink\u0026csContrastStitchLocation=all-button-holes\u0026csCuffAdjustment=Y\u0026csCuffStyle=french-rounded\u0026csEngravingCollarStay=NA\u0026csGauntletButton=NA\u0026csLeftCuffWatch=NA\u0026csMonogram=NA\u0026monograminitials=NA\u0026csMonogramColour=NA\u0026csMonogramFont=NA\u0026csMonogramLocation=NA\u0026csPiping=NA\u0026csPipingColour=NA\u0026csPipingLocation=NA\u0026csPlacketStyle=standard\u0026csPocketStyle=NA\u0026csRightCuffWatch=NA\u0026source=cart\u0026pf=PLP-custom-product-tile-8\u0026pf=cs_otp\u0026cm_sp=CS_PLP_Product_Tile\",\n      UKprice: \"£79\",\n      USprice: \"$129\"\n    },\n\n    product9: {\n      id: \"CFL0027VRY\",\n      image: \"/on/demandware.static/-/Library-Sites-CTShirtsSharedLibrary/default/merchAssets/content/custom/Pre%2Dbuilt/prebuilt9%5FFULL.jpg\",\n      link: baseURL + \"/custom/build-your-shirt?pid=CFL0027VRY\u0026Quantity=1\u0026csBackStyle=NA\u0026csSizeAndFit=NA\u0026csButton=light-brown\u0026csCollarStyle=classic\u0026csContrastStitch=Y\u0026csContrastStitchColour=maroon\u0026csContrastStitchLocation=all-button-holes\u0026csCuffAdjustment=Y\u0026csCuffStyle=rounded-onebutton\u0026csEngravingCollarStay=NA\u0026csGauntletButton=NA\u0026csLeftCuffWatch=NA\u0026csMonogram=NA\u0026monograminitials=NA\u0026csMonogramColour=NA\u0026csMonogramFont=NA\u0026csMonogramLocation=NA\u0026csPiping=NA\u0026csPipingColour=NA\u0026csPipingLocation=NA\u0026csPlacketStyle=standard\u0026csPocketStyle=NA\u0026csRightCuffWatch=NA\u0026source=cart\u0026pf=PLP-custom-product-tile-9\u0026pf=cs_otp\u0026cm_sp=CS_PLP_Product_Tile\",\n      UKprice: \"£139\",\n      USprice: \"$179\"\n    },\n\n    product10: {\n      id: \"CFB0038SGE\",\n      image: \"/on/demandware.static/-/Library-Sites-CTShirtsSharedLibrary/default/merchAssets/content/custom/Pre%2Dbuilt/prebuilt10%5FFULL.jpg\",\n      link: baseURL + \"/custom/build-your-shirt?pid=CFB0038SGE\u0026Quantity=1\u0026csBackStyle=NA\u0026csSizeAndFit=NA\u0026csButton=mid-brown\u0026csCollarStyle=classic\u0026csContrastStitch=Y\u0026csContrastStitchColour=maroon\u0026csContrastStitchLocation=all-button-holes\u0026csCuffAdjustment=Y\u0026csCuffStyle=square-two-buttons\u0026csEngravingCollarStay=NA\u0026csGauntletButton=NA\u0026csLeftCuffWatch=NA\u0026csMonogram=NA\u0026monograminitials=NA\u0026csMonogramColour=NA\u0026csMonogramFont=NA\u0026csMonogramLocation=NA\u0026csPiping=NA\u0026csPipingColour=NA\u0026csPipingLocation=NA\u0026csPlacketStyle=standard\u0026csPocketStyle=NA\u0026csRightCuffWatch=NA\u0026source=cart\u0026pf=PLP-custom-product-tile-10\u0026pf=cs_otp\u0026cm_sp=CS_PLP_Product_Tile\",\n      UKprice: \"£79\",\n      USprice: \"$129\"\n    },\n\n    product11: {\n      id: \"CFN0022WSK\",\n      image: \"/on/demandware.static/-/Library-Sites-CTShirtsSharedLibrary/default/merchAssets/content/custom/Pre%2Dbuilt/preBuiltCFN0022WSK.jpg\",\n      link: baseURL + \"/custom/build-your-shirt?pid=CFN0022WSK\u0026Quantity=1\u0026csBackStyle=back-pleat\u0026csSizeAndFit=NA\u0026csButton=white\u0026csCollarSize=16.5\u0026csCollarStyle=classic\u0026csContrastFabric=Y\u0026csContrastFabricLocation=outside-collar-cuff\u0026csContrastFabricReference=CFN0002WHT\u0026csContrastStitch=Y\u0026csContrastStitchColour=light-blue\u0026csContrastStitchLocation=all-button-holes\u0026csCuffAdjustment=NA\u0026csCuffStyle=french-rounded\u0026csEngravingCollarStay=NA\u0026csFit=slim-fit\u0026csGauntletButton=NA\u0026csLeftCuffWatch=NA\u0026csMonogram=NA\u0026monograminitials=NA\u0026csMonogramColour=NA\u0026csMonogramFont=NA\u0026csMonogramLocation=NA\u0026csPiping=Y\u0026csPipingColour=navy\u0026csPipingLocation=collar-cuff\u0026csPlacketStyle=standard\u0026csPocketStyle=NA\u0026csRightCuffWatch=NA\u0026csSleeveLength=34\u0026source=cart\u0026pf=cs_edit\u0026cm_sp=CS_PLP_Product_Tile\",\n      UKprice: \"£79\",\n      USprice: \"$129\"\n    },\n\n    product12: {\n      id: \"CFN0039HEB\",\n      image: \"/on/demandware.static/-/Library-Sites-CTShirtsSharedLibrary/default/merchAssets/content/custom/Pre%2Dbuilt/prebuiltNew.jpg\",\n      link: baseURL + \"/custom/build-your-shirt?pid=CFN0039HEB\u0026Quantity=1\u0026csBackStyle=back-pleat\u0026csSizeAndFit=NA\u0026csButton=smoke\u0026csCollarSize=15\u0026csCollarStyle=cutaway\u0026csContrastFabric=Y\u0026csContrastFabricLocation=inside-collar-cuff\u0026csContrastFabricReference=CFL0029MBU\u0026csContrastStitch=Y\u0026csContrastStitchColour=grey\u0026csContrastStitchLocation=all-button-holes\u0026csCuffAdjustment=NA\u0026csCuffStyle=mitered-one-button\u0026csEngravingCollarStay=NA\u0026csFit=slim-fit\u0026csGauntletButton=NA\u0026csLeftCuffWatch=NA\u0026csMonogram=NA\u0026monograminitials=NA\u0026csMonogramColour=NA\u0026csMonogramFont=NA\u0026csMonogramLocation=NA\u0026csPiping=Y\u0026csPipingColour=silver\u0026csPipingLocation=collar-cuff\u0026csPlacketStyle=standard\u0026csPocketStyle=NA\u0026csRightCuffWatch=NA\u0026csSleeveLength=32.5\u0026source=cart\u0026pf=cs_edit\u0026cm_sp=CS_PLP_Product_Tile\",\n      UKprice: \"£79\",\n      USprice: \"$129\"\n    }\n  };\n\n  // ===== Utils =====\n  const qs = (root, sel) =\u003e (root || document).querySelector(sel);\n  const qsa = (root, sel) =\u003e Array.from((root || document).querySelectorAll(sel));\n\n  function replaceImgKeepAttrs(img, newSrc) {\n    if (!img) return;\n    const clone = img.cloneNode(true);\n    clone.setAttribute(\"data-thumb-roll-over\", (img.getAttribute(\"src\") || \"\").split(\"?\")[0]);\n    clone.setAttribute(\"data-hi-res-thumb-roll-over\", (img.getAttribute(\"src\") || \"\").split(\"?\")[0]);\n    clone.setAttribute(\"data-thumb\", newSrc);\n    clone.src = newSrc;\n    img.replaceWith(clone);\n  }\n\n  function getDisplayPrice(product) {\n    const raw = (country === \"UK\" ? product.UKprice : product.USprice) || \"\";\n    const numeric = (raw.match(/[\\d.,]+/) || [\"\"])[0].replace(\",\", \"\");\n    const currencyCode = raw.trim().startsWith(\"£\") ? \"GBP\"\n      : raw.trim().startsWith(\"$\") ? \"USD\"\n        : (country === \"UK\" ? \"GBP\" : \"USD\");\n    return { raw, numeric, currencyCode };\n  }\n\n  function setPriceFromProduct(root, product) {\n    if (!root || !product) return;\n    const { raw, numeric, currencyCode } = getDisplayPrice(product);\n\n    const was = qs(root, \".js-thumb-was-price span[aria-hidden='true'], .was-price span[aria-hidden='true']\");\n    const now = qs(root, \".js-thumb-now-price span[aria-hidden='true'], .now-price span[aria-hidden='true']\");\n    const wasA11y = qs(root, \".js-thumb-was-price .accessibility-hidden, .was-price .accessibility-hidden\");\n    const nowA11y = qs(root, \".js-thumb-now-price .accessibility-hidden, .now-price .accessibility-hidden\");\n\n    if (now) {\n      const inner = now.querySelector(\".js-showonminicart-price\");\n      if (inner) {\n        if (inner.textContent !== raw) inner.textContent = raw;\n      } else if (now.textContent !== raw) {\n        now.textContent = raw;\n      }\n    }\n    if (nowA11y \u0026\u0026 nowA11y.textContent !== `now ${raw}`) nowA11y.textContent = `now ${raw}`;\n    if (was \u0026\u0026 was.textContent !== raw) was.textContent = raw;\n    if (wasA11y \u0026\u0026 wasA11y.textContent !== `was ${raw}`) wasA11y.textContent = `was ${raw}`;\n\n    const currencyInput = qs(root, \"input#productPriceCurrency\");\n    const wasInput = qs(root, \"input#productWasPrice\");\n    const nowInput = qs(root, \"input#productNowPrice\");\n    if (currencyInput \u0026\u0026 currencyInput.value !== currencyCode) currencyInput.value = currencyCode;\n    if (wasInput \u0026\u0026 wasInput.value !== numeric) wasInput.value = numeric || \"\";\n    if (nowInput \u0026\u0026 nowInput.value !== numeric) nowInput.value = numeric || \"\";\n  }\n\n  function ensureBadgeAfter(el, href) {\n    if (!el) return;\n    const next = el.nextElementSibling;\n    if (next \u0026\u0026 next.classList \u0026\u0026 next.classList.contains(\"custom-plp-tag\")) return;\n    const a = document.createElement(\"a\");\n    a.className = \"custom-plp-tag\";\n    a.href = href;\n    a.textContent = \"Custom\";\n    el.insertAdjacentElement(\"afterend\", a);\n  }\n\n  // ===== Core: update a tile (idempotent, re-entrant safe) =====\n  function updateTile(tile, product) {\n    if (!tile || !product) return;\n\n    // Light sync pass for already-patched tiles — keeps links/prices fresh\n    // after filter/sort re-renders that reuse the same node\n    if (tile.dataset.ctCustomApplied === \"1\") {\n      const allLinks = qsa(tile, \"a.js-thumb-link, a.product-tile__img-link, a.product-tile__name-link\");\n      allLinks.forEach(a =\u003e { if (a.href !== product.link) a.href = product.link; });\n      setPriceFromProduct(tile, product);\n      return;\n    }\n\n    try {\n      const img = qs(tile, \"img.js-thumb-img\");\n      const pic = qs(tile, \"picture\");\n      const allLinks = qsa(tile, \"a.js-thumb-link, a.product-tile__img-link, a.product-tile__name-link\");\n\n      const newImageSrc = origin + product.image;\n\n      if (img \u0026\u0026 img.getAttribute(\"src\") !== newImageSrc) {\n        replaceImgKeepAttrs(img, newImageSrc);\n      }\n      if (pic) {\n        [[\"data-hiressrc\", newImageSrc], [\"data-iessrc\", newImageSrc], [\"data-iesrc\", newImageSrc]]\n          .forEach(([k, v]) =\u003e { if (pic.getAttribute(k) !== v) pic.setAttribute(k, v); });\n      }\n\n      allLinks.forEach(a =\u003e { if (a.href !== product.link) a.href = product.link; });\n\n      ensureBadgeAfter(tile, product.link);\n      setPriceFromProduct(tile, product);\n\n      const promo = qs(tile, \".product-tile__promo\");\n      if (promo \u0026\u0026 promo.textContent !== \"Buy 2, Save 10%\") promo.textContent = \"Buy 2, Save 10%\";\n\n      tile.dataset.ctCustomApplied = \"1\";\n      LOG(\"Updated tile\", product.id);\n    } catch (e) {\n      // Swallow per-tile errors so one bad tile never blocks the rest\n      LOG(\"Error updating tile\", product.id, e);\n    }\n  }\n\n  // ===== Apply to all matching PLP tiles =====\n  function editCustomPlpTiles() {\n    Object.values(customProducts).forEach((product) =\u003e {\n      const tiles = document.querySelectorAll(`[data-prod-id=\"${product.id}\"]`);\n      tiles.forEach((tile) =\u003e updateTile(tile, product));\n    });\n\n    // Name override — runs every pass, harmless if el already correct\n    overrideProductName(\"CFL0021WHT\", \"Non-Iron Twill - Lilac Purple\");\n  }\n\n  // ===== Rename helper =====\n  function overrideProductName(prodId, newName) {\n    const tiles = document.querySelectorAll(`[data-prod-id=\"${prodId}\"]`);\n    if (!tiles.length) return false;\n    let changed = false;\n    tiles.forEach((tile) =\u003e {\n      const nameEl = tile.querySelector(\".js-thumb-name\");\n      if (nameEl \u0026\u0026 nameEl.textContent !== newName) {\n        nameEl.textContent = newName;\n        changed = true;\n      }\n    });\n    return changed;\n  }\n\n  // ===== Observer — no isPatching guard so mutations are never silently dropped =====\n  let raf = 0;\n  let retryTimer = null;\n\n  function scheduleUpdate() {\n    // Debounce with rAF to batch rapid DOM mutations into one pass\n    if (raf) cancelAnimationFrame(raf);\n    raf = requestAnimationFrame(() =\u003e {\n      editCustomPlpTiles();\n\n      // Secondary retry catches tiles that finish settling just after the rAF fires\n      if (retryTimer) clearTimeout(retryTimer);\n      retryTimer = setTimeout(editCustomPlpTiles, 300);\n    });\n  }\n\n  const observer = new MutationObserver(scheduleUpdate);\n  observer.observe(document.body, { childList: true, subtree: true });\n\n  // ===== Initial passes =====\n  // Run immediately for tiles already in the DOM, then retry at increasing\n  // intervals to catch slow-rendering / lazy-loaded tiles reliably\n  editCustomPlpTiles();\n  setTimeout(editCustomPlpTiles, 500);\n  setTimeout(editCustomPlpTiles, 1500);\n})();\n\n\n","trigger":{"include_pages":[{"type":"any"}],"exclude_pages":null},"_id":"68c1a3ef680c78c754c39863"},{"uses_overlay":false,"type":"html","parametrized_definition":"\u003cstyle\u003e\n.pt_product-details .price-diff {\n    text-transform: uppercase !important;\n    font-weight: 500 !important;\n    font-size: 1.2rem !important;\n}\n[data-bestselling] {\n    margin-bottom: 10px;\n}\n\n.ui-dialog{\n\tborder-radius: 5px;\n}\n\t.plp-grid__multibuy-placeholder--desktop {\n    \theight: 6rem !important;\n\t}\n      .minicart-recommendations .product-tile__name-link span {\n        font-size: 1.4rem !important; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; line-clamp: 1 !important;\n      }\n .js-minicart-rec-slot-wrapper .product-tile__name-link {\n    height: 2.5rem !important;\n}\n .minicart-recommendations .tile__pricing { font-size: 1.5rem !important; }\n \n .minicart-payment-options li.payment-info__li {\n    display: inline-block;\n    margin-left: 5px;\n    min-width: 50px;\n    margin: 0px !important;\n}\n\n.minicart-payment-options img{\n    max-width: 30px !important;\n}\n.footer {\n    padding-bottom: 1.5rem !important;\n}\n.weblayer--box-subscription{\n\tborder-radius:0.5rem !important;\n}\n.colour-swatching .colourSwitch {\n    margin: 0.3rem !important;\n}\n.attribute-info__icon text{\n\tfont-family: 'Futura' !important;\n}\n.bg-black1{\n\tbackground-color:#373737;\n}\n\u003c/style\u003e\n\n\u003cscript\u003e\n\t(() =\u003e {\n  \"use strict\";\n\n  const LOG_PREFIX = \"[ct-social-proof-top]\";\n  const STYLE_ID = \"ct-social-proof-top-style\";\n\n  const pageType =\n    window.utag_data \u0026\u0026\n    window.utag_data.page \u0026\u0026\n    window.utag_data.page.type;\n\n  if (!/product/i.test(String(pageType))) {\n    console.log(LOG_PREFIX, \"Not a product page → exit\");\n    return;\n  }\n\n  const BADGE_IN_ITEM_SELECTOR =\n    \".slick-slide.slick-current.slick-active .pdpimage__item p.js-thumb-sale-badge\";\n\n  const badgeInActiveItem = document.querySelector(BADGE_IN_ITEM_SELECTOR);\n\n  console.log(LOG_PREFIX, \"Badge selector:\", BADGE_IN_ITEM_SELECTOR);\n  console.log(LOG_PREFIX, \"Badge found?\", !!badgeInActiveItem, badgeInActiveItem || \"\");\n\n  // If badge exists in the active pdpimage__item, do nothing\n  if (badgeInActiveItem) {\n    console.log(LOG_PREFIX, \"Badge exists in active .pdpimage__item → no CSS injected\");\n    return;\n  }\n\n  // Otherwise inject CSS\n  if (document.getElementById(STYLE_ID)) {\n    console.log(LOG_PREFIX, \"CSS already injected → leaving as-is\");\n    return;\n  }\n\n  const style = document.createElement(\"style\");\n  style.id = STYLE_ID;\n  style.textContent = `\n    .socialProofTile {\n      top: 1rem !important;\n    }\n  `;\n\n  document.head.appendChild(style);\n  console.log(LOG_PREFIX, \"Badge NOT found in active .pdpimage__item → injected CSS (top: 1rem)\");\n})();\n\n\u003c/script\u003e","trigger":{"include_pages":[{"type":"any"}],"exclude_pages":null},"_id":"68f7b4e24b2345d83288d7bf"},{"uses_overlay":false,"type":"js","parametrized_definition":"(() =\u003e {\r\n  // =======================\r\n  // CT392 – PDP Payment Icons (clone from .payment-info)\r\n  // =======================\r\n  const RUN_FLAG = \"__CT392_INIT__\";\r\n  if (window[RUN_FLAG]) {\r\n    console.log(\"[CT392] Already init\");\r\n    return;\r\n  }\r\n  window[RUN_FLAG] = true;\r\n\r\n  const LOG = (...a) =\u003e console.log(\"[CT392]\", ...a);\r\n\r\n  // selectors / config\r\n  const ADD_ONE_SEL         = \"#add-to-cart\";      // standard PDP\r\n  const ADD_SET_SEL         = \"#add-all-to-cart\";  // suits / product set\r\n  const SOURCE_PAYMENT_INFO = \".payment-info\";     // footer/localised block with logos\r\n\r\n  // detect page type\r\n  const ut = window.utag_data || {};\r\n  const pageType = String(ut?.page?.type || \"\").toLowerCase();\r\n  const isPDP = pageType === \"product\" || pageType === \"product set\";\r\n\r\n  if (!isPDP) {\r\n    LOG(\"Not a PDP; skipping CT392\");\r\n    return;\r\n  }\r\n\r\n  const isProductSet = pageType === \"product set\";\r\n\r\n  // build styled clone block for PDP\r\n  function makeIconsNode() {\r\n    const $src = $(SOURCE_PAYMENT_INFO).first();\r\n    if (!$src.length) {\r\n      LOG(\"No .payment-info source found, aborting clone\");\r\n      return null;\r\n    }\r\n\r\n    // deep clone\r\n    const $clone = $src.clone(true, true);\r\n\r\n    // strip duplicate IDs\r\n    $clone.find(\"[id]\").addBack(\"[id]\").removeAttr(\"id\");\r\n\r\n    // remove \"Wir akzeptieren:\" / \"We accept:\" label\r\n    $clone.children(\"div\").first().remove();\r\n\r\n    // normalise images\r\n    $clone.find(\"img\").each(function () {\r\n      const $img = $(this);\r\n      const dataSrc = $img.attr(\"data-src\");\r\n      const srcAttr = $img.attr(\"src\");\r\n\r\n      if (!srcAttr \u0026\u0026 dataSrc) {\r\n        $img.attr(\"src\", dataSrc);\r\n      }\r\n\r\n      $img.attr(\"data-loaded\", \"true\");\r\n      $img.removeClass(\"lozad\");\r\n    });\r\n\r\n    // remove margin utility classes\r\n    $clone.removeClass(\"m-top-m m-top-l mps-m-top-m m-bottom-m\");\r\n\r\n    // horizontal layout for \u003cul\u003e\r\n    $clone.find(\"ul.payment-info__li-container\").each(function () {\r\n      this.setAttribute(\r\n        \"style\",\r\n        [\r\n          \"display:flex !important\",\r\n          \"align-items:center !important\",\r\n          \"gap:10px !important\",\r\n          \"margin:5px 0 0 !important\",\r\n          \"padding:0 20px !important\",\r\n          \"list-style:none !important\",\r\n          \"text-align:left !important\"\r\n        ].join(\";\")\r\n      );\r\n    });\r\n\r\n    // style \u003cli\u003e icons\r\n    $clone.find(\"li.payment-info__li\").each(function () {\r\n      this.setAttribute(\r\n        \"style\",\r\n        [\r\n          \"display:flex !important\",\r\n          \"align-items:center !important\",\r\n          \"justify-content:center !important\",\r\n          \"max-width:50px\"\r\n        ].join(\";\")\r\n      );\r\n    });\r\n    \r\n     $clone.find(\"li.payment-info__li img\").each(function () {\r\n      this.setAttribute(\r\n        \"style\",\r\n        [\r\n          \"max-width:40px\",\r\n          \"height:40px\"\r\n        ].join(\";\")\r\n      );\r\n    });\r\n\r\n    // wrapper injected under CTA\r\n    $clone\r\n      .addClass(\"ct392-container\").addClass('flex-justify-center')\r\n      .css({\r\n        width: \"100%\",\r\n        display: \"flex\"\r\n      });\r\n\r\n    return $clone[0];\r\n  }\r\n\r\n  function injectMainPdp() {\r\n    if (document.querySelector(\".ct392-container\")) return;\r\n\r\n    if (isProductSet) {\r\n      const addAllBtn = document.querySelector(ADD_SET_SEL);\r\n      if (!addAllBtn) return;\r\n\r\n      if (\r\n        addAllBtn.nextElementSibling \u0026\u0026\r\n        addAllBtn.nextElementSibling.classList?.contains(\"ct392-container\")\r\n      )\r\n        return;\r\n\r\n      const node = makeIconsNode();\r\n      if (!node) return;\r\n\r\n      addAllBtn.insertAdjacentElement(\"afterend\", node);\r\n      LOG(\"Injected (suit set PDP)\");\r\n    } else {\r\n      const addBtn = document.querySelector(ADD_ONE_SEL);\r\n      if (!addBtn) return;\r\n\r\n      let block = addBtn;\r\n      for (let i = 0; i \u003c 4 \u0026\u0026 block \u0026\u0026 block.parentElement; i++) {\r\n        block = block.parentElement;\r\n      }\r\n\r\n      if (!block || block === document.body) {\r\n        block = addBtn.closest(\"form\") || addBtn.parentElement;\r\n      }\r\n      if (!block) return;\r\n\r\n      if (block.querySelector(\".ct392-container\")) return;\r\n\r\n      const node = makeIconsNode();\r\n      if (!node) return;\r\n\r\n      block.appendChild(node);\r\n      LOG(\"Injected (standard PDP)\");\r\n    }\r\n  }\r\n\r\n  function run() {\r\n    injectMainPdp();\r\n  }\r\n\r\n  // initial + rerun after AJAX (variant/size refreshes)\r\n  run();\r\n  $(document).ajaxComplete(() =\u003e {\r\n    run();\r\n  });\r\n})();\r\n","trigger":{"include_pages":[{"type":"any"}],"exclude_pages":null},"_id":"68fb6250d34d870b223da38e"},{"uses_overlay":false,"type":"js","parametrized_definition":"(() =\u003e {\r\n  console.log(\"[CT GiftCard] v42 — Steam hover + move-up + selected badge\");\r\n\r\n  const TEXT = \"#373737\";\r\n  const BORDER = \"#d0d0d0\";\r\n\r\n  /* =========================================================\r\n     1. GLOBAL STYLES\r\n  ========================================================= */\r\n  const STYLE_ID = \"ct-gift-redesign-v42\";\r\n  if (!document.getElementById(STYLE_ID)) {\r\n    const style = document.createElement(\"style\");\r\n    style.id = STYLE_ID;\r\n    style.textContent = `\r\n      .gift-card__list, .gift-card__header { display:none!important; visibility:hidden!important; }\r\n      .main__area { max-width:130.4rem!important; }\r\n      .gift-card__wrapper { box-shadow:none!important; }\r\n\r\n      .ct-gift-wrapper {\r\n        display:flex; flex-wrap:wrap; gap:2rem;\r\n        margin:0 auto 4rem; max-width:1100px;\r\n      }\r\n      .ct-gift-left,.ct-gift-right { flex:1 1 420px; min-width:300px; }\r\n      .ct-gift-right {\r\n        max-height:1060px!important; overflow-y:auto!important;\r\n        scrollbar-width:thin; scrollbar-color:#999 #f0f0f0;\r\n      }\r\n      .ct-gift-right::-webkit-scrollbar{width:8px;}\r\n      .ct-gift-right::-webkit-scrollbar-track{background:#f0f0f0;}\r\n      .ct-gift-right::-webkit-scrollbar-thumb{background-color:#999;border-radius:4px;}\r\n      @media(max-width:768px){\r\n        .ct-gift-wrapper{flex-direction:column;}\r\n        .ct-gift-left,.ct-gift-right{min-width:100%;max-height:none;overflow:visible;}\r\n      }\r\n\r\n      .ct-page-headline{\r\n        max-width:1100px;margin:2rem auto;\r\n        font-family:\"Futura PT\",sans-serif;color:${TEXT};\r\n        display:flex;flex-direction:column;align-items:center;text-align:center;\r\n      }\r\n      .ct-page-headline h1{\r\n        font-size:4.2rem;font-weight:700;color:${TEXT};\r\n        margin:0 0 .5rem;text-transform:uppercase;\r\n      }\r\n      .ct-page-headline h2{font-size:1.4rem;font-weight:500;color:${TEXT};margin:0 0 1.5rem;}\r\n      .ct-top-nav{display:flex;justify-content:center;flex-wrap:wrap;gap:1rem;}\r\n      .ct-top-nav .ct-btn-primary,.ct-top-nav .ct-btn-outline{\r\n        width:200px;height:40px;display:flex;justify-content:center;align-items:center;\r\n      }\r\n      .ct-top-nav .ct-btn-primary{\r\n        background:${TEXT};color:#fff;border:none;border-radius:4px;font-size:1.4rem;font-weight:600;\r\n        text-transform:uppercase;cursor:pointer;\r\n      }\r\n      .ct-top-nav .ct-btn-outline{\r\n        background:#fff;color:${TEXT};border:1px solid ${BORDER};border-radius:4px;\r\n        font-size:1.4rem;font-weight:600;text-transform:uppercase;cursor:pointer;\r\n      }\r\n\r\n      .ct-gift-left .form__label,\r\n      .ct-gift-left .form__label\u003espan.form__label,\r\n      .ct-gift-left h3{\r\n        font-size:1.6rem!important;font-weight:500!important;color:${TEXT}!important;text-align:left!important;\r\n      }\r\n\r\n      /* Left-column heading */\r\n      .ct-gift-left .ct-left-heading{\r\n        font-size:2rem;\r\n        font-weight:600;\r\n        color:${TEXT};\r\n        margin:0 0 2rem;\r\n        text-align:left;\r\n      }\r\n\r\n      .ct-amount-custom-wrapper{max-width:none!important;width:100%!important;}\r\n      .gift-card__amount-label{\r\n        width:7.5rem;height:5rem;border:.1rem solid #bababa;border-radius:.5rem;\r\n        display:flex!important;justify-content:center;align-items:center;font-size:1.4rem!important;\r\n      }\r\n\r\n      .js-designs-slider{\r\n        margin-bottom:30px!important;\r\n        padding-left:20px!important;\r\n        padding-right:20px!important;\r\n      }\r\n\r\n      /* Let the hover lift breathe – prevent clipping */\r\n      .gift-card__design,\r\n      .js-designs-slider,\r\n      .js-designs-slider li,\r\n      .js-designs-slider .slick-list,\r\n      .js-designs-slider .slick-track,\r\n      .ct-designs-grid{\r\n        overflow:visible!important;\r\n      }\r\n\r\n      /* Transparent plates behind designs (no solid white slab) */\r\n      .gift-card__design,\r\n      .js-designs-slider li,\r\n      .js-designs-slider\u003ediv[data-designnameid],\r\n      .ct-designs-grid,\r\n      .ct-designs-grid\u003ediv[data-designnameid]{\r\n        background-color:transparent!important;\r\n      }\r\n\r\n      /* =========================================================\r\n         STEAM-STYLE CARD: 3D lift + sheen\r\n      ========================================================= */\r\n      .js-designs-slider\u003ediv[data-designnameid],\r\n      .ct-designs-grid\u003ediv[data-designnameid]{\r\n        margin-bottom:40px!important;\r\n        cursor:pointer;\r\n        position:relative;\r\n        overflow:hidden;\r\n        border:1px solid rgba(0,0,0,0.25);\r\n        border-top:1px solid rgba(255,255,255,0.1);\r\n        border-radius:30px;\r\n        box-shadow:0 8px 10px -2px rgba(0,0,0,0.5);\r\n        transform:perspective(222px) translate3d(0,5px,0) rotateX(0deg);\r\n        transform-origin:center;\r\n        perspective-origin:top;\r\n        transition:transform 0.28s ease, box-shadow 0.28s ease, border 0.28s ease;\r\n      }\r\n\r\n      .js-designs-slider\u003ediv[data-designnameid]::before,\r\n      .ct-designs-grid\u003ediv[data-designnameid]::before{\r\n        width:100%;\r\n        height:172%;\r\n        position:absolute;\r\n        top:0;\r\n        left:0;\r\n        content:\"\";\r\n        background-image:linear-gradient(35deg,\r\n          rgba(0,0,0,0.1) 0%,\r\n          rgba(0,0,0,0.07) 51.5%,\r\n          rgba(255,255,255,0.15) 54%,\r\n          rgba(255,255,255,0.15) 100%\r\n        );\r\n        transform:translateY(-36%);\r\n        opacity:0.5;\r\n        transition:transform 0.28s ease, opacity 0.28s ease;\r\n        pointer-events:none;\r\n      }\r\n\r\n      .js-designs-slider\u003ediv[data-designnameid]:hover,\r\n      .js-designs-slider\u003ediv[data-designnameid]:focus,\r\n      .ct-designs-grid\u003ediv[data-designnameid]:hover,\r\n      .ct-designs-grid\u003ediv[data-designnameid]:focus{\r\n        border:1px solid rgba(0,0,0,0.1);\r\n        transform:perspective(222px) translate3d(0,0,8px) rotateX(3deg);\r\n        box-shadow:0 14px 16px -2px rgba(0,0,0,0.5);\r\n      }\r\n\r\n      .js-designs-slider\u003ediv[data-designnameid]:hover::before,\r\n      .js-designs-slider\u003ediv[data-designnameid]:focus::before,\r\n      .ct-designs-grid\u003ediv[data-designnameid]:hover::before,\r\n      .ct-designs-grid\u003ediv[data-designnameid]:focus::before{\r\n        opacity:1;\r\n        transform:translateY(-20%);\r\n      }\r\n\r\n      /* Base image styling: centred, 100% width */\r\n      .js-designs-slider\u003ediv[data-designnameid] img,\r\n      .ct-designs-grid\u003ediv[data-designnameid] img{\r\n        display:block;\r\n        width:100%!important;\r\n        height:auto;\r\n        margin-left:auto;\r\n        margin-right:auto;\r\n        border-radius:30px;\r\n      }\r\n\r\n      /* Move-to-top animation class (applied on select) */\r\n      .ct-card-anim{\r\n        animation:ct-card-move-up 0.28s ease-out;\r\n      }\r\n\r\n      @keyframes ct-card-move-up{\r\n        from{\r\n          transform:perspective(222px) translate3d(0,30px,0) rotateX(0deg);\r\n          opacity:0;\r\n        }\r\n        to{\r\n          transform:perspective(222px) translate3d(0,5px,0) rotateX(0deg);\r\n          opacity:1;\r\n        }\r\n      }\r\n\r\n      /* Selected badge */\r\n      .ct-selected-badge{\r\n        position:absolute;\r\n        top:10px;\r\n        right:20px;\r\n        background:#dbefeb;\r\n        color:#004139;\r\n        padding:4px 10px;\r\n        border-radius:6px;\r\n        font-size:1.2rem;\r\n        font-weight:600;\r\n        z-index:5;\r\n        display:flex;\r\n        align-items:center;\r\n        gap:4px;\r\n        opacity:0;\r\n        transform:translateY(-6px);\r\n        transition:opacity .25s ease, transform .25s ease;\r\n      }\r\n      .ct-selected-badge.show{\r\n        opacity:1;\r\n        transform:translateY(0);\r\n      }\r\n\r\n      .ct-main-cta{\r\n        background:#005B2D;color:#fff;border:none;border-radius:4px;\r\n        width:200px;height:40px;display:flex;justify-content:center;align-items:center;\r\n        font-size:1.4rem;font-weight:600;text-transform:uppercase;cursor:pointer;\r\n      }\r\n\r\n      /* Recipient email label — no padding top */\r\n      .gift-card__recipient-email .form__label--checkout{\r\n        padding-top:0!important;\r\n      }\r\n\r\n      .js-gc-edit-section{\r\n        padding-right:20px!important;\r\n      }\r\n\r\n      /* \"Choose a design\" heading size */\r\n      .gift-card__title,\r\n      .gift-card__design h3,\r\n      .ct-gift-right h3{\r\n        font-size:2.4rem!important;\r\n      }\r\n    `;\r\n    document.head.appendChild(style);\r\n  }\r\n\r\n  /* =========================================================\r\n     2. HELPERS\r\n  ========================================================= */\r\n  const $  = (s, r = document) =\u003e r.querySelector(s);\r\n  const $$ = (s, r = document) =\u003e Array.from(r.querySelectorAll(s));\r\n  const make = (t, c, h) =\u003e {\r\n    const el = document.createElement(t);\r\n    if (c) el.className = c;\r\n    if (h !== undefined) el.innerHTML = h;\r\n    return el;\r\n  };\r\n\r\n  const form = $(\"#dwfrm_giftcert\");\r\n  if (!form) {\r\n    console.warn(\"[CT GiftCard] form not found\");\r\n    return;\r\n  }\r\n\r\n  const addSelectedBadge = card =\u003e {\r\n    if (!card) return;\r\n    // kill existing badges inside slider area\r\n    const root = card.closest(\".js-designs-slider, .ct-designs-grid\") || document;\r\n    root.querySelectorAll(\".ct-selected-badge\").forEach(b =\u003e b.remove());\r\n\r\n    const badge = document.createElement(\"div\");\r\n    badge.className = \"ct-selected-badge\";\r\n    badge.innerHTML = `Selected \u003cspan aria-hidden=\"true\"\u003e✓\u003c/span\u003e`;\r\n    card.appendChild(badge);\r\n\r\n    requestAnimationFrame(() =\u003e {\r\n      badge.classList.add(\"show\");\r\n    });\r\n  };\r\n\r\n  /* =========================================================\r\n     3. STRUCTURE / WRAPPERS (SWAPPED ORDER)\r\n  ========================================================= */\r\n  let wrapper = $(\".ct-gift-wrapper\");\r\n  let leftCol = $(\".ct-gift-left\");\r\n  let rightCol = $(\".ct-gift-right\");\r\n  const designBlock = $(\".gift-card__design\");\r\n\r\n  if (!wrapper) {\r\n    wrapper = make(\"div\", \"ct-gift-wrapper\");\r\n    leftCol = make(\"div\", \"ct-gift-left\");\r\n    rightCol = make(\"div\", \"ct-gift-right\");\r\n\r\n    form.parentNode.insertBefore(wrapper, form);\r\n\r\n    // Designs column first (rightCol), form column second (leftCol)\r\n    wrapper.append(rightCol, leftCol);\r\n\r\n    if (designBlock) rightCol.appendChild(designBlock);\r\n    leftCol.appendChild(form);\r\n  } else {\r\n    if (rightCol \u0026\u0026 designBlock \u0026\u0026 designBlock.parentNode !== rightCol) {\r\n      rightCol.appendChild(designBlock);\r\n    }\r\n    if (leftCol \u0026\u0026 form.parentNode !== leftCol) {\r\n      leftCol.appendChild(form);\r\n    }\r\n  }\r\n\r\n  /* =========================================================\r\n     4. HEADLINE (H1 + nav buttons)\r\n  ========================================================= */\r\n  $$(\".ct-page-headline\").forEach(h =\u003e h.remove());\r\n  const headline = make(\r\n    \"div\",\r\n    \"ct-page-headline\",\r\n    `\r\n      \u003ch1\u003eeGift Cards\u003c/h1\u003e\r\n      \u003ch2\u003eGift impeccable shirts in seconds\u003c/h2\u003e\r\n      \u003cdiv class=\"ct-top-nav\"\u003e\r\n        \u003cbutton class=\"ct-btn ct-btn-primary\" type=\"button\"\u003eeGift Card\u003c/button\u003e\r\n        \u003cbutton class=\"ct-btn ct-btn-outline\" type=\"button\" onclick=\"window.location.href='/gift-cards/balance-check'\"\u003e\r\n          CHECK MY BALANCE\r\n        \u003c/button\u003e\r\n      \u003c/div\u003e\r\n    `\r\n  );\r\n  wrapper.parentNode.insertBefore(headline, wrapper);\r\n\r\n  /* =========================================================\r\n     5. LEFT COLUMN HEADING\r\n  ========================================================= */\r\n  if (leftCol \u0026\u0026 !leftCol.querySelector(\".ct-left-heading\")) {\r\n    const heading = make(\"h2\", \"ct-left-heading\", \"Gift Card Details\");\r\n    leftCol.insertBefore(heading, leftCol.firstChild);\r\n  }\r\n\r\n  /* =========================================================\r\n     6. FORM NORMALISATION\r\n  ========================================================= */\r\n  $$(\".bg-grey5\").forEach(el =\u003e el.classList.remove(\"bg-grey5\"));\r\n  $$(\".form__row\").forEach(r =\u003e r.classList.remove(\"mps-m-auto\", \"p-top-m\"));\r\n  $$(\".mps-col-55, .mps-col-50\").forEach(el =\u003e {\r\n    el.classList.remove(\"mps-col-55\", \"mps-col-50\");\r\n    el.classList.add(\"col-100\");\r\n  });\r\n  $$(\".flex-justify-start\").forEach(el =\u003e el.classList.remove(\"flex-justify-start\"));\r\n\r\n  /* =========================================================\r\n     7. PERSONALISATION + ERROR STATES\r\n  ========================================================= */\r\n  const personalOuter =\r\n    form.querySelector(\".m-sides-l.mps-p-top-xl\") ||\r\n    form.querySelector(\".m-sides-l .gift-info\") ||\r\n    form.querySelector(\".m-sides-l\") ||\r\n    null;\r\n\r\n  if (personalOuter) {\r\n    personalOuter.classList.remove(\r\n      \"m-sides-l\",\r\n      \"mps-p-top-xl\",\r\n      \"p-sides-m\",\r\n      \"mps-p-sides-xl\",\r\n      \"p-bottom-l\",\r\n      \"p-top-s\"\r\n    );\r\n  }\r\n\r\n  const giftInfo = form.querySelector(\".gift-info\");\r\n  if (giftInfo) giftInfo.className = \"gift-info overflow-hidden\";\r\n\r\n  const personalRows = form.querySelectorAll(\r\n    \".gift-info .form__row.select-group, .gift-info .form__row.select-group.required\"\r\n  );\r\n\r\n  personalRows.forEach(row =\u003e {\r\n    row.classList.remove(\"mps-m-sides-xl\");\r\n    row.classList.add(\"required\", \"parent-el-error\");\r\n\r\n    const lbl = row.querySelector(\"label.form__label\");\r\n    const lblInner = row.querySelector(\"label.form__label \u003e span.form__label\");\r\n    [lbl, lblInner].forEach(node =\u003e {\r\n      if (!node) return;\r\n      node.style.fontSize = \"1.6rem\";\r\n      node.style.fontWeight = \"500\";\r\n      node.style.color = TEXT;\r\n      node.style.textAlign = \"left\";\r\n    });\r\n\r\n    const field = row.querySelector(\"input, textarea\");\r\n    if (field) {\r\n      field.setAttribute(\"aria-invalid\", \"false\");\r\n      if (field.id \u0026\u0026 !row.querySelector(`#${field.id}-error`)) {\r\n        const err = document.createElement(\"span\");\r\n        err.id = field.id + \"-error\";\r\n        err.className = \"error\";\r\n        err.setAttribute(\"role\", \"alert\");\r\n        const hidden = document.createElement(\"span\");\r\n        hidden.className = \"accessibility-hidden\";\r\n        hidden.textContent = `${lblInner?.textContent?.trim() || lbl?.textContent?.trim() || \"Field\"}: `;\r\n        err.appendChild(hidden);\r\n        err.append(\"This field is required.\");\r\n        field.insertAdjacentElement(\"beforebegin\", err);\r\n        field.setAttribute(\"aria-describedby\", err.id);\r\n      }\r\n    }\r\n  });\r\n\r\n  /* =========================================================\r\n     8. REMOVE PLACEHOLDERS\r\n  ========================================================= */\r\n  $$(\"input[placeholder], textarea[placeholder]\").forEach(el =\u003e el.removeAttribute(\"placeholder\"));\r\n\r\n  /* =========================================================\r\n     9. CTA\r\n  ========================================================= */\r\n  const previewBtn = form.querySelector(\".js-gc-preview-button\");\r\n  if (previewBtn) {\r\n    previewBtn.classList.add(\"ct-main-cta\");\r\n    previewBtn.textContent = \"PREVIEW GIFT CARD\";\r\n    if (!document.querySelector(\".ct-cta-wrap\")) {\r\n      const ctaWrap = make(\"div\", \"ct-cta-wrap\");\r\n      const fs = form.querySelector(\"fieldset.gift-card__fieldset\") || form;\r\n      fs.insertAdjacentElement(\"afterend\", ctaWrap);\r\n      ctaWrap.appendChild(previewBtn);\r\n    }\r\n  }\r\n\r\n  /* =========================================================\r\n     10. UNSLICK (safety)\r\n  ========================================================= */\r\n  const ut = window.utag_data || {};\r\n  if (ut.page?.responsive_design_type === \"Desktop View\") {\r\n    const sliderInit = document.querySelector(\".js-designs-slider.slick-initialized\");\r\n    if (sliderInit) {\r\n      if (typeof jQuery !== \"undefined\" \u0026\u0026 jQuery(sliderInit).hasClass(\"slick-initialized\")) {\r\n        try { jQuery(sliderInit).slick(\"unslick\"); } catch (e) { console.warn(\"unslick failed\", e); }\r\n      }\r\n      const slickList = sliderInit.querySelector(\".slick-list\");\r\n      const slickTrack = slickList?.querySelector(\".slick-track\");\r\n      if (slickTrack) {\r\n        const slides = Array.from(slickTrack.querySelectorAll(\"li.slick-slide\"))\r\n          .filter(li =\u003e !li.classList.contains(\"slick-cloned\"))\r\n          .map(li =\u003e li.querySelector(\"div[data-designnameid]\"));\r\n        const grid = document.createElement(\"div\");\r\n        grid.className = \"ct-designs-grid\";\r\n        slides.forEach(s =\u003e grid.appendChild(s.cloneNode(true)));\r\n        sliderInit.innerHTML = \"\";\r\n        sliderInit.appendChild(grid);\r\n        console.log(\"[CT GiftCard] unslicked → static grid\");\r\n      }\r\n    }\r\n  }\r\n\r\n  /* =========================================================\r\n     11. CLICK → SELECT + MOVE SELECTED TO TOP (+ ANIMATE + BADGE)\r\n  ========================================================= */\r\n  const slider = document.querySelector(\".js-designs-slider\");\r\n  if (slider) {\r\n    const checkedRadio = slider.querySelector(\r\n      'input[name=\"dwfrm_giftcert_purchase_giftCertificateDesign\"]:checked'\r\n    );\r\n    if (checkedRadio) {\r\n      const card = checkedRadio.closest('[data-designnameid]');\r\n      if (card) {\r\n        card.classList.add(\"is-selected\");\r\n        const containerNode = card.closest(\"li.slick-slide\") || card;\r\n        const parent = containerNode.parentElement;\r\n        if (parent \u0026\u0026 parent.firstElementChild !== containerNode) {\r\n          parent.insertBefore(containerNode, parent.firstElementChild);\r\n        }\r\n        addSelectedBadge(card);\r\n      }\r\n    }\r\n\r\n    slider.addEventListener(\"click\", e =\u003e {\r\n      const card = e.target.closest('[data-designnameid]');\r\n      if (!card || !slider.contains(card)) return;\r\n\r\n      const designId = card.getAttribute(\"data-designnameid\");\r\n      const containerNode = card.closest(\"li.slick-slide\") || card;\r\n      const parent = containerNode.parentElement;\r\n      if (!parent) return;\r\n\r\n      const isAlreadyFirst = parent.firstElementChild === containerNode;\r\n\r\n      if (!isAlreadyFirst) {\r\n        parent.insertBefore(containerNode, parent.firstElementChild);\r\n      }\r\n\r\n      parent.querySelectorAll('[data-designnameid]').forEach(el =\u003e {\r\n        el.classList.remove(\"is-selected\");\r\n      });\r\n      card.classList.add(\"is-selected\");\r\n\r\n      // Animate the card moving up into place\r\n      card.classList.remove(\"ct-card-anim\");\r\n      void card.offsetWidth; // force reflow\r\n      card.classList.add(\"ct-card-anim\");\r\n\r\n      // Add / move badge\r\n      addSelectedBadge(card);\r\n\r\n      if (designId) {\r\n        const radio = document.querySelector(\r\n          `input[name=\"dwfrm_giftcert_purchase_giftCertificateDesign\"][value=\"${designId}\"]`\r\n        );\r\n        if (radio) {\r\n          radio.checked = true;\r\n          if (typeof Event === \"function\") {\r\n            radio.dispatchEvent(new Event(\"change\", { bubbles: true }));\r\n          }\r\n        }\r\n      }\r\n    });\r\n  }\r\n\r\n  /* =========================================================\r\n     12. Headings and class cleanup\r\n  ========================================================= */\r\n  const amountHeading = document.querySelector(\"h3.font__secondary.capitalize.bold.text-center\");\r\n  if (amountHeading) amountHeading.classList.remove(\"m-top-xl\", \"mps-p-top-m\");\r\n\r\n  const rowBottomL = document.querySelector(\".form__row.m-bottom-l.col-100\");\r\n  if (rowBottomL) rowBottomL.classList.remove(\"m-bottom-l\");\r\n\r\n  const worthEdit = document.querySelector(\".gift-card__worth-edit.js-gc-edit-section.mps-m-bottom-xl\");\r\n  if (worthEdit) worthEdit.classList.remove(\"mps-m-bottom-xl\");\r\n\r\n  const popularLabel = document.querySelector(\r\n    \".gift-card__worth-edit.js-gc-edit-section label.m-bottom-s.h4\"\r\n  );\r\n  if (popularLabel) {\r\n    popularLabel.classList.remove(\"form__label\");\r\n    popularLabel.textContent = \"Choose from some popular gifting amounts or specify your own\";\r\n  }\r\n\r\n  const nameLabelSpan = document.querySelector(\r\n    'span.form__label.form__label--checkout.m-top-m.text-left.m-right-m.m-bottom-s.h4.blue7.font__secondary'\r\n  );\r\n  if (nameLabelSpan \u0026\u0026 nameLabelSpan.textContent.trim() === \"\") {\r\n    nameLabelSpan.textContent = \"Recipients Name\";\r\n  }\r\n\r\n  const giftCardRoot = document.querySelector(\".gift-card\");\r\n  if (giftCardRoot) {\r\n    giftCardRoot.classList.add(\"p-sides-m\");\r\n    const firstChild = giftCardRoot.firstElementChild;\r\n    if (firstChild) firstChild.classList.remove(\"p-sides-m\");\r\n  }\r\n\r\n  const bottomWrap = document.querySelector(\"div.p-bottom-m\");\r\n  if (bottomWrap) bottomWrap.classList.remove(\"p-bottom-m\");\r\n\r\n  console.log(\"[CT GiftCard] v42 — done ✅\");\r\n})();\r\n","trigger":{"include_pages":[{"url":"https://www.charlestyrwhitt.com/us/gift-cards/email?qa=yes","type":"exact"}],"exclude_pages":null},"_id":"69037bb72bb4673d6c677d12"},{"uses_overlay":false,"type":"js","parametrized_definition":"(function () {\n  \"use strict\";\n\n  // PDP gate (CT standard)\n  if (!window.utag_data || !window.utag_data.page || window.utag_data.page.type !== \"product\") {\n    return;\n  }\n\n  // If no long description, add spacing\n  if ($(\".js-product-long-description\").length === 0) {\n    $(\".colour-swatching-wrapper\").addClass(\"m-top-s\");\n  }\n})();\n","trigger":{"include_pages":[{"type":"any"}],"exclude_pages":null},"_id":"694409609bd330ee8745f612"},{"uses_overlay":false,"type":"js","parametrized_definition":"(function () {\n  \"use strict\";\n\n  // ---- Config ----\n  var ONLY_SHOW_ICON_ATTRS = true;\n\n  var RUN_FLAG = \"data-ct-attrs-run\";\n  var ROOT_SEL = \".pdp-main__inner-benefits\";\n  // Text is sourced from the benefit bullets ONLY.\n  // The description paragraph (.pdp-main__benefits-description p) is deliberately excluded.\n  var LIST_SEL = \".pdp-main__benefits .benefit-content\";\n  var STYLE_ID = \"ct-pdp-icons-style\";\n\n  // ---- Page guard: ONLY run on PDP-like pages ----\n  function isProductPage() {\n    try {\n      var t = String((window.utag_data \u0026\u0026 window.utag_data.page \u0026\u0026 window.utag_data.page.type) || \"\");\n      return t.toLowerCase().indexOf(\"product\") \u003e -1;\n    } catch (e) {}\n    return false;\n  }\n  if (!isProductPage()) return;\n\n  function isShirtProduct() {\n    var id = normaliseId(getProductId());\n    return (\n      id.indexOf(\"FO\") === 0 ||\n      id.indexOf(\"FS\") === 0 ||\n      id.indexOf(\"CS\") === 0 ||\n      id.indexOf(\"SC\") === 0 ||\n      id.indexOf(\"CSR\") === 0 ||\n      id.indexOf(\"CF\") === 0\n    );\n  }\n\n  function nameHasStretchKeyword() {\n    var n = normaliseText(getProductName());\n    return (\n      n.indexOf(\"stretch\") \u003e -1 ||\n      n.indexOf(\"extens\") \u003e -1 || // FR (extensible / extensibilite)\n      n.indexOf(\"elast\") \u003e -1 // DE (elastisch / Elastan)\n    );\n  }\n\n  function upsertAttrWithCapN(attrs, attrObj, cap) {\n    if (!attrs) attrs = [];\n    if (hasAttr(attrs, attrObj.name)) return attrs;\n\n    if (attrs.length \u003c cap) {\n      attrs.unshift(attrObj);\n      return attrs;\n    }\n    attrs[cap - 1] = attrObj;\n    attrs = attrs.slice(0, cap);\n    return attrs;\n  }\n\n  function enforceCapN(attrs, cap) {\n    return (attrs || []).slice(0, cap);\n  }\n\n  // ---- Product helpers ----\n  function getProductId() {\n    try {\n      return String(\n        (window.utag_data \u0026\u0026\n          window.utag_data.products \u0026\u0026\n          window.utag_data.products[0] \u0026\u0026\n          window.utag_data.products[0].id) ||\n          \"\"\n      ).trim();\n    } catch (e) {}\n    return \"\";\n  }\n\n  function getProductName() {\n    try {\n      return String(window.utag_data.products[0].name || \"\");\n    } catch (e) {}\n    return \"\";\n  }\n\n  function normaliseId(s) {\n    return String(s || \"\").toUpperCase().replace(/[^A-Z0-9]/g, \"\");\n  }\n\n  function productIdStartsWith(prefix) {\n    return normaliseId(getProductId()).indexOf(normaliseId(prefix)) === 0;\n  }\n\n  function productIdEquals(id) {\n    return normaliseId(getProductId()) === normaliseId(id);\n  }\n\n  // ---- Umbrella / set SKU matching ----\n  // On suit set pages the URL carries an umbrella ID (e.g. SUT35RYL) while\n  // utag_data.products holds the component IDs (e.g. SUT0353RYL, SUT0354RYL).\n  // matchesSku() checks both, so a rule can target either form.\n  function getUrlProductId() {\n    try {\n      var m = String(window.location.pathname || \"\").match(/\\/([^\\/]+)\\.html$/i);\n      if (m \u0026\u0026 m[1]) return normaliseId(m[1]);\n    } catch (e) {}\n    return \"\";\n  }\n\n  function getAllProductIds() {\n    var ids = [];\n    try {\n      var list = (window.utag_data \u0026\u0026 window.utag_data.products) || [];\n      for (var i = 0; i \u003c list.length; i++) {\n        if (list[i] \u0026\u0026 list[i].id) ids.push(normaliseId(list[i].id));\n      }\n    } catch (e) {}\n    return ids;\n  }\n\n  function matchesSku(id) {\n    var target = normaliseId(id);\n    if (!target) return false;\n    if (getUrlProductId() === target) return true;\n    return getAllProductIds().indexOf(target) \u003e -1;\n  }\n\n  function normaliseText(s) {\n    return String(s || \"\")\n      .toLowerCase()\n      .normalize(\"NFD\")\n      .replace(/[\\u0300-\\u036f]/g, \"\");\n  }\n\n  function nameIncludes(phrase) {\n    var n = normaliseText(getProductName());\n    return n.indexOf(normaliseText(phrase)) \u003e -1;\n  }\n\n  function isSuitProductName() {\n    var n = normaliseText(getProductName());\n    return /\\bsuit\\b/.test(n) || /\\banzug\\b/.test(n) || /\\bcostume\\b/.test(n);\n  }\n\n  // ---- Icon map ----\n  var ICONS = {\n  \t\"100% Silk\":\n  \"https://www.charlestyrwhitt.com/on/demandware.static/-/Library-Sites-CTShirtsSharedLibrary/default/dwa855545d/merchAssets/100_Silk_ICON_Blk.svg\",\n  \t\"V-Neck Undershirt\":\n  \"https://www.charlestyrwhitt.com/on/demandware.static/-/Library-Sites-CTShirtsSharedLibrary/default/dwa855545d/merchAssets/V_Neck_Undershirt_ICON_Blk.svg\",\n  \t\"Reversible\":\n  \"https://www.charlestyrwhitt.com/on/demandware.static/-/Library-Sites-CTShirtsSharedLibrary/default/dwa855545d/merchAssets/Reversible_ICON_Blk.svg\",\n  \t\"100% Cashmere\":\n  \"https://www.charlestyrwhitt.com/on/demandware.static/-/Library-Sites-CTShirtsSharedLibrary/default/dwa855545d/merchAssets/100_Cashmere_ICON_Blk.svg\",\n\n    \"100% Cotton\":\n      \"https://www.charlestyrwhitt.com/on/demandware.static/-/Library-Sites-CTShirtsSharedLibrary/default/dw61a9f70c/merchAssets/content/Cotton_100.png\",\n    \"Non-Iron\":\n      \"https://www.charlestyrwhitt.com/on/demandware.static/-/Library-Sites-CTShirtsSharedLibrary/default/dw1300858a/merchAssets/content/non-iron.png\",\n\n    \"Stretch\":\n      \"https://www.charlestyrwhitt.com/on/demandware.static/-/Library-Sites-CTShirtsSharedLibrary/default/dwf302fabc/merchAssets/content/stretch.png\",\n    \"Cotton Stretch\":\n      \"https://www.charlestyrwhitt.com/on/demandware.static/-/Library-Sites-CTShirtsSharedLibrary/default/dwf302fabc/merchAssets/content/stretch.png\",\n\n    \"Breathable\":\n      \"https://www.charlestyrwhitt.com/on/demandware.static/-/Library-Sites-CTShirtsSharedLibrary/default/dwa855545d/merchAssets/content/All-Svg-Icons/Breathable.svg\",\n    \"Water Repellent\":\n      \"https://www.charlestyrwhitt.com/on/demandware.static/-/Library-Sites-CTShirtsSharedLibrary/default/dw471026a4/merchAssets/content/water-repellent.png\",\n    \"Stain Repellent\":\n      \"https://www.charlestyrwhitt.com/on/demandware.static/-/Library-Sites-CTShirtsSharedLibrary/default/dw1dafa7d3/merchAssets/content/stain-resistant.png\",\n    \"Stretch Waistband\":\n      \"https://www.charlestyrwhitt.com/on/demandware.static/-/Library-Sites-CTShirtsSharedLibrary/default/dwe81b2e72/merchAssets/content/stretch-waistband.svg\",\n\n    \"Temperature Regulating\":\n      \"https://www.charlestyrwhitt.com/on/demandware.static/-/Library-Sites-CTShirtsSharedLibrary/default/dwfae5c9cd/merchAssets/content/All-Svg-Icons/temperature-regulating-black.svg\",\n    \"Merino Wool\":\n      \"https://www.charlestyrwhitt.com/on/demandware.static/-/Library-Sites-CTShirtsSharedLibrary/default/dwa64e405a/merchAssets/content/All-Svg-Icons/Woolmark-black.svg\",\n    \"Machine Washable\":\n      \"https://www.charlestyrwhitt.com/on/demandware.static/-/Library-Sites-CTShirtsSharedLibrary/default/dw3bbe2e72/merchAssets/content/All-Svg-Icons/Machine-washable.svg\",\n\n    \"Super 120s Wool\":\n      \"https://www.charlestyrwhitt.com/on/demandware.static/-/Library-Sites-CTShirtsSharedLibrary/default/dw70a3ffad/merchAssets/content/Super 120s Wool.svg\",\n    \"Crease Recovery\":\n      \"https://www.charlestyrwhitt.com/on/demandware.static/-/Library-Sites-CTShirtsSharedLibrary/default/dw37f51631/merchAssets/content/Crease-Recovery.png\",\n    \"Moisture Wicking\":\n      \"https://www.charlestyrwhitt.com/on/demandware.static/-/Library-Sites-CTShirtsSharedLibrary/default/dw8e3ae4f0/merchAssets/content/Moisture-Wicking.png\",\n    \"100% Linen\":\n      \"https://www.charlestyrwhitt.com/on/demandware.static/-/Library-Sites-CTShirtsSharedLibrary/default/dw4ef09f58/merchAssets/content/All-Svg-Icons/100-linen-black.svg\",\n    \"Lightweight\":\n      \"https://www.charlestyrwhitt.com/on/demandware.static/-/Library-Sites-CTShirtsSharedLibrary/default/dw8c0d6212/merchAssets/content/All-Svg-Icons/Icon_lightweight.svg\",\n\n    \"Reda Cloth\":\n      \"https://www.charlestyrwhitt.com/on/demandware.static/-/Library-Sites-CTShirtsSharedLibrary/default/v7cd253140e1ee03cf7423b865513f234b6d499e6/merchAssets/content/Reda.svg\",\n    \"Silky Feel\":\n      \"https://www.charlestyrwhitt.com/on/demandware.static/-/Library-Sites-CTShirtsSharedLibrary/default/dwf302fabc/merchAssets/content/silky-feel.svg\",\n    \"2-Ply Supima Cotton\":\n      \"https://www.charlestyrwhitt.com/on/demandware.static/-/Library-Sites-CTShirtsSharedLibrary/default/dw61a9f70c/merchAssets/content/2ply.svg\",\n\n    \"100% Leather\":\n      \"https://www.charlestyrwhitt.com/on/demandware.static/-/Library-Sites-CTShirtsSharedLibrary/default/dw61a9f70c/merchAssets/content/Leather_Icon_Black.svg\",\n    \"100% Leather Upper\":\n      \"https://www.charlestyrwhitt.com/on/demandware.static/-/Library-Sites-CTShirtsSharedLibrary/default/dw61a9f70c/merchAssets/content/Leather_Icon_Black.svg\",\n    \"100% Leather Lined\":\n      \"https://www.charlestyrwhitt.com/on/demandware.static/-/Library-Sites-CTShirtsSharedLibrary/default/dw61a9f70c/merchAssets/content/Leather_Icon_Black.svg\",\n\n    \"Flexible Sole\":\n      \"https://www.charlestyrwhitt.com/on/demandware.static/-/Library-Sites-CTShirtsSharedLibrary/default/dwa855545d/merchAssets/content/fsole.svg\",\n    \"Insulated for Warmth\":\n      \"https://www.charlestyrwhitt.com/on/demandware.static/-/Library-Sites-CTShirtsSharedLibrary/default/dwfae5c9cd/merchAssets/content/All-Svg-Icons/Icon_InsulatedForWarmth.svg\",\n    \"Soft Touch\":\n      \"https://www.charlestyrwhitt.com/on/demandware.static/-/Library-Sites-CTShirtsSharedLibrary/default/dw8c0d6212/merchAssets/content/All-Svg-Icons/Icon_lightweight.svg\",\n    \"Collar Stiffeners\":\n      \"https://www.charlestyrwhitt.com/on/demandware.static/-/Library-Sites-CTShirtsSharedLibrary/default/dwa855545d/merchAssets/content/All-Svg-Icons/collar-stiffeners.svg\",\n    \"Natural Stretch\":\n      \"https://www.charlestyrwhitt.com/on/demandware.static/-/Library-Sites-CTShirtsSharedLibrary/default/dwf302fabc/merchAssets/content/stretch.png\",\n    \"Lightweight Fabric\":\n      \"https://www.charlestyrwhitt.com/on/demandware.static/-/Library-Sites-CTShirtsSharedLibrary/default/dw8c0d6212/merchAssets/content/All-Svg-Icons/Icon_lightweight.svg\",\n    \"Made in Italy\":\n      \"https://www.charlestyrwhitt.com/on/demandware.static/Sites-CTShirts-XBR-Site/-/en/v1768308049381/flags/4x3/it.svg\"\n  };\n\n  // ---- Localisation (DE/FR titles only) ----\n  var LOCALES = {\n   DE: {\n   \t\"V-Neck Undershirt\": \"Unterhemd\",\n   \t\"Reversible\": \"Wendbar\",\n    \"100% Cotton\": \"100% Baumwolle\",\n    \"Non-Iron\": \"Bügelfrei\",\n    \"Stretch\": \"Stretch\",\n    \"Cotton Stretch\": \"Baumwoll-Stretch\",\n    \"Breathable\": \"Atmungsaktiv\",\n    \"Water Repellent\": \"Wasserabweisend\",\n    \"Stain Repellent\": \"Fleckabweisend\",\n    \"Stretch Waistband\": \"Dehnbarer Bund\",\n    \"Temperature Regulating\": \"Temperaturregulierend\",\n    \"Merino Wool\": \"Merinowolle\",\n    \"Machine Washable\": \"Maschinenwaschbar\",\n    \"Super 120s Wool\": \"Super 120s Wolle\",\n    \"Crease Recovery\": \"Knitterarm\",                           // updated\n    \"Moisture Wicking\": \"Feuchtigkeitsableitend\",\n    \"100% Linen\": \"100% Leinen\",\n    \"Lightweight\": \"Leicht\",\n    \"Lightweight Fabric\": \"Leichter Stoff\",\n    \"Lightweight Sole\": \"Leichte Sohle\",\n    \"Reda Cloth\": \"Reda-Stoff\",\n    \"Silky Feel\": \"Seidig\",                                     // updated\n    \"2-Ply Supima Cotton\": \"Supima-Baumwolle (2-fädig)\",        // updated\n    \"100% Leather\": \"100% Leder\",\n    \"100% Leather Upper\": \"Obermaterial: 100 % Leder\",\n    \"100% Leather Lined\": \"100% ledergefüttert\",                 // updated\n    \"Flexible Sole\": \"Flexible Sohle\",\n    \"Insulated for Warmth\": \"Wärmeisolierend\",                   // updated\n    \"Soft Touch\": \"Weich im Griff\",                              // updated\n    \"Collar Stiffeners\": \"Kragenstäbchen\",\n    \"Natural Stretch\": \"Natürliche Elastizität\",                 // updated\n    \"Made in Italy\": \"Hergestellt in Italien\",\n    \"100% 2-Ply Egyptian Cotton\": \"100% ägyptische Baumwolle (2-fädig)\" // updated\n  },\n    FR: {\n    \t\"V-Neck Undershirt\": \"Sous-vêtement\",\n    \t\"Reversible\": \"Réversible\",\n      \"100% Cotton\": \"100 % coton\",\n      \"Non-Iron\": \"Sans repassage\",\n      \"Stretch\": \"Extensible\",\n      \"Cotton Stretch\": \"Coton extensible\",\n      \"Breathable\": \"Respirant\",\n      \"Water Repellent\": \"Déperlant\",\n      \"Stain Repellent\": \"Anti-taches\",\n      \"Stretch Waistband\": \"Ceinture extensible\",\n      \"Temperature Regulating\": \"Régule la température\",\n      \"Merino Wool\": \"Laine mérinos\",\n      \"Machine Washable\": \"Lavable en machine\",\n      \"Super 120s Wool\": \"Laine Super 120s\",\n      \"Crease Recovery\": \"Résistant aux plis\",\n      \"Moisture Wicking\": \"Évacuation de l’humidité\",\n      \"100% Linen\": \"100 % lin\",\n      \"Lightweight\": \"Léger\",\n      \"Lightweight Fabric\": \"Tissu léger\",\n      \"Lightweight Sole\": \"Semelle légère\",\n      \"Reda Cloth\": \"Tissu Reda\",\n      \"Silky Feel\": \"Toucher soyeux\",\n      \"2-Ply Supima Cotton\": \"Coton Supima 2 fils\",\n      \"100% Leather\": \"100 % cuir\",\n      \"100% Leather Upper\": \"Tige : 100 % cuir\",\n      \"100% Leather Lined\": \"Doublure 100 % cuir\",\n      \"Flexible Sole\": \"Semelle flexible\",\n      \"Insulated for Warmth\": \"Isolé pour la chaleur\",\n      \"Soft Touch\": \"Toucher doux\",\n      \"Collar Stiffeners\": \"Baleines de col\",\n      \"Natural Stretch\": \"Naturellement extensible\",\n      \"Made in Italy\": \"Fabriqué en Italie\",\n      \"100% 2-Ply Egyptian Cotton\": \"100 % coton égyptien 2 fils\"\n    }\n  };\n\n  function getLocaleKey() {\n    try {\n      var sl = String(\n        (window.utag_data \u0026\u0026 window.utag_data.global \u0026\u0026 window.utag_data.global.site_language) || \"\"\n      ).toLowerCase();\n      if (sl.indexOf(\"de\") \u003e -1) return \"DE\";\n      if (sl.indexOf(\"fr\") \u003e -1) return \"FR\";\n    } catch (e) {}\n    return \"EN\";\n  }\n\n  function localiseTitles(attrs) {\n    var key = getLocaleKey();\n    if (key === \"EN\") return attrs;\n    var dict = LOCALES[key];\n    if (!dict) return attrs;\n\n    return (attrs || []).map(function (a) {\n      if (a \u0026\u0026 dict[a.name]) return { name: dict[a.name], icon: a.icon };\n      return a;\n    });\n  }\n\n  // ---- Socks / trainers detectors ----\n  function isSocksProduct() {\n    var n = normaliseText(getProductName());\n    return /\\bsock(s)?\\b/.test(n) || /\\bchaussette(s)?\\b/.test(n) || /\\bsocke(n)?\\b/.test(n);\n  }\n  function isComfortSocks() {\n    var n = normaliseText(getProductName());\n    if (!isSocksProduct()) return false;\n    return /\\bcomfort\\b/.test(n) || /\\bconfort\\b/.test(n) || /\\bkomfort\\b/.test(n);\n  }\n  function isCottonRibSocks() {\n    var n = normaliseText(getProductName());\n    return (\n      /\\bcotton\\s+rib\\s+sock(s)?\\b/.test(n) ||\n      (/\\bchaussette(s)?\\b/.test(n) \u0026\u0026 /\\bcotele(e)?s?\\b/.test(n) \u0026\u0026 /\\bcoton\\b/.test(n)) ||\n      (/\\bsocke(n)?\\b/.test(n) \u0026\u0026 /\\bripp\\b/.test(n) \u0026\u0026 /\\bbaumwoll(e)?\\b/.test(n))\n    );\n  }\n  function isNoShowOrInvisibleSocks() {\n    var n = normaliseText(getProductName());\n    var isSocks =\n      /\\bsock(s)?\\b/.test(n) ||\n      /\\bchaussette(s)?\\b/.test(n) ||\n      /\\bsocke(n)?\\b/.test(n) ||\n      /\\bfu(ss|ß)ling(e)?\\b/.test(n);\n    if (!isSocks) return false;\n\n    return (\n      /\\bno\\s*show\\b/.test(n) ||\n      /\\binvisible\\b/.test(n) ||\n      /\\binvisibles?\\b/.test(n) ||\n      /\\bsocquette(s)?\\b/.test(n) ||\n      /\\bfu(ss|ß)ling(e)?\\b/.test(n)\n    );\n  }\n  function isMerinoWoolSocks() {\n    var n = normaliseText(getProductName());\n    if (!isSocksProduct()) return false;\n    return /\\bmerino\\b/.test(n) || /\\bmerinowolle\\b/.test(n) || /\\blaine\\s+merinos\\b/.test(n);\n  }\n  function isTrainersProduct() {\n  var n = normaliseText(getProductName());\n  return (\n    /\\btrainer(s)?\\b/.test(n) ||\n    /\\bsneaker(s)?\\b/.test(n) ||\n    /\\bbasket(s)?\\b/.test(n) ||\n    /\\bturnschuh(e|en)?\\b/.test(n) ||\n    /\\bsneaker\\b/.test(n)\n  );\n}\n\n  // ---- Attr helpers ----\n  function hasAttr(attrs, name) {\n    for (var i = 0; i \u003c (attrs || []).length; i++) {\n      if (attrs[i] \u0026\u0026 attrs[i].name === name) return true;\n    }\n    return false;\n  }\n  function removeAttr(attrs, name) {\n    return (attrs || []).filter(function (a) {\n      return !(a \u0026\u0026 a.name === name);\n    });\n  }\n  function upsertAttrWithCap(attrs, attrObj) {\n    if (!attrs) attrs = [];\n    if (hasAttr(attrs, attrObj.name)) return attrs;\n\n    if (attrs.length \u003c 4) {\n      attrs.unshift(attrObj);\n      return attrs;\n    }\n    attrs[attrs.length - 1] = attrObj;\n    return attrs;\n  }\n  function replaceAttr(attrs, fromName, toObj) {\n    for (var i = 0; i \u003c (attrs || []).length; i++) {\n      if (attrs[i] \u0026\u0026 attrs[i].name === fromName) attrs[i] = toObj;\n    }\n    return attrs;\n  }\n  function makeAttr(name, iconKey) {\n    return { name: name, icon: ICONS[iconKey || name] || null };\n  }\n\n  // ---- Text extraction ----\n  // Reads ONLY the benefit bullets (.pdp-main__benefits .benefit-content).\n  // The description paragraph is no longer used for pattern matching.\n  function extractText(root) {\n    var text = \"\";\n    var nodes, i;\n\n    nodes = root.querySelectorAll(LIST_SEL);\n\n    // SFCC dual-DOM fallback: if the matched root holds no bullets,\n    // read the bullets from anywhere in the document.\n    if (!nodes.length) nodes = document.querySelectorAll(LIST_SEL);\n\n    for (i = 0; i \u003c nodes.length; i++) text += \" \" + (nodes[i].textContent || \"\");\n\n    text = text.replace(/\\s+/g, \" \").trim();\n    window.ctPdpRawText = text;\n    return text;\n  }\n\n  // ---- Attribute detection rules (EN + DE + FR patterns) ----\n  // Note: patterns are intentionally keywordy + accented-safe because normaliseText isn't applied to raw text.\n  var ICON_ATTRS = [\n  \t{\n\t  name: \"100% Cashmere\",\n\t  patterns: [\n\t    // EN\n\t    /100%\\s*cashmere/i,\n\t    /pure\\s+cashmere/i,\n\n\t    // DE\n\t    /100%\\s*kaschmir/i,\n\t    /\\breines\\s+kaschmir\\b/i,\n\n\t    // FR\n\t    /100%\\s*cachemire/i,\n\t    /\\bpur\\s+cachemire\\b/i\n\t  ]\n\t},\n\t    {\n      name: \"100% Cotton\",\n      patterns: [\n        // EN\n        /100%\\s*(?:\\d+\\s*-\\s*ply|\\d+\\s*ply)?\\s*cotton/i,\n        /100%\\s*(?:two\\s*ply|2\\s*ply)?\\s*cotton/i,\n        /pure\\s+cotton/i,\n        // DE\n        /100%\\s*(?:\\d+\\s*-\\s*f(?:a|ä)dige|\\d+\\s*f(?:a|ä)dige)?\\s*baumwoll/i,\n        /100%\\s*baumwoll/i,\n        /\\breine\\s+baumwoll(e)?\\b/i,\n        // FR\n        /100%\\s*coton/i,\n        /\\bpur\\s+coton\\b/i,\n        /\\b100\\s*%\\s*coton\\b/i\n      ]\n    },\n    {\n  name: \"100% Silk\",\n  patterns: [\n    // EN\n    /100%\\s*silk/i,\n    /pure\\s+silk/i,\n\n    // DE\n    /100%\\s*seide/i,\n    /\\breine\\s+seide\\b/i,\n\n    // FR\n    /100%\\s*soie/i,\n    /\\bpur(e)?\\s+soie\\b/i\n  ]\n},\n    {\n      name: \"Soft Touch\",\n      patterns: [\n        // EN\n        /fine\\s+mercerised\\s+cotton/i,\n        /brushed\\s+for\\s+softness/i,\n        /brushed\\s+on\\s+both\\s+sides/i,\n        /loungewear[-\\s]?like\\s+softness/i,\n        // DE\n        /\\bweich(er|es|e)?\\b/i,\n        /\\bsoft(er|es|e)?\\s+griff\\b/i,\n        /\\bangerauht\\b/i,\n        /\\bgeb[uü]rstet\\b/i,\n        // FR\n        /\\btoucher\\s+doux\\b/i,\n        /\\bdoux\\s+au\\s+toucher\\b/i,\n        /\\bgratt[eé]\\b/i,\n        /\\bbross[eé]\\b/i\n      ]\n    },\n    {\n      name: \"100% Leather Lined\",\n      patterns: [\n        // EN\n        /100%\\s*leather\\s+lining/i,\n        /\\bfully\\s+leather\\s+lined\\b/i,\n        /\\bleather\\s+lined\\b/i,\n        // DE\n        /\\b100%\\s*leder(futter|futtern|gefuttert)\\b/i,\n        /\\bvollst[aä]ndig\\s+ledergefuttert\\b/i,\n        /\\bleder(futter|gefuttert)\\b/i,\n        // FR\n        /\\bdoublure\\s+100%\\s*cuir\\b/i,\n        /\\benti[eè]rement\\s+doubl[eé]\\s+cuir\\b/i,\n        /\\bdoubl[eé]\\s+cuir\\b/i\n      ]\n    },\n    {\n      name: \"Flexible Sole\",\n      patterns: [\n        // EN\n        /\\bflexible\\b[\\s-]*(?:nubuck\\s+)?sole\\b/i,\n        /\\bflexible\\s+sole\\b/i,\n        /\\bflexible\\b[\\s-]*(?:leather\\s+)?insole(?:s)?\\b/i,\n        /\\bsole(?:s)?\\b[\\s\\S]{0,60}\\bflexib(?:le|ility)\\b/i,\n        // DE\n        /\\bflexibl(e|er|es|en)?\\s+sohle\\b/i,\n        /\\bf(?:l|lex)exibilit[aä]t\\b/i,\n        /\\beinlegesohle\\b[\\s\\S]{0,40}\\bflexibl/i,\n        // FR\n        /\\bsemelle\\s+flexible\\b/i,\n        /\\bflexibilit[eé]\\b/i,\n        /\\bsemelle\\b[\\s\\S]{0,60}\\bflexibl/i\n      ]\n    },\n    {\n      name: \"100% Leather\",\n      patterns: [\n        // EN\n        /\\bupper:\\s*leather\\b/i,\n        /100%\\s+[\\w-]+(?:\\s+[\\w-]+){0,3}\\s+leather/i,\n        /\\b100\\s*percent\\s+[\\w-]+(?:\\s+[\\w-]+){0,3}\\s+leather\\b/i,\n        /100%\\s*leather(?!\\s+lining)\\b/i,\n        // DE\n        /\\bober(material)?:\\s*leder\\b/i,\n        /\\b100%\\s*leder\\b/i,\n        /\\bvollleder\\b/i,\n        // FR\n        /\\btige\\s*:\\s*cuir\\b/i,\n        /\\b100%\\s*cuir\\b/i,\n        /\\ben\\s+cuir\\b/i\n      ]\n    },\n    {\n      name: \"2-Ply Supima Cotton\",\n      patterns: [\n        // EN\n        /2[-\\s]*ply\\s+supima/i,\n        /supima\\s+cotton.*2[-\\s]*ply/i,\n        // DE\n        /2[-\\s]*(?:f(?:a|ä)dig|lagig)\\s+supima/i,\n        /supima.*2[-\\s]*(?:f(?:a|ä)dig|lagig)/i,\n        // FR\n        /supima.*2\\s*fils/i,\n        /2\\s*fils.*supima/i\n      ]\n    },\n    {\n\t  name: \"Reversible\",\n\t  patterns: [\n\t    // EN\n\t    /\\breversible\\b/i,\n\n\t    // DE\n\t    /\\bwendbar\\b/i,\n\n\t    // FR\n\t    /\\br[eé]versible\\b/i\n\t  ]\n\t},\n    {\n      name: \"100% Linen\",\n      patterns: [\n        // EN\n        /100%\\s*linen/i,\n        /pure\\s+linen/i,\n        // DE\n        /100%\\s*leinen/i,\n        /\\breines\\s+leinen\\b/i,\n        // FR\n        /100%\\s*lin/i,\n        /\\bpur\\s+lin\\b/i\n      ]\n    },\n    {\n      name: \"Non-Iron\",\n      patterns: [\n        // EN\n        /non[-\\s]?iron/i,\n        /easy[-\\s]?iron/i,\n        /no\\s+ironing/i,\n        /crease[-\\s]?free/i,\n        // DE\n        /\\bb[üu]gelfrei\\b/i,\n        /\\bleicht\\s+zu\\s+b[üu]geln\\b/i,\n        /\\bohne\\s+b[üu]geln\\b/i,\n        /\\bknitterfrei\\b/i,\n        // FR\n        /\\bsans\\s+repassage\\b/i,\n        /\\bfacile\\s+a\\s+repasser\\b/i,\n        /\\bne\\s+se\\s+repass(e|ent)\\s+pas\\b/i,\n        /\\bsans\\s+pli(s)?\\b/i\n      ]\n    },\n    {\n      name: \"Stretch\",\n      patterns: [\n        // EN\n        /\\bstretch\\b/i,\n        /with\\s+stretch/i,\n        /added\\s+stretch/i,\n        /\\blycra\\b/i,\n        /\\belastane\\b/i,\n        // DE\n        /\\belastan\\b/i,\n        /\\belastisch\\b/i,\n        /\\bmit\\s+stretch\\b/i,\n        // FR\n        /\\bextensible\\b/i,\n        /\\b(avec|ajout\\s+de)\\s+stretch\\b/i,\n        /\\b[ée]lasthanne\\b/i\n      ]\n    },\n    {\n      name: \"Breathable\",\n      patterns: [\n        // EN\n        /breathable/i,\n        /breathability/i,\n        /naturally\\s+breathable/i,\n        /keeps?\\s+you\\s+cool/i,\n        // DE\n        /\\batmungsaktiv\\b/i,\n        /\\b(luft|klima)durchl[aä]ssig\\b/i,\n        /\\bh[aä]lt\\s+(sie|dich)\\s+k[üu]hl\\b/i,\n        // FR\n        /\\brespirant(e|s)?\\b/i,\n        /\\blaisse\\s+respirer\\b/i,\n        /\\b(a[eè]re|aeration)\\b/i\n      ]\n    },\n    {\n      name: \"Moisture Wicking\",\n      patterns: [\n        // EN\n        /moisture[-\\s]?wick/i,\n        /wicking/i,\n        // DE\n        /\\bfeuchtigkeitsableitend\\b/i,\n        /\\bfeuchtigkeit\\b[\\s\\S]{0,20}\\bableit/i,\n        /\\bschwei(ss|ß)(?:ableitend|transport)\\b/i,\n        // FR\n        /\\b[eé]vacuation\\s+de\\s+l['’]humidit[eé]\\b/i,\n        /\\banti[-\\s]?transpiration\\b/i,\n        /\\btranspiration\\b[\\s\\S]{0,30}\\b(evacue|[eé]vacuation)\\b/i\n      ]\n    },\n    {\n      name: \"Water Repellent\",\n      patterns: [\n        // EN\n        /water[-\\s]?repell/i,\n        /water[-\\s]?resist/i,\n        /shower[-\\s]?resist/i,\n        /rain[-\\s]?resist/i,\n        // DE\n        /\\bwasserabweisend\\b/i,\n        /\\bregenabweisend\\b/i,\n        /\\bwasserfest\\b/i,\n        // FR\n        /\\bd[eé]perlant(e|s)?\\b/i,\n        /\\br[eé]sistant\\s+(a|au)\\s+l['’]eau\\b/i,\n        /\\bimperm[eé]able\\b/i\n      ]\n    },\n    {\n      name: \"Lightweight\",\n      patterns: [\n        // EN\n        /light[-\\s]?weight/i,\n        /lighter\\s+weight/i,\n        // DE\n        /\\bleicht\\b/i,\n        /\\bleichtgewicht\\b/i,\n        /\\bgeringes\\s+gewicht\\b/i,\n        // FR\n        /\\bl[eé]ger\\b/i,\n        /\\bl[eé]g[eè]ret[eé]\\b/i,\n        /\\bpoids\\s+l[eé]ger\\b/i\n      ]\n    },\n    {\n      name: \"Stain Repellent\",\n      patterns: [\n        // EN\n        /stain[-\\s]?resist/i,\n        /stain[-\\s]?repell/i,\n        // DE\n        /\\bfleckabweisend\\b/i,\n        /\\bschmutzabweisend\\b/i,\n        // FR\n        /\\banti[-\\s]?tache(s)?\\b/i,\n        /\\bresiste\\s+aux\\s+taches\\b/i\n      ]\n    },\n    {\n      name: \"Stretch Waistband\",\n      patterns: [\n        // EN\n        /stretch\\s+waistband/i,\n        /comfort\\s+waist/i,\n        // DE\n        /\\bdehnbarer\\s+bund\\b/i,\n        /\\bkomfortbund\\b/i,\n        /\\bstretchbund\\b/i,\n        // FR\n        /\\bceinture\\s+extensible\\b/i,\n        /\\btaille\\s+extensible\\b/i,\n        /\\bceinture\\s+stretch\\b/i\n      ]\n    },\n    {\n      name: \"Temperature Regulating\",\n      patterns: [\n        // EN\n        /temperature[-\\s]?regulat/i,\n        /thermo[-\\s]?regulat/i,\n        // DE\n        /\\btemperaturregulierend\\b/i,\n        /\\btemperatur\\b[\\s\\S]{0,20}\\bregulier/i,\n        /\\bthermo\\b/i,\n        // FR\n        /\\br[eé]gulation\\s+de\\s+la\\s+temp[eé]rature\\b/i,\n        /\\bthermo[-\\s]?r[eé]gulation\\b/i,\n        /\\bthermique\\b/i\n      ]\n    },\n    {\n      name: \"Merino Wool\",\n      patterns: [\n        // EN\n        /merino/i,\n        // DE\n        /\\bmerinowolle\\b/i,\n        // FR\n        /\\blaine\\s+m[eé]rinos\\b/i\n      ]\n    },\n    {\n      name: \"Machine Washable\",\n      patterns: [\n        // EN\n        /machine[-\\s]?wash/i,\n        /machine\\s+washable/i,\n        /easy\\s+care/i,\n        // DE\n        /\\bmaschinenwaschbar\\b/i,\n        /\\bmaschinenw[aä]sche\\b/i,\n        /\\bpflegeleicht\\b/i,\n        // FR\n        /\\blavable\\s+en\\s+machine\\b/i,\n        /\\blavage\\s+en\\s+machine\\b/i,\n        /\\bentretien\\s+facile\\b/i\n      ]\n    },\n    {\n      name: \"Super 120s Wool\",\n      patterns: [\n        // EN\n        /super\\s*120/i,\n        /120s\\s+wool/i,\n        // DE\n        /super\\s*120/i,\n        /120s\\s+wolle/i,\n        // FR\n        /super\\s*120/i,\n        /laine\\s+super\\s*120/i\n      ]\n    },\n    {\n      name: \"Reda Cloth\",\n      patterns: [\n        // EN/DE/FR: brand name is stable\n        /reda\\b/i\n      ]\n    },\n    {\n      name: \"Crease Recovery\",\n      patterns: [\n        // EN\n        /crease[-\\s]?recovery/i,\n        /crease[-\\s]?resistant/i,\n        // DE\n        /\\bknittererholung\\b/i,\n        /\\bknitterarm\\b/i,\n        /\\bknitter\\b[\\s\\S]{0,20}\\b(erhol|resist)\\b/i,\n        // FR\n        /\\br[eé]sistant\\s+aux\\s+plis\\b/i,\n        /\\banti[-\\s]?plis\\b/i\n      ]\n    }\n  ];\n\n  var EXTRA_ATTRS = [\n    {\n      name: \"Silky Feel\",\n      patterns: [\n        // EN\n        /silky[\\s-]*feel/i,\n        // DE\n        /\\bseid(en|ig)\\b/i,\n        /\\bseidig\\b/i,\n        // FR\n        /\\btoucher\\s+soyeux\\b/i,\n        /\\bsoyeux\\b/i\n      ]\n    }\n  ];\n\n  function dedupePush(list, attr) {\n    for (var i = 0; i \u003c list.length; i++) if (list[i].name === attr.name) return;\n    list.push(attr);\n  }\n\n  function findAttributes(text) {\n    var attrs = [];\n    var i, j, a, p;\n\n    for (i = 0; i \u003c ICON_ATTRS.length; i++) {\n      a = ICON_ATTRS[i];\n      for (j = 0; j \u003c a.patterns.length; j++) {\n        p = a.patterns[j];\n        if (p.test(text)) {\n          dedupePush(attrs, a);\n          break;\n        }\n      }\n    }\n\n    for (i = 0; i \u003c EXTRA_ATTRS.length; i++) {\n      if (attrs.length \u003e= 4) break;\n      a = EXTRA_ATTRS[i];\n      for (j = 0; j \u003c a.patterns.length; j++) {\n        p = a.patterns[j];\n        if (p.test(text)) {\n          dedupePush(attrs, a);\n          break;\n        }\n      }\n    }\n\n    var mapped = [];\n    for (i = 0; i \u003c attrs.length \u0026\u0026 i \u003c 4; i++) {\n      a = attrs[i];\n      mapped.push({ name: a.name, icon: ICONS[a.name] || null });\n    }\n\n    if (ONLY_SHOW_ICON_ATTRS) {\n      mapped = mapped.filter(function (attr) {\n        return !!attr.icon;\n      });\n    }\n\n    return mapped;\n  }\n\n  // ---- Product-specific rules ----\n  function applyProductSpecificRules(attrs) {\n    var raw = String(window.ctPdpRawText || \"\");\n    var isSuit = isSuitProductName();\n\n\t    var isPureSilk =\n\t  /100%\\s*silk/i.test(raw) ||\n\t  /100%\\s*seide/i.test(raw) ||\n\t  /100%\\s*soie/i.test(raw);\n\n\tif (isPureSilk) {\n\t  attrs = upsertAttrWithCap(attrs, makeAttr(\"100% Silk\", \"100% Silk\"));\n\n\t  // Clean up conflicting materials\n\t  attrs = removeAttr(attrs, \"100% Cotton\");\n\t  attrs = removeAttr(attrs, \"100% Linen\");\n\t  attrs = removeAttr(attrs, \"Merino Wool\");\n\t}\n\n    function replaceLightweightWithFabric() {\n      if (hasAttr(attrs, \"Lightweight\")) {\n        attrs = replaceAttr(attrs, \"Lightweight\", makeAttr(\"Lightweight Fabric\", \"Lightweight Fabric\"));\n      }\n      return attrs;\n    }\n\n\t    if (productIdEquals(\"ACU0220WHT\")) {\n\t  attrs = upsertAttrWithCap(attrs, makeAttr(\"V-Neck Undershirt\", \"V-Neck Undershirt\"));\n\t}\n\n    if (productIdEquals(\"TRC0285NAV\")) {\n      attrs = removeAttr(attrs, \"Temperature Regulating\");\n      attrs = upsertAttrWithCap(attrs, makeAttr(\"Moisture Wicking\", \"Moisture Wicking\"));\n      attrs = upsertAttrWithCap(attrs, makeAttr(\"Stretch Waistband\", \"Stretch Waistband\"));\n    }\n\n    if (productIdEquals(\"OUC0089NAV\")) {\n      attrs = upsertAttrWithCap(attrs, makeAttr(\"Insulated for Warmth\", \"Insulated for Warmth\"));\n    }\n\n    if (productIdEquals(\"OUC0093NAV\")) {\n      attrs = removeAttr(attrs, \"Merino Wool\");\n    }\n\n    if (productIdEquals(\"OUR0033NAV\")) {\n      attrs = removeAttr(attrs, \"Lightweight\");\n      attrs = removeAttr(attrs, \"Lightweight Fabric\");\n    }\n\n    if (productIdEquals(\"OUC0088NAV\")) {\n      attrs = removeAttr(attrs, \"Lightweight\");\n      attrs = removeAttr(attrs, \"Lightweight Fabric\");\n    }\n\n    if (productIdEquals(\"OUC0081NAV\")) {\n      attrs = upsertAttrWithCap(attrs, makeAttr(\"Insulated for Warmth\", \"Insulated for Warmth\"));\n    }\n\n    if (productIdEquals(\"OUR0036NAV\")) {\n      attrs = upsertAttrWithCap(attrs, makeAttr(\"Machine Washable\", \"Machine Washable\"));\n    }\n\n    if (productIdEquals(\"OUC0085BLK\")) {\n      attrs = upsertAttrWithCap(attrs, makeAttr(\"Insulated for Warmth\", \"Insulated for Warmth\"));\n    }\n\n    if (nameIncludes(\"performance chinos\") || nameIncludes(\"performance-chinos\")) {\n      attrs = removeAttr(attrs, \"Temperature Regulating\");\n      attrs = upsertAttrWithCap(attrs, makeAttr(\"Moisture Wicking\", \"Moisture Wicking\"));\n      attrs = upsertAttrWithCap(attrs, makeAttr(\"Stretch Waistband\", \"Stretch Waistband\"));\n    }\n\n    if (nameIncludes(\"puffer coat\")) {\n      attrs = upsertAttrWithCap(attrs, makeAttr(\"Insulated for Warmth\", \"Insulated for Warmth\"));\n    }\n    if (nameIncludes(\"lightweight quilted jacket\") || nameIncludes(\"diamond quilted jacket\")) {\n      attrs = upsertAttrWithCap(attrs, makeAttr(\"Insulated for Warmth\", \"Insulated for Warmth\"));\n    }\n    if (nameIncludes(\"flannel gilet\")) {\n      attrs = removeAttr(attrs, \"Merino Wool\");\n    }\n    if (nameIncludes(\"3 in 1\") \u0026\u0026 (nameIncludes(\"raincoat\") || nameIncludes(\"rain mac\") || nameIncludes(\"rain\"))) {\n      attrs = removeAttr(attrs, \"Lightweight\");\n      attrs = removeAttr(attrs, \"Lightweight Fabric\");\n    }\n    if (nameIncludes(\"wool funnel neck\")) {\n      attrs = removeAttr(attrs, \"Lightweight\");\n      attrs = removeAttr(attrs, \"Lightweight Fabric\");\n    }\n    if (nameIncludes(\"padded raincoat\")) {\n      attrs = upsertAttrWithCap(attrs, makeAttr(\"Machine Washable\", \"Machine Washable\"));\n    }\n\n    if (productIdStartsWith(\"SH\")) {\n      attrs = replaceAttr(attrs, \"100% Leather\", makeAttr(\"100% Leather Upper\", \"100% Leather Upper\"));\n      if (/sole/i.test(raw) || /sohle/i.test(raw) || /semelle/i.test(raw)) {\n        attrs = replaceAttr(attrs, \"Lightweight\", makeAttr(\"Lightweight Sole\", \"Lightweight\"));\n      }\n    }\n\n    if (hasAttr(attrs, \"100% Leather\") || hasAttr(attrs, \"100% Leather Upper\")) {\n      attrs = removeAttr(attrs, \"100% Leather Lined\");\n    }\n\n    if (hasAttr(attrs, \"Flexible Sole\")) {\n      attrs = removeAttr(attrs, \"Lightweight Sole\");\n    }\n\n    if (isSocksProduct()) {\n      attrs = upsertAttrWithCap(attrs, makeAttr(\"Breathable\", \"Breathable\"));\n    }\n\n    if (isSocksProduct() \u0026\u0026 (/luxury\\s+cotton/i.test(raw) || /luxus.*baumwoll/i.test(raw) || /coton.*luxe/i.test(raw))) {\n      attrs = upsertAttrWithCap(attrs, makeAttr(\"Soft Touch\", \"Soft Touch\"));\n    }\n\n    if (isCottonRibSocks()) {\n      attrs = removeAttr(attrs, \"Temperature Regulating\");\n      attrs = upsertAttrWithCap(attrs, makeAttr(\"Soft Touch\", \"Soft Touch\"));\n    }\n\n    if (isComfortSocks()) {\n      attrs = upsertAttrWithCap(attrs, makeAttr(\"Soft Touch\", \"Soft Touch\"));\n    }\n\n    if (isNoShowOrInvisibleSocks()) {\n      attrs = (attrs || []).filter(function (a) {\n        if (!a || !a.name) return true;\n        var nn = String(a.name).toLowerCase();\n        return nn !== \"lightweight\" \u0026\u0026 nn !== \"lightweight sole\";\n      });\n      attrs = upsertAttrWithCap(attrs, makeAttr(\"Breathable\", \"Breathable\"));\n      attrs = upsertAttrWithCap(attrs, makeAttr(\"Soft Touch\", \"Soft Touch\"));\n    }\n\n    if (isMerinoWoolSocks()) {\n      attrs = upsertAttrWithCap(attrs, makeAttr(\"Temperature Regulating\", \"Temperature Regulating\"));\n      attrs = removeAttr(attrs, \"Merino Wool\");\n    }\n\n    if (isTrainersProduct()) {\n      attrs = upsertAttrWithCap(attrs, makeAttr(\"Breathable\", \"Breathable\"));\n      attrs = upsertAttrWithCap(attrs, makeAttr(\"Flexible Sole\", \"Flexible Sole\"));\n    }\n\n    if (productIdEquals(\"SHS0004CHC\")) {\n      attrs = upsertAttrWithCap(attrs, makeAttr(\"Breathable\", \"Breathable\"));\n      attrs = upsertAttrWithCap(attrs, makeAttr(\"Flexible Sole\", \"Flexible Sole\"));\n    }\n\n    if (productIdEquals(\"SHW0252LGY\")) {\n      attrs = upsertAttrWithCap(attrs, makeAttr(\"Lightweight\", \"Lightweight\"));\n      attrs = upsertAttrWithCap(attrs, makeAttr(\"Breathable\", \"Breathable\"));\n      attrs = upsertAttrWithCap(attrs, makeAttr(\"Flexible Sole\", \"Flexible Sole\"));\n    }\n\n    if (productIdEquals(\"SHW0200BRN\")) {\n      attrs = upsertAttrWithCap(attrs, makeAttr(\"Breathable\", \"Breathable\"));\n      attrs = upsertAttrWithCap(attrs, makeAttr(\"Flexible Sole\", \"Flexible Sole\"));\n    }\n\n    if (hasAttr(attrs, \"Flexible Sole\")) {\n      attrs = removeAttr(attrs, \"Lightweight Sole\");\n    }\n\n    if (productIdStartsWith(\"AC\") \u0026\u0026 !productIdEquals(\"ACR0009NAV\")) {\n      attrs = removeAttr(attrs, \"Stretch\");\n      attrs = removeAttr(attrs, \"Cotton Stretch\");\n    }\n\n    if (productIdEquals(\"ACR0009NAV\")) {\n      attrs = upsertAttrWithCap(attrs, makeAttr(\"Stretch\", \"Stretch\"));\n    }\n\n    if (productIdEquals(\"ACU0200MNV\")) {\n      attrs = removeAttr(attrs, \"Stretch\");\n      attrs = upsertAttrWithCap(attrs, makeAttr(\"Cotton Stretch\", \"Cotton Stretch\"));\n      attrs = upsertAttrWithCap(attrs, makeAttr(\"Soft Touch\", \"Soft Touch\"));\n    }\n\n    if (productIdEquals(\"ACC0223NAV\") || productIdEquals(\"ACC0233NAV\")) {\n      attrs = removeAttr(attrs, \"Lightweight\");\n      attrs = removeAttr(attrs, \"Lightweight Sole\");\n      attrs = upsertAttrWithCap(attrs, makeAttr(\"Soft Touch\", \"Soft Touch\"));\n    }\n\n    if (productIdEquals(\"ACG0008BRN\")) {\n      attrs = removeAttr(attrs, \"100% Leather\");\n      attrs = removeAttr(attrs, \"100% Leather Upper\");\n      attrs = removeAttr(attrs, \"100% Leather Lined\");\n    }\n\n\n\n    if (nameIncludes(\"natural stretch twill\")) {\n      attrs = upsertAttrWithCap(attrs, makeAttr(\"Merino Wool\", \"Merino Wool\"));\n    }\n\n    if (nameIncludes(\"seasonal design\")) {\n      attrs = removeAttr(attrs, \"Merino Wool\");\n      attrs = removeAttr(attrs, \"Super 120s Wool\");\n    }\n\n    if (nameIncludes(\"100% linen\") \u0026\u0026 isSuit) {\n      attrs = upsertAttrWithCap(attrs, makeAttr(\"Breathable\", \"Breathable\"));\n      attrs = replaceLightweightWithFabric();\n    }\n\n    if (nameIncludes(\"Ultimate Non-Iron Chinos\")) {\n      attrs = removeAttr(attrs, \"Breathable\");\n      attrs = upsertAttrWithCap(attrs, makeAttr(\"Stretch Waistband\", \"Stretch Waistband\"));\n    }\n\n    if (nameIncludes(\"ultimate performance\") \u0026\u0026 isSuit) {\n      attrs = removeAttr(attrs, \"Temperature Regulating\");\n      attrs = removeAttr(attrs, \"Stretch\");\n      attrs = removeAttr(attrs, \"Cotton Stretch\");\n      attrs = upsertAttrWithCap(attrs, makeAttr(\"Natural Stretch\", \"Natural Stretch\"));\n    }\n\n    if (nameIncludes(\"italian\") \u0026\u0026 isSuit) {\n      attrs = replaceLightweightWithFabric();\n    }\n\n    if (nameIncludes(\"morning suit\")) {\n      attrs = removeAttr(attrs, \"Breathable\");\n    }\n\n    if (nameIncludes(\"wool texture\")) {\n      attrs = removeAttr(attrs, \"Breathable\");\n    }\n\n    if (nameIncludes(\"proper blazer\")) {\n      attrs = removeAttr(attrs, \"Breathable\");\n    }\n\n    if (nameIncludes(\"cotton stretch\") \u0026\u0026 !isSuit) {\n      attrs = removeAttr(attrs, \"100% Cotton\");\n    }\n\n    if (nameIncludes(\"linen cotton\") \u0026\u0026 !isSuit) {\n      attrs = upsertAttrWithCap(attrs, makeAttr(\"Lightweight\", \"Lightweight\"));\n    }\n\n    if (nameIncludes(\"wool silk\") \u0026\u0026 !isSuit) {\n      attrs = upsertAttrWithCap(attrs, makeAttr(\"Soft Touch\", \"Soft Touch\"));\n    }\n\n\n    if (nameIncludes(\"brushed flannel\")) {\n      attrs = upsertAttrWithCap(attrs, makeAttr(\"Soft Touch\", \"Soft Touch\"));\n    }\n\n    if (nameHasStretchKeyword()) {\n      var nn = normaliseText(getProductName());\n\n      if (nn.indexOf(\"cotton stretch\") \u003e -1 || nn.indexOf(\"baumwoll-stretch\") \u003e -1 || nn.indexOf(\"coton stretch\") \u003e -1) {\n        attrs = removeAttr(attrs, \"Stretch\");\n        attrs = upsertAttrWithCap(attrs, makeAttr(\"Cotton Stretch\", \"Cotton Stretch\"));\n      } else if (!hasAttr(attrs, \"Cotton Stretch\")) {\n        attrs = upsertAttrWithCap(attrs, makeAttr(\"Stretch\", \"Stretch\"));\n      }\n    }\n\n    if (productIdEquals(\"FOL0240WHT\") || productIdEquals(\"FOL0242WHT\")) {\n      attrs = removeAttr(attrs, \"Lightweight\");\n      attrs = removeAttr(attrs, \"Lightweight Fabric\");\n      attrs = removeAttr(attrs, \"Lightweight Sole\");\n    }\n\n    if (productIdEquals(\"FOR2362WHT\")) {\n      attrs = upsertAttrWithCap(attrs, makeAttr(\"100% 2-Ply Egyptian Cotton\", \"100% Cotton\"));\n    }\n\n    if (productIdEquals(\"JEP0340NAV\")) {\n      attrs = removeAttr(attrs, \"Lightweight\");\n      attrs = removeAttr(attrs, \"Lightweight Fabric\");\n      attrs = removeAttr(attrs, \"Lightweight Sole\");\n    }\n\n     // ---- Slip-on loafers (explicit SKU override) ----\n\tvar LOAFER_IDS = [\n\t  \"SHW0252LGY\",\n\t  \"SHW0252CHK\",\n\t  \"SHW0252LBN\",\n\t  \"SHW0252NAV\",\n\t  \"SHW0264CHC\",\n\t  \"SHW0268OCE\"\n\t];\n\n\tif (LOAFER_IDS.indexOf(normaliseId(getProductId())) \u003e -1) {\n\t  attrs = [\n\t    makeAttr(\"Flexible Sole\", \"Flexible Sole\"),\n\t    makeAttr(\"Breathable\", \"Breathable\"),\n\t    makeAttr(\"Lightweight\", \"Lightweight\"),\n\t    makeAttr(\"100% Leather Upper\", \"100% Leather Upper\")\n\t  ];\n\t}\n\n    // ---- Late SKU overrides ----\n    // Placed after all name-based rules so they take precedence.\n\n    // Reda cloth: Italian luxury suiting SKUs\n    var REDA_IDS = [\n      \"SUL0420IDG\", // Indigo slim fit Italian luxury suit jacket\n      \"SUL0421IDG\", // Indigo slim fit Italian luxury suit trouser\n      \"SUL0420TPE\", // Taupe slim fit Italian luxury suit jacket\n      \"SUL0421TPE\", // Taupe slim fit Italian luxury suit trouser\n      \"SUL0422TPE\", // Taupe slim fit Italian luxury waistcoat\n      \"SUL0423NAV\", // Navy birdseye slim fit Italian luxury suit jacket\n      \"SUL0424NAV\", // Navy birdseye slim fit Italian luxury suit trouser\n      \"SUL0423CHA\", // Charcoal birdseye slim fit Italian luxury suit jacket\n      \"SUL0424CHA\"  // Charcoal birdseye slim fit Italian luxury suit trouser\n    ];\n\n    for (var ri = 0; ri \u003c REDA_IDS.length; ri++) {\n      if (matchesSku(REDA_IDS[ri])) {\n        attrs = upsertAttrWithCap(attrs, makeAttr(\"Reda Cloth\", \"Reda Cloth\"));\n        break;\n      }\n    }\n\n    // Swap one attribute for another, keeping the original slot position.\n    function swapAttr(list, fromName, toName) {\n      if (hasAttr(list, toName)) {\n        return removeAttr(list, fromName);\n      }\n      if (hasAttr(list, fromName)) {\n        return replaceAttr(list, fromName, makeAttr(toName, toName));\n      }\n      return upsertAttrWithCap(list, makeAttr(toName, toName));\n    }\n\n    // SES0012SLV Linen Cotton Jacket, Silver: add Breathable\n    // SES0012GRN Linen Cotton Jacket, Green: add Breathable\n    if (matchesSku(\"SES0012SLV\") || matchesSku(\"SES0012GRN\")) {\n      attrs = upsertAttrWithCap(attrs, makeAttr(\"Breathable\", \"Breathable\"));\n    }\n\n    // SEB0063TPE Proper Blazer, Taupe: add Crease Recovery\n    if (matchesSku(\"SEB0063TPE\")) {\n      attrs = upsertAttrWithCap(attrs, makeAttr(\"Crease Recovery\", \"Crease Recovery\"));\n    }\n\n    // SUT35RYL / SUT53GRY (umbrella suit IDs): show Stretch instead of Natural Stretch\n    if (matchesSku(\"SUT35RYL\") || matchesSku(\"SUT53GRY\")) {\n      attrs = swapAttr(attrs, \"Natural Stretch\", \"Stretch\");\n      attrs = removeAttr(attrs, \"Cotton Stretch\");\n    }\n\n    // SES0009TPE / SES0009NAV Cotton Stretch Jacket: show Stretch instead of Cotton Stretch\n    if (matchesSku(\"SES0009TPE\") || matchesSku(\"SES0009NAV\")) {\n      attrs = swapAttr(attrs, \"Cotton Stretch\", \"Stretch\");\n    }\n\n    // Shirts: cap at 4 and prioritise Machine Washable if mentioned in copy (EN+DE+FR)\n    if (isShirtProduct()) {\n      var wantsMW =\n        /machine[-\\s]?wash/i.test(raw) ||\n        /machine\\s+washable/i.test(raw) ||\n        /easy\\s+care/i.test(raw) ||\n        /maschinenwaschbar/i.test(raw) ||\n        /pflegeleicht/i.test(raw) ||\n        /lavable\\s+en\\s+machine/i.test(raw) ||\n        /lavage\\s+en\\s+machine/i.test(raw);\n\n      if (wantsMW) {\n        attrs = upsertAttrWithCapN(attrs, makeAttr(\"Machine Washable\", \"Machine Washable\"), 4);\n      }\n\n      attrs = enforceCapN(attrs, 4);\n\n      if (wantsMW \u0026\u0026 !hasAttr(attrs, \"Machine Washable\")) {\n        attrs[3] = makeAttr(\"Machine Washable\", \"Machine Washable\");\n      }\n    }\n\n    // Cashmere products: always Breathable + Temperature Regulating (EN+DE+FR)\n    var pn = normaliseText(getProductName());\n\n\t   var isCashmere =\n\t  pn.indexOf(\"cashmere\") \u003e -1 ||\n\t  pn.indexOf(\"kaschmir\") \u003e -1 ||\n\t  pn.indexOf(\"cachemire\") \u003e -1;\n\n\tvar isPureCashmere =\n\t  /100%\\s*cashmere/i.test(raw) ||\n\t  /100%\\s*kaschmir/i.test(raw) ||\n\t  /100%\\s*cachemire/i.test(raw);\n\n\tif (isCashmere) {\n\t  if (isPureCashmere) {\n\t    attrs = upsertAttrWithCap(attrs, makeAttr(\"100% Cashmere\", \"100% Cashmere\"));\n\t  }\n\n\t  attrs = upsertAttrWithCap(attrs, makeAttr(\"Breathable\", \"Breathable\"));\n\t  attrs = upsertAttrWithCap(attrs, makeAttr(\"Temperature Regulating\", \"Temperature Regulating\"));\n\t}\n\n    if (productIdEquals(\"SUB0626IDG\")) {\n      attrs = removeAttr(attrs, \"Super 120s Wool\");\n      attrs = upsertAttrWithCap(attrs, makeAttr(\"Merino Wool\", \"Merino Wool\"));\n    }\n\n    return attrs;\n  }\n\n  // ---- Styling ----\n  function injectStyles() {\n    if (document.getElementById(STYLE_ID)) return;\n\n   var css =\n  \".ct-pdp-icons-list{display:flex;flex-direction:row;gap:3rem;color:#373737;justify-content:flex-start;}\" +\n  \".ct-pdp-icons-list.ct-pdp-icons-list--spread{justify-content:left;}\" +\n  \".ct-pdp-icon-item{display:flex;flex-direction:column;align-items:center;gap:0rem;}\" +\n  \".ct-pdp-icon-item__icon img{width:3.6rem;height:3.6rem;object-fit:contain;display:block;border-radius:100%;padding:5px;}\" +\n  \".ct-pdp-icon-item__text-title{font-size:1.2rem;font-weight:normal;color:#373737;text-align:center;}\";\n\n\n    var style = document.createElement(\"style\");\n    style.id = STYLE_ID;\n    style.textContent = css;\n    document.head.appendChild(style);\n  }\n\n  function removeLegacyIcons() {\n    var old = document.querySelectorAll(\".pdp-icons-container\");\n    for (var i = 0; i \u003c old.length; i++) {\n      if (old[i] \u0026\u0026 old[i].parentNode) old[i].parentNode.removeChild(old[i]);\n    }\n  }\n\n  function isProductSetPage() {\n    try {\n      var t = window.utag_data \u0026\u0026 window.utag_data.page \u0026\u0026 window.utag_data.page.type;\n      return String(t || \"\").toLowerCase() === \"product set\";\n    } catch (e) {}\n    return false;\n  }\n\n  // ---- Render ----\n  function render(attrs) {\n    injectStyles();\n    removeLegacyIcons();\n    if (!attrs || !attrs.length) return;\n\n    var container = document.createElement(\"div\");\n    container.className = \"ct-generated-icons m-bottom-s m-top-s\";\n\n    var list = document.createElement(\"div\");\n    list.className = \"ct-pdp-icons-list\";\n\n    // If more than 2 icons, spread them out; otherwise keep left aligned\n\tif (attrs.length \u003e 3) {\n\t  list.classList.add(\"ct-pdp-icons-list--spread\");\n\t}\n\n\n    for (var i = 0; i \u003c attrs.length; i++) {\n      var attr = attrs[i];\n\n      var item = document.createElement(\"div\");\n      item.className = \"ct-pdp-icon-item\";\n\n      if (attr.icon) {\n        var iconWrap = document.createElement(\"div\");\n        iconWrap.className = \"ct-pdp-icon-item__icon\";\n\n        var img = document.createElement(\"img\");\n        img.src = attr.icon;\n        img.alt = attr.name;\n\n        iconWrap.appendChild(img);\n        item.appendChild(iconWrap);\n      }\n\n      var title = document.createElement(\"div\");\n      title.className = \"ct-pdp-icon-item__text-title\";\n      title.textContent = attr.name;\n      item.appendChild(title);\n\n      list.appendChild(item);\n    }\n\n    container.appendChild(list);\n\n    if (isProductSetPage()) {\n      var setItem = document.querySelector(\".js-product-set-item\");\n      if (setItem) {\n        setItem.insertAdjacentElement(\"beforebegin\", container);\n        return;\n      }\n    }\n\n    var productContent = document.querySelector(\".pdp-main__inner-details\");\nif (productContent) {\n  // Inject inside .pdp-main__inner-details\n  var last = productContent.lastElementChild;\n\n  // If the LAST nested element is a div.grey2, inject BEFORE it\n  if (\n    last \u0026\u0026\n    last.tagName === \"DIV\" \u0026\u0026\n    last.classList \u0026\u0026\n    last.classList.contains(\"grey2\")\n  ) {\n    productContent.insertBefore(container, last);\n  } else {\n    // Otherwise append as the last element\n    productContent.appendChild(container);\n  }\n}\n  }\n\n  // ---- Poll ----\n  function poll(sel, cb, wait, max) {\n    var attempts = 0;\n    (function check() {\n      var el = document.querySelector(sel);\n      if (el) cb(el);\n      else if (attempts \u003c max) {\n        attempts++;\n        setTimeout(check, wait);\n      }\n    })();\n  }\n\n  function init(root) {\n    if (root.hasAttribute(RUN_FLAG)) return;\n    root.setAttribute(RUN_FLAG, \"true\");\n\n    var text = extractText(root);\n    var attrs = findAttributes(text);\n\n    // Product rules BEFORE localisation\n    attrs = applyProductSpecificRules(attrs);\n\n    // Localise titles (DE/FR)\n    attrs = localiseTitles(attrs);\n\n    window.ctPdpAttributes = attrs;\n    render(attrs);\n  }\n\n  poll(ROOT_SEL, init, 200, 40);\n})();","trigger":{"include_pages":[{"type":"any"}],"exclude_pages":null},"_id":"6986151b967c803840d27e22"},{"uses_overlay":false,"type":"js","parametrized_definition":"(() =\u003e {\r\n  \"use strict\";\r\n\r\n  const RUN_FLAG = \"__CT_FOR_YOU_FULL_PLP_OVERLAY_V1__\";\r\n  if (window[RUN_FLAG]) return;\r\n  window[RUN_FLAG] = true;\r\n\r\n  const RECO_ID = \"697a88b7a87355cc6408aafc\";\r\n  const MAX_ITEMS = 36;\r\n  const MAX_DESKTOP = 6;\r\n\r\n  // How many skeleton tiles to paint per surface before data lands\r\n  const SKELETON_COUNT = {\r\n    desktop: MAX_DESKTOP,\r\n    mobile: 8,\r\n    overlay: 12\r\n  };\r\n\r\n  // Hover intent delay before the desktop panel triggers a reco pull\r\n  const DESKTOP_HOVER_DELAY_MS = 180;\r\n\r\n  let ctForYouLastFocusedTrigger = null;\r\n  let ctForYouOverlayKeydownHandler = null;\r\n  let ctForYouLastInteractionWasKeyboard = false;\r\n  let ctDesktopHoverTimer = null;\r\n\r\n  function getForYouCopy() {\r\n    const lang = String(window.utag_data?.global?.site_language || \"\").toUpperCase();\r\n\r\n    if (lang.includes(\"DE\")) {\r\n      return {\r\n        label: \"Für Sie\",\r\n        heading: \"Eine auf Sie zugeschnittene Auswahl\",\r\n        subheading: \"Eine auf Sie zugeschnittene Auswahl, basierend auf Ihrem Surfverhalten und dem, was andere Kunden lieben.\"\r\n      };\r\n    }\r\n\r\n    if (lang.includes(\"FR\")) {\r\n      return {\r\n        label: \"Pour vous\",\r\n        heading: \"Une sélection adaptée pour vous\",\r\n        subheading: \"Une sélection adaptée pour vous, inspirée des produits que vous avez vu et de ce que les autres clients apprécient.\"\r\n      };\r\n    }\r\n\r\n    return {\r\n      label: \"For You\",\r\n      heading: \"A tailored collection for you\",\r\n      subheading: \"A tailored collection for you, inspired by your browsing and what other customers love.\"\r\n    };\r\n  }\r\n\r\n  function trackForYouClick() {\r\n    if (window._satellite \u0026\u0026 typeof window._satellite.track === \"function\") {\r\n      window._satellite.track(\"for_you_ai\", {\r\n        link_name: \"for_you_ai\"\r\n      });\r\n    }\r\n  }\r\n\r\n  function bindInteractionModeTracking() {\r\n    if (window.__CT_FOR_YOU_INPUT_MODE_BOUND__) return;\r\n    window.__CT_FOR_YOU_INPUT_MODE_BOUND__ = true;\r\n\r\n    document.addEventListener(\"keydown\", function (e) {\r\n      const key = e.key;\r\n      if (\r\n        key === \"Tab\" ||\r\n        key === \"Enter\" ||\r\n        key === \" \" ||\r\n        key === \"Spacebar\" ||\r\n        key === \"ArrowDown\" ||\r\n        key === \"ArrowUp\" ||\r\n        key === \"ArrowLeft\" ||\r\n        key === \"ArrowRight\"\r\n      ) {\r\n        ctForYouLastInteractionWasKeyboard = true;\r\n      }\r\n    }, true);\r\n\r\n    document.addEventListener(\"mousedown\", function () {\r\n      ctForYouLastInteractionWasKeyboard = false;\r\n    }, true);\r\n\r\n    document.addEventListener(\"pointerdown\", function () {\r\n      ctForYouLastInteractionWasKeyboard = false;\r\n    }, true);\r\n\r\n    document.addEventListener(\"touchstart\", function () {\r\n      ctForYouLastInteractionWasKeyboard = false;\r\n    }, true);\r\n  }\r\n\r\n  function markKeyboardInteractionOnTrigger(el) {\r\n    if (!el || el.getAttribute(\"data-ct-keyboard-bound\") === \"true\") return;\r\n\r\n    el.setAttribute(\"data-ct-keyboard-bound\", \"true\");\r\n\r\n    el.addEventListener(\"keydown\", function (e) {\r\n      if (\r\n        e.key === \"Tab\" ||\r\n        e.key === \"Enter\" ||\r\n        e.key === \" \" ||\r\n        e.key === \"Spacebar\" ||\r\n        e.key === \"ArrowDown\" ||\r\n        e.key === \"ArrowUp\" ||\r\n        e.key === \"ArrowLeft\" ||\r\n        e.key === \"ArrowRight\"\r\n      ) {\r\n        ctForYouLastInteractionWasKeyboard = true;\r\n      }\r\n    });\r\n  }\r\n\r\n  function bindDesktopHoverImageSwap(tileEl, imgEl, primarySrc, hoverSrc) {\r\n    if (!tileEl || !imgEl || !primarySrc || !hoverSrc) return;\r\n    if (!isDesktopViewport()) return;\r\n    if (tileEl.getAttribute(\"data-ct-hover-swap-bound\") === \"true\") return;\r\n\r\n    tileEl.setAttribute(\"data-ct-hover-swap-bound\", \"true\");\r\n\r\n    let preloaded = false;\r\n    const preloadImg = new Image();\r\n\r\n    function ensurePreloaded() {\r\n      if (preloaded) return;\r\n      preloadImg.src = hoverSrc;\r\n      preloaded = true;\r\n    }\r\n\r\n    function swapToHover() {\r\n      ensurePreloaded();\r\n      imgEl.src = hoverSrc;\r\n    }\r\n\r\n    function swapToPrimary() {\r\n      imgEl.src = primarySrc;\r\n    }\r\n\r\n    tileEl.addEventListener(\"mouseenter\", swapToHover);\r\n    tileEl.addEventListener(\"mouseleave\", swapToPrimary);\r\n    tileEl.addEventListener(\"focusin\", swapToHover);\r\n    tileEl.addEventListener(\"focusout\", swapToPrimary);\r\n  }\r\n\r\n  function poll(selector, cb, timeout, max) {\r\n    max--;\r\n    if (document.querySelector(selector) \u0026\u0026 window.utag_data) {\r\n      cb();\r\n    } else if (max \u003e 0) {\r\n      setTimeout(() =\u003e poll(selector, cb, timeout, max), timeout);\r\n    }\r\n  }\r\n\r\n  function isDesktopViewport() {\r\n    return window.matchMedia \u0026\u0026 window.matchMedia(\"(min-width: 1024px)\").matches;\r\n  }\r\n\r\n  function isMobileViewport() {\r\n    return !isDesktopViewport();\r\n  }\r\n\r\n  function isMobileView() {\r\n    try {\r\n      const t = (window.utag_data?.page?.responsive_design_type || \"\").toLowerCase();\r\n      return t === \"mobile view\";\r\n    } catch (e) {\r\n      return false;\r\n    }\r\n  }\r\n\r\n  function escapeHtml(str) {\r\n    return String(str || \"\")\r\n      .replace(/\u0026/g, \"\u0026amp;\")\r\n      .replace(/\u003c/g, \"\u0026lt;\")\r\n      .replace(/\u003e/g, \"\u0026gt;\")\r\n      .replace(/\"/g, \"\u0026quot;\")\r\n      .replace(/'/g, \"\u0026#039;\");\r\n  }\r\n\r\n  function cleanProductTitle(raw) {\r\n    let t = String(raw || \"\").trim();\r\n    if (!t) return \"\";\r\n\r\n    t = t.replace(/^(men's|men's|mens)\\s+/i, \"\").trim();\r\n    t = t.replace(/^(women's|women's|womens)\\s+/i, \"\").trim();\r\n    t = t.replace(/\\bPants\\b/gi, \"Trousers\");\r\n    t = t.replace(/charles\\s+tyrwhitt/ig, \"\").trim();\r\n\r\n    const sizeIdx = t.toLowerCase().indexOf(\" size\");\r\n    if (sizeIdx !== -1) {\r\n      t = t.slice(0, sizeIdx).trim();\r\n    }\r\n\r\n    t = t\r\n      .replace(/\\bSingle\\s+Cuff\\b/ig, \"\")\r\n      .replace(/\\bPure\\b/ig, \"\")\r\n      .replace(/\\s{2,}/g, \" \")\r\n      .replace(/\\s+[-–—]\\s*$/g, \"\")\r\n      .trim();\r\n\r\n    return t;\r\n  }\r\n\r\n  function formatCollarType(raw) {\r\n    const t = String(raw || \"\").trim();\r\n    if (!t) return \"\";\r\n\r\n    const lang = String(window.utag_data?.global?.sfcc_country || \"\").toUpperCase();\r\n\r\n    const translations = {\r\n      DE: { Classic: \"Klassisch\", Cutaway: \"Cutaway\", \"Semi Cutaway\": \"Semi-Cutaway\" },\r\n      FR: { Classic: \"Classique\", Cutaway: \"Cutaway\", \"Semi Cutaway\": \"Semi-cutaway\" }\r\n    };\r\n\r\n    const normalised = t\r\n      .replace(/[_-]+/g, \" \")\r\n      .replace(/\\s+/g, \" \")\r\n      .replace(/\\b\\w/g, m =\u003e m.toUpperCase())\r\n      .trim();\r\n\r\n    const locale = lang.includes(\"DE\") ? \"DE\" : lang.includes(\"FR\") ? \"FR\" : null;\r\n    if (locale \u0026\u0026 translations[locale][normalised]) {\r\n      return translations[locale][normalised];\r\n    }\r\n\r\n    return normalised;\r\n  }\r\n\r\n  function normalizeMoney(val) {\r\n    const v = String(val || \"\").trim();\r\n    if (!v) return \"\";\r\n    return v.replace(/\\s+/g, \"\").replace(/,/g, \"\").replace(/[^\\d.]/g, \"\").trim();\r\n  }\r\n\r\n  function parseMoney(val) {\r\n    const n = normalizeMoney(val);\r\n    return n ? parseFloat(n) : NaN;\r\n  }\r\n\r\n  function hasRealDiscount(was, now) {\r\n    const wasNum = parseMoney(was);\r\n    const nowNum = parseMoney(now);\r\n\r\n    if (!Number.isNaN(wasNum) \u0026\u0026 !Number.isNaN(nowNum)) {\r\n      return wasNum \u003e nowNum;\r\n    }\r\n\r\n    return !!was \u0026\u0026 !!now \u0026\u0026 String(was).trim() !== String(now).trim();\r\n  }\r\n\r\n  function removeProductTile(tileEl) {\r\n    try {\r\n      if (tileEl \u0026\u0026 tileEl.parentNode) tileEl.parentNode.removeChild(tileEl);\r\n    } catch (e) {}\r\n  }\r\n\r\n  function watchTileImage(imgEl, tileEl, onRemoved) {\r\n    if (!imgEl || !tileEl) return;\r\n\r\n    const src = (imgEl.getAttribute(\"src\") || \"\").trim();\r\n    if (!src) return;\r\n\r\n    let settled = false;\r\n\r\n    function removeTile() {\r\n      if (settled) return;\r\n      settled = true;\r\n      removeProductTile(tileEl);\r\n      if (typeof onRemoved === \"function\") onRemoved();\r\n    }\r\n\r\n    function handleLoad() {\r\n      if (settled) return;\r\n\r\n      if (imgEl.naturalWidth \u003e 0 \u0026\u0026 imgEl.naturalHeight \u003e 0) {\r\n        settled = true;\r\n        tileEl.setAttribute(\"data-ct-image-ok\", \"true\");\r\n      } else {\r\n        removeTile();\r\n      }\r\n    }\r\n\r\n    function handleError() {\r\n      removeTile();\r\n    }\r\n\r\n    imgEl.addEventListener(\"load\", handleLoad, { once: true });\r\n    imgEl.addEventListener(\"error\", handleError, { once: true });\r\n\r\n    if (imgEl.complete) {\r\n      if (imgEl.naturalWidth \u003e 0 \u0026\u0026 imgEl.naturalHeight \u003e 0) {\r\n        settled = true;\r\n        tileEl.setAttribute(\"data-ct-image-ok\", \"true\");\r\n      } else {\r\n        removeTile();\r\n      }\r\n    }\r\n  }\r\n\r\n  function buildProductUrl(prodId) {\r\n    if (!prodId) return \"#\";\r\n\r\n    const global = window.utag_data?.global || {};\r\n    const country = String(global.sfcc_country || \"UK\").toLowerCase();\r\n    const siteLanguage = String(global.site_language || \"\").trim();\r\n\r\n    const pathParts = (window.location.pathname || \"\").split(\"/\").filter(Boolean);\r\n\r\n    let prefix = \"/\" + encodeURIComponent(country);\r\n\r\n    if (\r\n      pathParts.length \u003e= 2 \u0026\u0026\r\n      pathParts[0].toLowerCase() === country \u0026\u0026\r\n      siteLanguage \u0026\u0026\r\n      pathParts[1].toLowerCase() === siteLanguage.toLowerCase()\r\n    ) {\r\n      prefix += \"/\" + encodeURIComponent(siteLanguage);\r\n    }\r\n\r\n    return (\r\n      window.location.origin +\r\n      prefix +\r\n      \"/\" +\r\n      encodeURIComponent(prodId) +\r\n      \".html?pf=for_you_ai\"\r\n    );\r\n  }\r\n\r\n  const COPY = getForYouCopy();\r\n\r\n  /* --------------------------------------------------------------------------\r\n     Shared recommendation cache\r\n\r\n     One getRecommendation call per session feeds the desktop nav, the mobile\r\n     nav and the overlay. In-memory first, sessionStorage second, network last.\r\n     Nothing fires until a surface actually asks for it.\r\n  -------------------------------------------------------------------------- */\r\n  const CT_RECS = (() =\u003e {\r\n    const STORAGE_KEY = \"ct_for_you_recs_v1\";\r\n    const TTL_MS = 30 * 60 * 1000;\r\n    const SDK_MAX_WAIT_MS = 3000;\r\n    const SDK_STEP_MS = 100;\r\n\r\n    let memory = null;\r\n    let inflight = null;\r\n\r\n    function readSession() {\r\n      try {\r\n        const raw = sessionStorage.getItem(STORAGE_KEY);\r\n        if (!raw) return null;\r\n\r\n        const parsed = JSON.parse(raw);\r\n        if (!parsed || !Array.isArray(parsed.items)) return null;\r\n        if (typeof parsed.ts !== \"number\") return null;\r\n        if (Date.now() - parsed.ts \u003e TTL_MS) return null;\r\n        if (parsed.recoId !== RECO_ID) return null;\r\n\r\n        return parsed.items;\r\n      } catch (e) {\r\n        return null;\r\n      }\r\n    }\r\n\r\n    function writeSession(items) {\r\n      try {\r\n        sessionStorage.setItem(\r\n          STORAGE_KEY,\r\n          JSON.stringify({ ts: Date.now(), recoId: RECO_ID, items })\r\n        );\r\n      } catch (e) {}\r\n    }\r\n\r\n    function hasSdk() {\r\n      return !!(window.exponea \u0026\u0026 typeof window.exponea.getRecommendation === \"function\");\r\n    }\r\n\r\n    function get() {\r\n      // An empty array is truthy, so length is the real guard here\r\n      if (memory \u0026\u0026 memory.length) return Promise.resolve(memory);\r\n      if (inflight) return inflight;\r\n\r\n      const cached = readSession();\r\n      if (cached) {\r\n        memory = cached;\r\n        return Promise.resolve(cached);\r\n      }\r\n\r\n      inflight = new Promise((resolve) =\u003e {\r\n        let waited = 0;\r\n\r\n        (function waitForSdk() {\r\n          if (hasSdk()) {\r\n            try {\r\n              window.exponea.getRecommendation({\r\n                recommendationId: RECO_ID,\r\n                size: MAX_ITEMS,\r\n                callback: function (data) {\r\n                  const items = Array.isArray(data) ? data : [];\r\n                  if (items.length) {\r\n                    memory = items;\r\n                    writeSession(items);\r\n                  }\r\n                  resolve(items);\r\n                }\r\n              });\r\n            } catch (e) {\r\n              resolve([]);\r\n            }\r\n            return;\r\n          }\r\n\r\n          waited += SDK_STEP_MS;\r\n          if (waited \u003e= SDK_MAX_WAIT_MS) {\r\n            resolve([]);\r\n            return;\r\n          }\r\n\r\n          setTimeout(waitForSdk, SDK_STEP_MS);\r\n        })();\r\n      }).then((items) =\u003e {\r\n        inflight = null;\r\n        return items;\r\n      });\r\n\r\n      return inflight;\r\n    }\r\n\r\n    function getIds() {\r\n      return get().then((data) =\u003e\r\n        (data || [])\r\n          .filter((item) =\u003e item \u0026\u0026 item.item_id)\r\n          .map((item) =\u003e item.item_id)\r\n      );\r\n    }\r\n\r\n    return { get, getIds };\r\n  })();\r\n\r\n  const CT_PRODUCT_DATA = (() =\u003e {\r\n    const cache = new Map();\r\n    const inflight = new Map();\r\n    const queue = [];\r\n    let active = 0;\r\n\r\n    const MAX_CONCURRENCY = 4;\r\n    const TIMEOUT_MS = 8000;\r\n    const RETRIES = 1;\r\n\r\n    function buildUrl(prodId) {\r\n      const global = window.utag_data?.global || {};\r\n      const country = global.sfcc_country || \"UK\";\r\n      const lang = global.site_language || \"en_GB\";\r\n\r\n      return (\r\n        \"/on/demandware.store/Sites-CTShirts-\" +\r\n        encodeURIComponent(country) +\r\n        \"-Site/\" +\r\n        encodeURIComponent(lang) +\r\n        \"/Product-getProductTileData?productids=\" +\r\n        encodeURIComponent(prodId)\r\n      );\r\n    }\r\n\r\n    function ajaxText(url) {\r\n      if (window.jQuery \u0026\u0026 window.jQuery.ajax) {\r\n        return new Promise((resolve, reject) =\u003e {\r\n          let done = false;\r\n          const timer = setTimeout(() =\u003e {\r\n            if (done) return;\r\n            done = true;\r\n            reject(new Error(\"timeout\"));\r\n          }, TIMEOUT_MS);\r\n\r\n          window.jQuery\r\n            .ajax({ url, method: \"GET\", dataType: \"text\" })\r\n            .done((txt) =\u003e {\r\n              if (done) return;\r\n              done = true;\r\n              clearTimeout(timer);\r\n              resolve(txt);\r\n            })\r\n            .fail((xhr, status, err) =\u003e {\r\n              if (done) return;\r\n              done = true;\r\n              clearTimeout(timer);\r\n              reject(new Error(status || err || \"ajax_fail\"));\r\n            });\r\n        });\r\n      }\r\n\r\n      return fetch(url, { credentials: \"include\" }).then((r) =\u003e r.text());\r\n    }\r\n\r\n    async function fetchOne(prodId, attempt = 0) {\r\n      const url = buildUrl(prodId);\r\n\r\n      try {\r\n        const txt = await ajaxText(url);\r\n\r\n        let json = null;\r\n        try {\r\n          json = JSON.parse(txt);\r\n        } catch (e) {\r\n          if (attempt \u003c RETRIES) return fetchOne(prodId, attempt + 1);\r\n          return null;\r\n        }\r\n\r\n        if (!Array.isArray(json) || !json.length) return null;\r\n\r\n        const obj =\r\n          json.find((x) =\u003e x \u0026\u0026 String(x.productid).toUpperCase() === String(prodId).toUpperCase()) ||\r\n          json[0];\r\n\r\n        if (!obj) return null;\r\n\r\n        return {\r\n          id: String(obj.productid || prodId).toUpperCase(),\r\n          name: String(obj.productname || \"\"),\r\n          collarType: String(obj.collarType || \"\"),\r\n          image0: String(obj.productimage0 || \"\"),\r\n          image1: String(obj.productimage1 || \"\"),\r\n          was: String(obj.wasprice || \"\"),\r\n          now: String(obj.nowprice || \"\"),\r\n          mbuy: String(obj.multibuyPrice || \"\")\r\n        };\r\n      } catch (e) {\r\n        if (attempt \u003c RETRIES) return fetchOne(prodId, attempt + 1);\r\n        return null;\r\n      }\r\n    }\r\n\r\n    function pump() {\r\n      while (active \u003c MAX_CONCURRENCY \u0026\u0026 queue.length) {\r\n        const job = queue.shift();\r\n        active++;\r\n\r\n        fetchOne(job.id)\r\n          .then((res) =\u003e {\r\n            if (res) cache.set(job.id, res);\r\n            job.resolve(res);\r\n          })\r\n          .catch(() =\u003e job.resolve(null))\r\n          .finally(() =\u003e {\r\n            active--;\r\n            pump();\r\n          });\r\n      }\r\n    }\r\n\r\n    function get(prodId) {\r\n      if (!prodId) return Promise.resolve(null);\r\n\r\n      const id = String(prodId).toUpperCase();\r\n\r\n      if (cache.has(id)) return Promise.resolve(cache.get(id));\r\n      if (inflight.has(id)) return inflight.get(id);\r\n\r\n      const p = new Promise((resolve) =\u003e {\r\n        queue.push({ id, resolve });\r\n        pump();\r\n      }).finally(() =\u003e inflight.delete(id));\r\n\r\n      inflight.set(id, p);\r\n      return p;\r\n    }\r\n\r\n    return { get };\r\n  })();\r\n\r\n  function applyEndpointDataToTile(prodId, tileEl, onTileChange) {\r\n    if (!prodId || !tileEl) return Promise.resolve(false);\r\n\r\n    tileEl.setAttribute(\"data-ct-hydrating\", \"true\");\r\n\r\n    return CT_PRODUCT_DATA.get(prodId).then((p) =\u003e {\r\n      if (!p) {\r\n        removeProductTile(tileEl);\r\n        if (typeof onTileChange === \"function\") onTileChange();\r\n        return false;\r\n      }\r\n\r\n      const cleanTitle = cleanProductTitle(p.name || prodId);\r\n      const bestImg = String(p.image0 || p.image1 || \"\").trim();\r\n\r\n      if (!bestImg) {\r\n        removeProductTile(tileEl);\r\n        if (typeof onTileChange === \"function\") onTileChange();\r\n        return false;\r\n      }\r\n\r\n      const titleEl = tileEl.querySelector(\"[data-ct-title]\");\r\n      if (titleEl) {\r\n        titleEl.textContent = cleanTitle;\r\n      }\r\n\r\n      const collarWrap = tileEl.querySelector(\"[data-ct-collar-wrap]\");\r\n      if (collarWrap) {\r\n        const rawCollar = String(p.collarType || \"\").trim().toLowerCase();\r\n\r\n        const EXCLUDED_COLLARS = [\r\n          \"polo\",\r\n          \"button_neck\",\r\n          \"Button Neck\",\r\n          \"trophy_neck\"\r\n        ];\r\n\r\n        const isExcluded = EXCLUDED_COLLARS.some(function (val) {\r\n          return rawCollar.includes(val);\r\n        });\r\n\r\n        let collarEl = collarWrap.querySelector(\".product-tile__collar-label\");\r\n\r\n        if (isExcluded) {\r\n          collarWrap.classList.remove(\"ct-for-you-has-collar\");\r\n\r\n          if (collarEl \u0026\u0026 collarEl.parentNode) {\r\n            collarEl.parentNode.removeChild(collarEl);\r\n          }\r\n        } else {\r\n          const collarText = formatCollarType(p.collarType);\r\n\r\n          if (collarText) {\r\n            if (!collarEl) {\r\n              collarEl = document.createElement(\"div\");\r\n              collarEl.className = \"bg-grey5 grey1 p m-all-z text-center capitalize product-tile__collar-label position-absolute col-100\";\r\n              collarWrap.appendChild(collarEl);\r\n            }\r\n\r\n            collarEl.textContent = collarText;\r\n            collarWrap.classList.add(\"ct-for-you-has-collar\");\r\n          } else {\r\n            collarWrap.classList.remove(\"ct-for-you-has-collar\");\r\n\r\n            if (collarEl \u0026\u0026 collarEl.parentNode) {\r\n              collarEl.parentNode.removeChild(collarEl);\r\n            }\r\n          }\r\n        }\r\n      }\r\n\r\n      const pricingWrap = tileEl.querySelector(\"[data-ct-price]\");\r\n      if (pricingWrap) {\r\n        const now = String(p.now || \"\").trim();\r\n        const was = String(p.was || \"\").trim();\r\n        const hasDiscount = hasRealDiscount(was, now);\r\n\r\n        pricingWrap.innerHTML = now\r\n          ? (\r\n              hasDiscount\r\n                ? '\u003cspan class=\"ct-for-you-price-was\"\u003e' + escapeHtml(was) + '\u003c/span\u003e' +\r\n                  '\u003cspan class=\"ct-for-you-price-now red1\"\u003eNow ' + escapeHtml(now) + \"\u003c/span\u003e\"\r\n                : '\u003cspan class=\"ct-for-you-price-now\"\u003e' + escapeHtml(now) + \"\u003c/span\u003e\"\r\n            )\r\n          : \"\";\r\n      }\r\n\r\n      const mbEl = tileEl.querySelector(\"[data-ct-mb]\");\r\n      if (mbEl) {\r\n        let mbValue = String(p.mbuy || \"\").trim();\r\n        const nowNum = parseMoney(p.now);\r\n        const mbNum = parseMoney(mbValue);\r\n\r\n        if (!mbValue) {\r\n          mbEl.remove();\r\n        } else {\r\n          if (!Number.isNaN(nowNum) \u0026\u0026 !Number.isNaN(mbNum) \u0026\u0026 mbNum \u003e nowNum) {\r\n            mbValue = p.now;\r\n          }\r\n\r\n          const finalMbNum = parseMoney(mbValue);\r\n          if (!Number.isNaN(nowNum) \u0026\u0026 !Number.isNaN(finalMbNum) \u0026\u0026 finalMbNum === nowNum) {\r\n            mbEl.remove();\r\n          } else {\r\n            const spans = mbEl.querySelectorAll(\"span\");\r\n            if (spans.length \u003e= 2) {\r\n              spans[0].textContent = mbValue + \" Multibuy\";\r\n              spans[1].textContent = mbValue + \" Multibuy price\";\r\n            } else {\r\n              mbEl.textContent = mbValue + \" Multibuy\";\r\n            }\r\n          }\r\n        }\r\n      }\r\n\r\n      const imgEl = tileEl.querySelector(\"img[data-ct-img]\");\r\n      if (!imgEl) {\r\n        removeProductTile(tileEl);\r\n        if (typeof onTileChange === \"function\") onTileChange();\r\n        return false;\r\n      }\r\n\r\n      const primaryImg = String(p.image0 || \"\").trim();\r\n      const hoverImg = String(p.image1 || \"\").trim();\r\n\r\n      if (!primaryImg) {\r\n        removeProductTile(tileEl);\r\n        if (typeof onTileChange === \"function\") onTileChange();\r\n        return false;\r\n      }\r\n\r\n      imgEl.alt = cleanTitle;\r\n      imgEl.src = primaryImg;\r\n      imgEl.setAttribute(\"data-ct-primary-img\", primaryImg);\r\n\r\n      const hoverImgIsValid =\r\n        hoverImg \u0026\u0026\r\n        !/noimagemedium\\.png/i.test(hoverImg);\r\n\r\n      if (hoverImgIsValid) {\r\n        imgEl.setAttribute(\"data-ct-hover-img\", hoverImg);\r\n        bindDesktopHoverImageSwap(tileEl, imgEl, primaryImg, hoverImg);\r\n      } else {\r\n        imgEl.removeAttribute(\"data-ct-hover-img\");\r\n      }\r\n\r\n      watchTileImage(imgEl, tileEl, onTileChange);\r\n\r\n      tileEl.setAttribute(\"data-ct-hydrating\", \"false\");\r\n      tileEl.setAttribute(\"data-ct-endpoint-ready\", \"true\");\r\n\r\n      return true;\r\n    }).catch(() =\u003e {\r\n      removeProductTile(tileEl);\r\n      if (typeof onTileChange === \"function\") onTileChange();\r\n      return false;\r\n    });\r\n  }\r\n\r\n  /* --------------------------------------------------------------------------\r\n     Skeleton tile builders\r\n\r\n     Each surface paints placeholder tiles the moment intent is registered, so\r\n     the panel reserves its final height before any network work completes.\r\n     Placeholder links are removed from the tab order until they carry a real\r\n     product URL.\r\n  -------------------------------------------------------------------------- */\r\n\r\n  function buildDesktopTile() {\r\n    const li = document.createElement(\"li\");\r\n    li.className = \"ct-for-you-desktop-tile\";\r\n    li.innerHTML = `\r\n      \u003ca href=\"#\" tabindex=\"-1\" aria-hidden=\"true\"\u003e\r\n        \u003cdiv class=\"position-relative ct-for-you-skel\" data-ct-collar-wrap\u003e\r\n          \u003cimg data-ct-img alt=\"\"\u003e\r\n        \u003c/div\u003e\r\n        \u003cdiv class=\"ct-for-you-desktop-title\" data-ct-title\u003e\r\n          \u003cspan class=\"ct-for-you-skel ct-for-you-skel-line\"\u003e\u003c/span\u003e\r\n          \u003cspan class=\"ct-for-you-skel ct-for-you-skel-line ct-for-you-skel-line--mid\"\u003e\u003c/span\u003e\r\n        \u003c/div\u003e\r\n        \u003cdiv class=\"ct-for-you-desktop-price tile__pricing text-left grey1 font__secondary m-top-xs normal\" data-ct-price\u003e\r\n          \u003cspan class=\"ct-for-you-skel ct-for-you-skel-line ct-for-you-skel-line--short\"\u003e\u003c/span\u003e\r\n        \u003c/div\u003e\r\n        \u003cp class=\"product-tile__promo h5 capitalize grey2 m-top-xs font__secondary\" data-ct-mb\u003e\r\n          \u003cspan aria-hidden=\"true\"\u003e\u003c/span\u003e\r\n          \u003cspan class=\"accessibility-hidden\"\u003e\u003c/span\u003e\r\n        \u003c/p\u003e\r\n      \u003c/a\u003e\r\n    `;\r\n    return li;\r\n  }\r\n\r\n  function buildMobileNavTile() {\r\n    const li = document.createElement(\"li\");\r\n    li.className = \"ct-for-you-nav-tile m-bottom-xl mps-m-bottom-z\";\r\n    li.innerHTML = `\r\n      \u003ca href=\"#\" tabindex=\"-1\" aria-hidden=\"true\"\u003e\r\n        \u003cdiv class=\"position-relative ct-for-you-skel\" data-ct-collar-wrap\u003e\r\n          \u003cimg data-ct-img alt=\"\"\u003e\r\n        \u003c/div\u003e\r\n        \u003cdiv class=\"ct-for-you-nav-title\" data-ct-title\u003e\r\n          \u003cspan class=\"ct-for-you-skel ct-for-you-skel-line\"\u003e\u003c/span\u003e\r\n          \u003cspan class=\"ct-for-you-skel ct-for-you-skel-line ct-for-you-skel-line--mid\"\u003e\u003c/span\u003e\r\n        \u003c/div\u003e\r\n        \u003cdiv class=\"ct-for-you-nav-price tile__pricing text-left grey1 font__secondary m-top-xs normal\" data-ct-price\u003e\r\n          \u003cspan class=\"ct-for-you-skel ct-for-you-skel-line ct-for-you-skel-line--short\"\u003e\u003c/span\u003e\r\n        \u003c/div\u003e\r\n        \u003cdiv class=\"ct-for-you-nav-mb grey2 product-tile__promo h5 capitalize grey2 m-top-xs font__secondary\" data-ct-mb\u003e\u003c/div\u003e\r\n      \u003c/a\u003e\r\n    `;\r\n    return li;\r\n  }\r\n\r\n  function buildOverlayTile() {\r\n    const li = document.createElement(\"li\");\r\n    li.className = \"position-relative plp-grid__container--tile m-bottom-xl ct-for-you-tile\";\r\n    li.innerHTML =\r\n      '\u003cdiv class=\"position-relative product-tile js-product-tile-container js-product-tile\"\u003e' +\r\n      '  \u003cdiv class=\"product-tile__img text-center position-relative\" data-ct-collar-wrap\u003e' +\r\n      '    \u003ca class=\"thumb-link js-thumb-link js-product-tile-image product-tile__img-link d-block keyboard-focus-outline\" href=\"#\" tabindex=\"-1\" aria-hidden=\"true\"\u003e' +\r\n      '      \u003cpicture class=\"d-block bg-white ct-for-you-skel\" style=\"aspect-ratio:430/538;\"\u003e' +\r\n      '        \u003cimg data-ct-img alt=\"\" style=\"aspect-ratio:430/538;\"\u003e' +\r\n      \"      \u003c/picture\u003e\" +\r\n      \"    \u003c/a\u003e\" +\r\n      \"  \u003c/div\u003e\" +\r\n      '  \u003cdiv class=\"js-tile-info-wrapper text-left product-tile__info-wrapper\"\u003e' +\r\n      '    \u003cdiv class=\"js-tile-info product-tile__info bg-white overflow-hidden position-relative\"\u003e' +\r\n      \"      \u003cdiv\u003e\" +\r\n      '        \u003ca class=\"js-thumb-link outline-offset-1 product-tile__name-link h4 h4__regular grey1 d-block js-product-tile-name p-top-s\" href=\"#\" tabindex=\"-1\" aria-hidden=\"true\"\u003e' +\r\n      '          \u003cspan class=\"js-thumb-name font__secondary\" data-ct-title\u003e' +\r\n      '            \u003cspan class=\"ct-for-you-skel ct-for-you-skel-line\"\u003e\u003c/span\u003e' +\r\n      '            \u003cspan class=\"ct-for-you-skel ct-for-you-skel-line ct-for-you-skel-line--mid\"\u003e\u003c/span\u003e' +\r\n      \"          \u003c/span\u003e\" +\r\n      \"        \u003c/a\u003e\" +\r\n      \"      \u003c/div\u003e\" +\r\n      \"      \u003cdiv\u003e\" +\r\n      '        \u003cdiv class=\"h5\"\u003e' +\r\n      '          \u003cdiv class=\"js-tile-pricing tile__pricing text-left grey1 font__secondary m-top-xs normal\" data-ct-price\u003e' +\r\n      '            \u003cspan class=\"ct-for-you-skel ct-for-you-skel-line ct-for-you-skel-line--short\"\u003e\u003c/span\u003e' +\r\n      \"          \u003c/div\u003e\" +\r\n      \"        \u003c/div\u003e\" +\r\n      '        \u003cp class=\"product-tile__promo h5 capitalize grey2 m-top-xs font__secondary\" data-ct-mb\u003e' +\r\n      '          \u003cspan aria-hidden=\"true\"\u003e\u003c/span\u003e' +\r\n      '          \u003cspan class=\"accessibility-hidden\"\u003e\u003c/span\u003e' +\r\n      \"        \u003c/p\u003e\" +\r\n      \"      \u003c/div\u003e\" +\r\n      \"    \u003c/div\u003e\" +\r\n      \"  \u003c/div\u003e\" +\r\n      \"\u003c/div\u003e\";\r\n    return li;\r\n  }\r\n\r\n  function paintSkeletonTiles(grid, buildTile, count) {\r\n    if (!grid) return [];\r\n\r\n    grid.innerHTML = \"\";\r\n    grid.setAttribute(\"data-ct-skeleton\", \"true\");\r\n\r\n    const tiles = [];\r\n    const fragment = document.createDocumentFragment();\r\n\r\n    for (let i = 0; i \u003c count; i++) {\r\n      const tile = buildTile();\r\n      tiles.push(tile);\r\n      fragment.appendChild(tile);\r\n    }\r\n\r\n    grid.appendChild(fragment);\r\n    return tiles;\r\n  }\r\n\r\n  function activateTile(tileEl, prodId) {\r\n    if (!tileEl || !prodId) return;\r\n\r\n    const url = buildProductUrl(prodId);\r\n    const links = tileEl.querySelectorAll(\"a\");\r\n\r\n    for (let i = 0; i \u003c links.length; i++) {\r\n      links[i].setAttribute(\"href\", url);\r\n      links[i].removeAttribute(\"tabindex\");\r\n      links[i].removeAttribute(\"aria-hidden\");\r\n    }\r\n\r\n    const inner = tileEl.querySelector(\".js-product-tile\");\r\n    if (inner) inner.setAttribute(\"data-prod-id\", prodId);\r\n  }\r\n\r\n  /*\r\n     Hydrates skeleton tiles in place. Surplus skeletons are removed, and if the\r\n     reco set is longer than the skeleton count the remainder is appended.\r\n  */\r\n  function hydrateGrid(opts) {\r\n    const grid = opts.grid;\r\n    const tiles = opts.tiles || [];\r\n    const ids = opts.ids || [];\r\n    const buildTile = opts.buildTile;\r\n    const max = opts.max;\r\n    const onChange = opts.onChange;\r\n\r\n    if (!grid) return;\r\n\r\n    grid.removeAttribute(\"data-ct-skeleton\");\r\n\r\n    const limit = Math.min(ids.length, max);\r\n\r\n    if (!limit) {\r\n      grid.innerHTML = \"\";\r\n      if (typeof onChange === \"function\") onChange();\r\n      return;\r\n    }\r\n\r\n    for (let i = 0; i \u003c tiles.length; i++) {\r\n      const tile = tiles[i];\r\n\r\n      if (i \u003e= limit) {\r\n        removeProductTile(tile);\r\n        continue;\r\n      }\r\n\r\n      activateTile(tile, ids[i]);\r\n      applyEndpointDataToTile(ids[i], tile, onChange);\r\n    }\r\n\r\n    if (limit \u003e tiles.length) {\r\n      const fragment = document.createDocumentFragment();\r\n      const pending = [];\r\n\r\n      for (let i = tiles.length; i \u003c limit; i++) {\r\n        const tile = buildTile();\r\n        activateTile(tile, ids[i]);\r\n        pending.push({ tile: tile, id: ids[i] });\r\n        fragment.appendChild(tile);\r\n      }\r\n\r\n      grid.appendChild(fragment);\r\n\r\n      for (let i = 0; i \u003c pending.length; i++) {\r\n        applyEndpointDataToTile(pending[i].id, pending[i].tile, onChange);\r\n      }\r\n    }\r\n\r\n    if (typeof onChange === \"function\") onChange();\r\n  }\r\n\r\n  function injectForYouMobileNavItem() {\r\n    if (!isMobileViewport()) return;\r\n\r\n    const mobileNav =\r\n      document.querySelector(\"#navigation .js-navigation\") ||\r\n      document.querySelector(\".js-navigation\");\r\n\r\n    if (!mobileNav) return;\r\n    if (mobileNav.querySelector('[data-ct-for-you-mobile=\"true\"]')) return;\r\n\r\n    const li = document.createElement(\"li\");\r\n    li.setAttribute(\"role\", \"listitem\");\r\n    li.className = \"js-nav-link-main navigation__li navigation__li--main\";\r\n    li.setAttribute(\"data-ct-for-you-mobile\", \"true\");\r\n\r\n    li.innerHTML = `\r\n      \u003cdiv class=\"experience-component experience-layouts-navItem\"\u003e\r\n        \u003ca data-hover=\"false\"\r\n          data-tracking=\"top-nav-parent-url\"\r\n          id=\"ct-for-you-mobile-nav-link\"\r\n          href=\"#\"\r\n          class=\"navigation__li-link navigation__li-link--has-sub navigation__li-link--color\r\n                  has-sub-menu js-maincat cursor-pointer position-relative capitalize\r\n                  text-decoration-none d-block\"\u003e\r\n          ${COPY.label}\r\n          \u003cspan\u003e\r\n            \u003csvg aria-hidden=\"true\" focusable=\"false\"\r\n                 style=\"width:20px;height:20px;margin-right:0;vertical-align:middle;display:inline-block;margin-top:-15px;\"\r\n                 viewBox=\"0 0 23 18\" xmlns=\"http://www.w3.org/2000/svg\"\u003e\r\n              \u003cpath d=\"M5.43949 1.05205C5.57433 0.495998 6.03716 0.21797 6.5 0.217969C6.96284 0.217968 7.42567 0.495995 7.56051 1.05205L8.30252 4.1121C8.3988 4.50915 8.70882 4.81917 9.10587 4.91545L12.1659 5.65746C13.278 5.92713 13.278 7.50881 12.1659 7.77848L9.10587 8.52049C8.70882 8.61677 8.39881 8.92679 8.30253 9.32384L7.56051 12.3839C7.29084 13.496 5.70917 13.496 5.43949 12.3839L4.69748 9.32384C4.6012 8.92679 4.29118 8.61677 3.89413 8.52049L0.834083 7.77848C-0.278028 7.50881 -0.278028 5.92713 0.834083 5.65746L3.89413 4.91545C4.29118 4.81917 4.6012 4.50915 4.69748 4.1121L5.43949 1.05205Z\" fill=\"currentColor\"\u003e\u003c/path\u003e\r\n              \u003cpath d=\"M11.5133 2.46797C10.961 2.46797 10.5133 2.02025 10.5133 1.46797C10.5133 0.915684 10.961 0.467969 11.5133 0.467969C12.0656 0.467969 12.5133 0.915684 12.5133 1.46797C12.5133 2.02025 12.0656 2.46797 11.5133 2.46797Z\" fill=\"currentColor\"\u003e\u003c/path\u003e\r\n              \u003cpath d=\"M19 11.718C18.4477 11.718 18 11.2703 18 10.718C18 10.1657 18.4477 9.71797 19 9.71797C19.5523 9.71797 20 10.1657 20 10.718C20 11.2703 19.5523 11.718 19 11.718Z\" fill=\"currentColor\"\u003e\u003c/path\u003e\r\n              \u003cpath d=\"M7.56051 17.3706C7.00823 17.3706 6.56051 16.9229 6.56051 16.3706C6.56051 15.8183 7.00823 15.3706 7.56051 15.3706C8.11279 15.3706 8.56051 15.8183 8.56051 16.3706C8.56051 16.9229 8.11279 17.3706 7.56051 17.3706Z\" fill=\"currentColor\"\u003e\u003c/path\u003e\r\n            \u003c/svg\u003e\r\n          \u003c/span\u003e\r\n\r\n          \u003cspan class=\"align-center-v right-z m-right-l nav-touch-device\"\u003e\r\n            \u003csvg class=\"navigation__li-link--arrow\" style=\"width:9px\" viewBox=\"0 0 6 10\" aria-label=\"\"\u003e\r\n              \u003cuse xlink:href=\"#icon-empty-arrow\"\u003e\u003c/use\u003e\r\n            \u003c/svg\u003e\r\n          \u003c/span\u003e\r\n        \u003c/a\u003e\r\n\r\n        \u003cdiv class=\"accessibility-arrow-container\"\u003e\u003c/div\u003e\r\n\r\n        \u003cdiv class=\"navigation__li-subcats level-2 js-navigation__level top-z\" data-ct-for-you-subcats=\"true\"\u003e\r\n          \u003cdiv class=\"navigation__li-subcats__container d-flex flex-direction-column navigation__li-subcats__container-no-touch text-left\"\u003e\r\n            \u003cdiv class=\"d-none nav-non-touch-device\"\u003e\u003c/div\u003e\r\n\r\n            \u003cdiv class=\"experience-region experience-detailsRegion\"\u003e\r\n              \u003cspan class=\"js-navigation-prev-next-mobile d-block nav-touch-device pd-navigation-btn text-center\"\u003e\r\n                ${COPY.label}\r\n                \u003cspan\u003e\r\n                  \u003csvg aria-hidden=\"true\" focusable=\"false\"\r\n                      style=\"width:20px;height:20px;margin-right:0;vertical-align:middle;display:inline-block;margin-top:-15px;\"\r\n                      viewBox=\"0 0 23 18\" xmlns=\"http://www.w3.org/2000/svg\"\u003e\r\n                    \u003cpath d=\"M5.43949 1.05205C5.57433 0.495998 6.03716 0.21797 6.5 0.217969C6.96284 0.217968 7.42567 0.495995 7.56051 1.05205L8.30252 4.1121C8.3988 4.50915 8.70882 4.81917 9.10587 4.91545L12.1659 5.65746C13.278 5.92713 13.278 7.50881 12.1659 7.77848L9.10587 8.52049C8.70882 8.61677 8.39881 8.92679 8.30253 9.32384L7.56051 12.3839C7.29084 13.496 5.70917 13.496 5.43949 12.3839L4.69748 9.32384C4.6012 8.92679 4.29118 8.61677 3.89413 8.52049L0.834083 7.77848C-0.278028 7.50881 -0.278028 5.92713 0.834083 5.65746L3.89413 4.91545C4.29118 4.81917 4.6012 4.50915 4.69748 4.1121L5.43949 1.05205Z\" fill=\"currentColor\"\u003e\u003c/path\u003e\r\n                    \u003cpath d=\"M11.5133 2.46797C10.961 2.46797 10.5133 2.02025 10.5133 1.46797C10.5133 0.915684 10.961 0.467969 11.5133 0.467969C12.0656 0.467969 12.5133 0.915684 12.5133 1.46797C12.5133 2.02025 12.0656 2.46797 11.5133 2.46797Z\" fill=\"currentColor\"\u003e\u003c/path\u003e\r\n                    \u003cpath d=\"M19 11.718C18.4477 11.718 18 11.2703 18 10.718C18 10.1657 18.4477 9.71797 19 9.71797C19.5523 9.71797 20 10.1657 20 10.718C20 11.2703 19.5523 11.718 19 11.718Z\" fill=\"currentColor\"\u003e\u003c/path\u003e\r\n                    \u003cpath d=\"M7.56051 17.3706C7.00823 17.3706 6.56051 16.9229 6.56051 16.3706C6.56051 15.8183 7.00823 15.3706 7.56051 15.3706C8.11279 15.3706 8.56051 15.8183 8.56051 16.3706C8.56051 16.9229 8.11279 17.3706 7.56051 17.3706Z\" fill=\"currentColor\"\u003e\u003c/path\u003e\r\n                  \u003c/svg\u003e\r\n                \u003c/span\u003e\r\n                \u003cspan class=\"arrow-back d-flex align-items-flex-center nav-touch-device\"\u003e\r\n                  \u003csvg class=\"arrow-back--svg\" style=\"width:9px\" viewBox=\"0 0 6 10\" aria-label=\"\"\u003e\r\n                    \u003cuse xlink:href=\"#icon-empty-arrow\"\u003e\u003c/use\u003e\r\n                  \u003c/svg\u003e\r\n                \u003c/span\u003e\r\n              \u003c/span\u003e\r\n\r\n              \u003cdiv class=\"ct-for-you-nav-panel\" data-ct-for-you-panel=\"true\"\u003e\r\n                \u003cul class=\"ct-for-you-nav-grid\" data-ct-for-you-grid=\"true\"\u003e\u003c/ul\u003e\r\n                \u003cp class=\"ct-for-you-nav-empty\" data-ct-for-you-empty=\"true\" style=\"display:none;\"\u003e\r\n                  No recommendations available right now. Please try again later.\r\n                \u003c/p\u003e\r\n              \u003c/div\u003e\r\n            \u003c/div\u003e\r\n\r\n            \u003cdiv class=\"js-trending-mobile-carousel nav-touch-device\"\u003e\u003c/div\u003e\r\n          \u003c/div\u003e\r\n        \u003c/div\u003e\r\n      \u003c/div\u003e\r\n    `;\r\n\r\n    const children = mobileNav.children;\r\n    if (children.length \u003e= 1) {\r\n      mobileNav.insertBefore(li, children[1] || null);\r\n    } else {\r\n      mobileNav.appendChild(li);\r\n    }\r\n  }\r\n\r\n  function hasExistingForYouTopNav() {\r\n    const navRoot = document.querySelector(\"#navigation\");\r\n    if (!navRoot) return false;\r\n\r\n    const links = navRoot.querySelectorAll(\"a\");\r\n    for (let i = 0; i \u003c links.length; i++) {\r\n      const txt = (links[i].textContent || \"\").trim().toLowerCase();\r\n      if (txt === COPY.label.toLowerCase()) return true;\r\n    }\r\n\r\n    return false;\r\n  }\r\n\r\n  function injectForYouNavItem() {\r\n    if (!isDesktopViewport()) return;\r\n\r\n    const navUl =\r\n      document.querySelector(\"#navigation .navigation__li-container--main\") ||\r\n      document.querySelector(\"#navigation .navigation-li-container\") ||\r\n      document.querySelector(\"#navigation ul\");\r\n\r\n    if (!navUl) return;\r\n    if (hasExistingForYouTopNav()) return;\r\n    if (navUl.querySelector('[data-ct-for-you-nav=\"true\"]')) return;\r\n\r\n    const li = document.createElement(\"li\");\r\n    li.setAttribute(\"role\", \"listitem\");\r\n    li.setAttribute(\"data-ct-for-you-nav\", \"true\");\r\n    li.className = \"js-nav-link-main navigation__li navigation__li--main\";\r\n\r\n    li.innerHTML = `\r\n    \u003cdiv class=\"experience-component experience-layouts-navItem\"\u003e\r\n      \u003ca data-hover=\"false\"\r\n         data-tracking=\"top-nav-parent-url\"\r\n         href=\"#\"\r\n         id=\"ct-for-you-nav-link\"\r\n         class=\"navigationItem-ct-foryou navigation__li-link navigation__li-link--has-sub navigation__li-link--color\r\n                has-sub-menu js-maincat cursor-pointer position-relative capitalize text-decoration-none d-block\r\n                grey1 mps-grey1 mls-grey1 ls-grey1\"\u003e\r\n        ${COPY.label}\r\n        \u003cspan\u003e\r\n          \u003csvg aria-hidden=\"true\" focusable=\"false\"\r\n              style=\"width:20px;height:20px;margin-right:0;vertical-align:middle;display:inline-block;margin-top:-15px;\"\r\n              viewBox=\"0 0 23 18\" xmlns=\"http://www.w3.org/2000/svg\"\u003e\r\n            \u003cpath d=\"M5.43949 1.05205C5.57433 0.495998 6.03716 0.21797 6.5 0.217969C6.96284 0.217968 7.42567 0.495995 7.56051 1.05205L8.30252 4.1121C8.3988 4.50915 8.70882 4.81917 9.10587 4.91545L12.1659 5.65746C13.278 5.92713 13.278 7.50881 12.1659 7.77848L9.10587 8.52049C8.70882 8.61677 8.39881 8.92679 8.30253 9.32384L7.56051 12.3839C7.29084 13.496 5.70917 13.496 5.43949 12.3839L4.69748 9.32384C4.6012 8.92679 4.29118 8.61677 3.89413 8.52049L0.834083 7.77848C-0.278028 7.50881 -0.278028 5.92713 0.834083 5.65746L3.89413 4.91545C4.29118 4.81917 4.6012 4.50915 4.69748 4.1121L5.43949 1.05205Z\" fill=\"currentColor\"\u003e\u003c/path\u003e\r\n            \u003cpath d=\"M11.5133 2.46797C10.961 2.46797 10.5133 2.02025 10.5133 1.46797C10.5133 0.915684 10.961 0.467969 11.5133 0.467969C12.0656 0.467969 12.5133 0.915684 12.5133 1.46797C12.5133 2.02025 12.0656 2.46797 11.5133 2.46797Z\" fill=\"currentColor\"\u003e\u003c/path\u003e\r\n            \u003cpath d=\"M19 11.718C18.4477 11.718 18 11.2703 18 10.718C18 10.1657 18.4477 9.71797 19 9.71797C19.5523 9.71797 20 10.1657 20 10.718C20 11.2703 19.5523 11.718 19 11.718Z\" fill=\"currentColor\"\u003e\u003c/path\u003e\r\n            \u003cpath d=\"M7.56051 17.3706C7.00823 17.3706 6.56051 16.9229 6.56051 16.3706C6.56051 15.8183 7.00823 15.3706 7.56051 15.3706C8.11279 15.3706 8.56051 15.8183 8.56051 16.3706C8.56051 16.9229 8.11279 17.3706 7.56051 17.3706Z\" fill=\"currentColor\"\u003e\u003c/path\u003e\r\n          \u003c/svg\u003e\r\n        \u003c/span\u003e\r\n\r\n        \u003cspan class=\"align-center-v right-z m-right-l nav-touch-device\"\u003e\r\n          \u003csvg class=\"navigation__li-link--arrow\" style=\"width:9px\" viewBox=\"0 0 6 10\" aria-label=\"\"\u003e\r\n            \u003cuse xlink:href=\"#icon-empty-arrow\"\u003e\u003c/use\u003e\r\n          \u003c/svg\u003e\r\n        \u003c/span\u003e\r\n      \u003c/a\u003e\r\n\r\n      \u003cdiv class=\"accessibility-arrow-container\"\u003e\u003c/div\u003e\r\n\r\n      \u003cdiv class=\"navigation__li-subcats level-2 js-navigation__level top-z\" data-ct-for-you-desktop-subcats=\"true\"\u003e\r\n        \u003cdiv class=\"navigation__li-subcats__container d-flex flex-direction-column navigation__li-subcats__container-no-touch text-left small-width\"\u003e\r\n          \u003cdiv class=\"d-none nav-non-touch-device\"\u003e\u003c/div\u003e\r\n\r\n          \u003cspan class=\"js-navigation-prev-next-mobile d-block nav-touch-device pd-navigation-btn text-center\"\u003e\r\n            ${COPY.label}\r\n            \u003cspan class=\"arrow-back d-flex align-items-flex-center nav-touch-device\"\u003e\r\n              \u003csvg class=\"arrow-back--svg\" style=\"width:9px\" viewBox=\"0 0 6 10\" aria-label=\"\"\u003e\r\n                \u003cuse xlink:href=\"#icon-empty-arrow\"\u003e\u003c/use\u003e\r\n              \u003c/svg\u003e\r\n            \u003c/span\u003e\r\n          \u003c/span\u003e\r\n\r\n          \u003cdiv class=\"experience-region experience-detailsRegion\"\u003e\r\n            \u003cdiv class=\"ct-for-you-desktop-panel\" data-ct-for-you-desktop-panel=\"true\"\u003e\r\n            \u003ch3 style=\"font-size: 16px; font-weight: 500;\"\r\n                class=\"navigationHeader-1099191298 mls-m-bottom-m m-top-s sentence-case-mobile uppercase \r\n                      font__primary grey1 mps-grey1 mls-grey1 ls-grey1\"\u003e\r\n                ${COPY.heading}\r\n            \u003c/h3\u003e\r\n              \u003cul class=\"ct-for-you-desktop-grid\" data-ct-for-you-desktop-grid=\"true\"\u003e\u003c/ul\u003e\r\n              \u003cp class=\"ct-for-you-desktop-empty\" data-ct-for-you-desktop-empty=\"true\" style=\"display:none;\"\u003e\r\n                No recommendations available right now. Please try again later.\r\n              \u003c/p\u003e\r\n            \u003c/div\u003e\r\n          \u003c/div\u003e\r\n\r\n          \u003cdiv class=\"js-trending-mobile-carousel nav-touch-device\"\u003e\u003c/div\u003e\r\n          \u003cdiv class=\"d-none nav-non-touch-device navigation__gallery\"\u003e\u003c/div\u003e\r\n        \u003c/div\u003e\r\n      \u003c/div\u003e\r\n    \u003c/div\u003e\r\n  `;\r\n\r\n    navUl.appendChild(li);\r\n  }\r\n\r\n  function fetchRecommendationsIntoDesktopNav(subcatsRoot) {\r\n    if (!subcatsRoot) return;\r\n\r\n    const grid = subcatsRoot.querySelector('[data-ct-for-you-desktop-grid=\"true\"]');\r\n    const emptyMsg = subcatsRoot.querySelector('[data-ct-for-you-desktop-empty=\"true\"]');\r\n    if (!grid) return;\r\n\r\n    const status = subcatsRoot.getAttribute(\"data-ct-status\") || \"idle\";\r\n    if (status === \"loading\" || status === \"loaded\") return;\r\n\r\n    subcatsRoot.setAttribute(\"data-ct-status\", \"loading\");\r\n    if (emptyMsg) emptyMsg.style.display = \"none\";\r\n\r\n    const tiles = paintSkeletonTiles(grid, buildDesktopTile, SKELETON_COUNT.desktop);\r\n\r\n    function setEmpty() {\r\n      if (!emptyMsg) return;\r\n      emptyMsg.style.display = grid.children.length ? \"none\" : \"block\";\r\n    }\r\n\r\n    CT_RECS.getIds()\r\n      .then(function (ids) {\r\n        // Empty means the SDK never answered, so leave the door open for a retry\r\n        subcatsRoot.setAttribute(\"data-ct-status\", ids.length ? \"loaded\" : \"idle\");\r\n\r\n        hydrateGrid({\r\n          grid: grid,\r\n          tiles: tiles,\r\n          ids: ids,\r\n          buildTile: buildDesktopTile,\r\n          max: MAX_DESKTOP,\r\n          onChange: setEmpty\r\n        });\r\n      })\r\n      .catch(function () {\r\n        subcatsRoot.setAttribute(\"data-ct-status\", \"idle\");\r\n        grid.removeAttribute(\"data-ct-skeleton\");\r\n        grid.innerHTML = \"\";\r\n        setEmpty();\r\n      });\r\n  }\r\n\r\n  function fetchRecommendationsIntoMobileNav(subcatsRoot) {\r\n    if (!subcatsRoot) return;\r\n\r\n    const grid = subcatsRoot.querySelector('[data-ct-for-you-grid=\"true\"]');\r\n    const emptyMsg = subcatsRoot.querySelector('[data-ct-for-you-empty=\"true\"]');\r\n    if (!grid) return;\r\n\r\n    const status = subcatsRoot.getAttribute(\"data-ct-status\") || \"idle\";\r\n    if (status === \"loading\" || status === \"loaded\") return;\r\n\r\n    subcatsRoot.setAttribute(\"data-ct-status\", \"loading\");\r\n    if (emptyMsg) emptyMsg.style.display = \"none\";\r\n\r\n    const tiles = paintSkeletonTiles(grid, buildMobileNavTile, SKELETON_COUNT.mobile);\r\n\r\n    function setEmpty() {\r\n      if (!emptyMsg) return;\r\n      emptyMsg.style.display = grid.children.length ? \"none\" : \"block\";\r\n    }\r\n\r\n    CT_RECS.getIds()\r\n      .then(function (ids) {\r\n        // Empty means the SDK never answered, so leave the door open for a retry\r\n        subcatsRoot.setAttribute(\"data-ct-status\", ids.length ? \"loaded\" : \"idle\");\r\n\r\n        hydrateGrid({\r\n          grid: grid,\r\n          tiles: tiles,\r\n          ids: ids,\r\n          buildTile: buildMobileNavTile,\r\n          max: MAX_ITEMS,\r\n          onChange: setEmpty\r\n        });\r\n      })\r\n      .catch(function () {\r\n        subcatsRoot.setAttribute(\"data-ct-status\", \"idle\");\r\n        grid.removeAttribute(\"data-ct-skeleton\");\r\n        grid.innerHTML = \"\";\r\n        setEmpty();\r\n      });\r\n  }\r\n\r\n  function fetchRecommendations() {\r\n    const grid = document.getElementById(\"ct-for-you-product-grid\");\r\n    const emptyMsg = document.querySelector(\".ct-for-you-grid-empty\");\r\n    if (!grid) return;\r\n\r\n    if (emptyMsg) emptyMsg.style.display = \"none\";\r\n\r\n    const tiles = paintSkeletonTiles(grid, buildOverlayTile, SKELETON_COUNT.overlay);\r\n\r\n    function setEmpty() {\r\n      if (!emptyMsg) return;\r\n      emptyMsg.style.display = grid.children.length ? \"none\" : \"block\";\r\n    }\r\n\r\n    CT_RECS.getIds()\r\n      .then(function (ids) {\r\n        hydrateGrid({\r\n          grid: grid,\r\n          tiles: tiles,\r\n          ids: ids,\r\n          buildTile: buildOverlayTile,\r\n          max: MAX_ITEMS,\r\n          onChange: setEmpty\r\n        });\r\n      })\r\n      .catch(function () {\r\n        grid.removeAttribute(\"data-ct-skeleton\");\r\n        grid.innerHTML = \"\";\r\n        setEmpty();\r\n      });\r\n  }\r\n\r\n  function adjustMobilePillNav() {\r\n    if (!isMobileView()) return;\r\n\r\n    const wrapper = document.querySelector(\".experience-region.experience-fixedPinsWrapper\");\r\n    if (!wrapper) return;\r\n\r\n    const forYouComponent = Array.from(\r\n      wrapper.querySelectorAll(\".experience-component.experience-assets-textInfoCta\")\r\n    ).find((comp) =\u003e {\r\n      const a = comp.querySelector(\"a.text-info-cta-8926321849--link, a\");\r\n      return a \u0026\u0026 a.textContent.trim().toLowerCase() === \"for you\";\r\n    });\r\n\r\n    if (forYouComponent \u0026\u0026 wrapper.children.length \u003e 0) {\r\n      const first = wrapper.children[0];\r\n      if (first \u0026\u0026 first !== forYouComponent) {\r\n        wrapper.insertBefore(forYouComponent, first.nextSibling);\r\n      }\r\n    }\r\n\r\n    const pillLink = forYouComponent ? forYouComponent.querySelector(\"a\") : null;\r\n\r\n    if (pillLink) {\r\n      pillLink.style.padding = \"5px 25px\";\r\n      pillLink.style.margin = \"0 5px\";\r\n      pillLink.style.lineHeight = \"initial\";\r\n      pillLink.style.width = \"fit-content\";\r\n      pillLink.style.borderRadius = \"15px\";\r\n    }\r\n  }\r\n\r\n  function getFocusableElements(container) {\r\n    if (!container) return [];\r\n\r\n    const selectors = [\r\n      'a[href]',\r\n      'area[href]',\r\n      'button:not([disabled])',\r\n      'input:not([disabled]):not([type=\"hidden\"])',\r\n      'select:not([disabled])',\r\n      'textarea:not([disabled])',\r\n      'iframe',\r\n      'object',\r\n      'embed',\r\n      '[contenteditable=\"true\"]',\r\n      '[tabindex]:not([tabindex=\"-1\"])'\r\n    ].join(\",\");\r\n\r\n    return Array.from(container.querySelectorAll(selectors)).filter((el) =\u003e {\r\n      if (!el) return false;\r\n      if (el.hasAttribute(\"disabled\")) return false;\r\n      if (el.getAttribute(\"aria-hidden\") === \"true\") return false;\r\n      if (el.getAttribute(\"tabindex\") === \"-1\") return false;\r\n\r\n      const style = window.getComputedStyle(el);\r\n      if (style.display === \"none\" || style.visibility === \"hidden\") return false;\r\n\r\n      return true;\r\n    });\r\n  }\r\n\r\n  function getMobilePanelElements() {\r\n    const subcats = document.querySelector('[data-ct-for-you-subcats=\"true\"]');\r\n    if (!subcats) return {};\r\n\r\n    const container =\r\n      subcats.querySelector(\".navigation__li-subcats__container\") || subcats;\r\n\r\n    const closeBtn =\r\n      subcats.querySelector(\".js-navigation-prev-next-mobile\") || null;\r\n\r\n    return {\r\n      subcats,\r\n      container,\r\n      closeBtn\r\n    };\r\n  }\r\n\r\n  function focusOverlayStart() {\r\n    if (!ctForYouLastInteractionWasKeyboard) return;\r\n\r\n    const overlay = document.getElementById(\"ct-for-you-overlay\");\r\n    if (!overlay) return;\r\n\r\n    const panel = overlay.querySelector(\".ct-for-you-overlay__panel\");\r\n    const closeBtn = overlay.querySelector(\".ct-for-you-overlay__close-x\");\r\n\r\n    const moveFocus = () =\u003e {\r\n      if (!overlay.classList.contains(\"ct-for-you-overlay--open\")) return;\r\n\r\n      if (closeBtn) {\r\n        closeBtn.focus();\r\n        return;\r\n      }\r\n\r\n      const focusables = getFocusableElements(panel);\r\n      if (focusables.length) {\r\n        focusables[0].focus();\r\n        return;\r\n      }\r\n\r\n      if (panel) {\r\n        panel.setAttribute(\"tabindex\", \"-1\");\r\n        panel.focus();\r\n      }\r\n    };\r\n\r\n    requestAnimationFrame(() =\u003e {\r\n      requestAnimationFrame(moveFocus);\r\n    });\r\n  }\r\n\r\n  function focusMobilePanelStart() {\r\n    if (!ctForYouLastInteractionWasKeyboard) return;\r\n\r\n    const els = getMobilePanelElements();\r\n    if (!els.subcats || !els.container) return;\r\n\r\n    const moveFocus = () =\u003e {\r\n      const activePanel = els.subcats.classList.contains(\"navigation__li-subcats--active\") ||\r\n        els.subcats.classList.contains(\"active\") ||\r\n        els.subcats.getAttribute(\"aria-hidden\") === \"false\" ||\r\n        window.getComputedStyle(els.subcats).display !== \"none\";\r\n\r\n      if (!activePanel) return;\r\n\r\n      if (els.closeBtn) {\r\n        if (!els.closeBtn.hasAttribute(\"tabindex\")) {\r\n          els.closeBtn.setAttribute(\"tabindex\", \"0\");\r\n        }\r\n        els.closeBtn.focus();\r\n        return;\r\n      }\r\n\r\n      const focusables = getFocusableElements(els.container);\r\n      if (focusables.length) {\r\n        focusables[0].focus();\r\n        return;\r\n      }\r\n\r\n      els.container.setAttribute(\"tabindex\", \"-1\");\r\n      els.container.focus();\r\n    };\r\n\r\n    requestAnimationFrame(() =\u003e {\r\n      requestAnimationFrame(moveFocus);\r\n    });\r\n  }\r\n\r\n  function removeOverlayFocusTrap() {\r\n    if (ctForYouOverlayKeydownHandler) {\r\n      document.removeEventListener(\"keydown\", ctForYouOverlayKeydownHandler, true);\r\n      ctForYouOverlayKeydownHandler = null;\r\n    }\r\n  }\r\n\r\n  function trapOverlayFocus() {\r\n    const overlay = document.getElementById(\"ct-for-you-overlay\");\r\n    if (!overlay) return;\r\n\r\n    const panel = overlay.querySelector(\".ct-for-you-overlay__panel\");\r\n    if (!panel) return;\r\n\r\n    removeOverlayFocusTrap();\r\n\r\n    ctForYouOverlayKeydownHandler = function (e) {\r\n      if (!overlay.classList.contains(\"ct-for-you-overlay--open\")) return;\r\n\r\n      if (e.key === \"Escape\") {\r\n        e.preventDefault();\r\n        closeOverlay();\r\n        return;\r\n      }\r\n\r\n      if (e.key !== \"Tab\") return;\r\n\r\n      const focusables = getFocusableElements(panel);\r\n\r\n      if (!focusables.length) {\r\n        e.preventDefault();\r\n        panel.setAttribute(\"tabindex\", \"-1\");\r\n        panel.focus();\r\n        return;\r\n      }\r\n\r\n      const first = focusables[0];\r\n      const last = focusables[focusables.length - 1];\r\n      const active = document.activeElement;\r\n\r\n      if (e.shiftKey) {\r\n        if (active === first || !panel.contains(active)) {\r\n          e.preventDefault();\r\n          last.focus();\r\n        }\r\n      } else {\r\n        if (active === last || !panel.contains(active)) {\r\n          e.preventDefault();\r\n          first.focus();\r\n        }\r\n      }\r\n    };\r\n\r\n    document.addEventListener(\"keydown\", ctForYouOverlayKeydownHandler, true);\r\n  }\r\n\r\n  function ensureOverlay() {\r\n    if (document.getElementById(\"ct-for-you-overlay\")) return;\r\n\r\n    const cssId = \"ct-for-you-overlay-css\";\r\n    if (!document.getElementById(cssId)) {\r\n      const style = document.createElement(\"style\");\r\n      style.id = cssId;\r\n      style.textContent = `\r\n[data-ct-for-you-desktop-subcats=\"true\"] .navigation__li-subcats__container {\r\n  width: 100%;\r\n  max-width: 1200px !important;\r\n  margin: 0 auto;\r\n}\r\n\r\n.ct-for-you-desktop-grid {\r\n  display: grid;\r\n  grid-template-columns: repeat(6, minmax(0, 1fr));\r\n  gap: 10px;\r\n  list-style: none;\r\n  margin: 0;\r\n  padding: 0;\r\n  width: 100%;\r\n}\r\n\r\n/*\r\n  The nav dropdown is content-sized, so placeholder tiles with no intrinsic\r\n  width would collapse it. Hold a floor until real images arrive.\r\n*/\r\n.ct-for-you-desktop-grid[data-ct-skeleton=\"true\"] {\r\n  grid-template-columns: repeat(6, minmax(150px, 1fr));\r\n}\r\n\r\n.ct-for-you-desktop-tile a {\r\n  display: block;\r\n  text-decoration: none;\r\n  color: inherit;\r\n}\r\n\r\n.ct-for-you-desktop-tile img {\r\n  width: 100%;\r\n  aspect-ratio: 4 / 5;\r\n  height: auto;\r\n  object-fit: cover;\r\n  display: block;\r\n  background: #fff;\r\n}\r\n\r\n.ct-for-you-desktop-title {\r\n  font-family: Futura, sans-serif;\r\n  font-size: 1.6rem;\r\n  line-height: 1.2;\r\n  color: #373737;\r\n  margin: 5px 0 2px;\r\n  display: -webkit-box;\r\n  -webkit-line-clamp: 2;\r\n  -webkit-box-orient: vertical;\r\n  overflow: hidden;\r\n  /* Two lines at 1.6rem/1.2, so one and two line titles keep prices aligned */\r\n  min-height: 3.84rem;\r\n}\r\n\r\n.ct-for-you-desktop-price {\r\n  font-family: Futura, sans-serif;\r\n  font-size: 1.6rem;\r\n  line-height: 1.2;\r\n  color: #373737;\r\n}\r\n\r\n.ct-for-you-desktop-panel {\r\n  padding: 0px 15px 15px !important;\r\n  width: min(1200px, calc(100vw - 100px)) !important;\r\n  max-width: calc(100vw - 100px) !important;\r\n  box-sizing: border-box !important;\r\n  margin-right: auto !important;\r\n  margin-left: auto !important;\r\n}\r\n\r\n.ct-for-you-desktop-empty {\r\n  font-family: Futura, Arial, sans-serif;\r\n  font-size: 1.4rem;\r\n  color: #373737;\r\n  margin: 0;\r\n}\r\n\r\n.ct-for-you-nav-panel { padding: 12px 16px 24px; }\r\n.ct-for-you-nav-grid {\r\n  list-style: none;\r\n  margin: 0;\r\n  padding: 0;\r\n  display: grid;\r\n  grid-template-columns: repeat(2, minmax(0,1fr));\r\n  gap: 4px;\r\n}\r\n\r\n.ct-for-you-nav-tile a { text-decoration: none; display: block; }\r\n.ct-for-you-nav-tile img {\r\n  width: 100%;\r\n  aspect-ratio: 430 / 538;\r\n  height: auto;\r\n  object-fit: cover;\r\n  display: block;\r\n  background: #fff;\r\n}\r\n.ct-for-you-nav-title {\r\n  font-family: Futura, sans-serif;\r\n  font-size: 1.6rem;\r\n  line-height: 1.2;\r\n  color: #373737;\r\n  margin: 8px 0 4px;\r\n  display: -webkit-box;\r\n  -webkit-line-clamp: 2;\r\n  -webkit-box-orient: vertical;\r\n  overflow: hidden;\r\n  min-height: 3.84rem;\r\n}\r\n.ct-for-you-nav-price { font-family: Futura, sans-serif; font-size: 1.6rem; color: #373737; }\r\n.ct-for-you-nav-empty { font-family: Futura, Arial, sans-serif; font-size: 1.6rem; }\r\n\r\n/* ---------- Loading states ---------- */\r\n\r\n@keyframes ct-for-you-shimmer {\r\n  0%   { background-position: 200% 0; }\r\n  100% { background-position: -200% 0; }\r\n}\r\n\r\n.ct-for-you-skel {\r\n  background: linear-gradient(90deg, #f4f4f4 25%, #eaeaea 37%, #f4f4f4 63%);\r\n  background-size: 200% 100%;\r\n  animation: ct-for-you-shimmer 1.4s ease-in-out infinite;\r\n  border-radius: 2px;\r\n}\r\n\r\n/* Sized to the real type: 1.6rem at line-height 1.2 */\r\n.ct-for-you-skel-line {\r\n  display: block;\r\n  height: 1.6rem;\r\n  margin: 0 0 4px;\r\n}\r\n\r\n.ct-for-you-skel-line:last-child { margin-bottom: 0; }\r\n.ct-for-you-skel-line--short { width: 45%; }\r\n.ct-for-you-skel-line--mid { width: 70%; }\r\n\r\n.ct-for-you-desktop-tile [data-ct-collar-wrap].ct-for-you-skel { aspect-ratio: 4 / 5; }\r\n.ct-for-you-nav-tile [data-ct-collar-wrap].ct-for-you-skel { aspect-ratio: 430 / 538; }\r\n\r\n/* Once the real image has decoded, kill the placeholder treatment */\r\n[data-ct-image-ok=\"true\"] .ct-for-you-skel {\r\n  background: #fff;\r\n  animation: none;\r\n}\r\n\r\n.ct-for-you-desktop-tile img,\r\n.ct-for-you-nav-tile img,\r\n.ct-for-you-tile img {\r\n  opacity: 0;\r\n  transition: opacity 180ms ease;\r\n}\r\n\r\n.ct-for-you-desktop-tile[data-ct-image-ok=\"true\"] img,\r\n.ct-for-you-nav-tile[data-ct-image-ok=\"true\"] img,\r\n.ct-for-you-tile[data-ct-image-ok=\"true\"] img {\r\n  opacity: 1;\r\n}\r\n\r\n/* Placeholder tiles are not clickable */\r\n[data-ct-skeleton=\"true\"] { pointer-events: none; }\r\n\r\n.ct-for-you-overlay {\r\n  position: fixed;\r\n  inset: 0;\r\n  z-index: 9999;\r\n  opacity: 0;\r\n  visibility: hidden;\r\n  pointer-events: none;\r\n  transition: opacity 220ms ease, visibility 0ms linear 220ms;\r\n}\r\n\r\n.ct-for-you-overlay--open {\r\n  opacity: 1;\r\n  visibility: visible;\r\n  pointer-events: auto;\r\n  transition: opacity 220ms ease;\r\n}\r\n\r\n.ct-for-you-overlay__backdrop {\r\n  position: absolute;\r\n  inset: 0;\r\n  background: rgba(0,0,0,0.35);\r\n}\r\n\r\n.ct-for-you-overlay__panel {\r\n  position: absolute;\r\n  top: 0;\r\n  bottom: 0;\r\n  right: 0;\r\n  left: auto;\r\n  width: 100%;\r\n  background: #fff;\r\n  overflow: auto;\r\n  transform: translate3d(110%, 0, 0);\r\n  transition: transform 360ms cubic-bezier(0.22, 1, 0.36, 1);\r\n  will-change: transform;\r\n}\r\n\r\n@media (min-width: 1024px) {\r\n  .ct-for-you-overlay__panel {\r\n    width: 40%;\r\n  }\r\n}\r\n\r\n.ct-for-you-overlay--open .ct-for-you-overlay__panel {\r\n  transform: translate3d(0, 0, 0);\r\n}\r\n\r\n.ct-for-you-grid-wrapper { padding: 1.5rem 1rem 3rem; }\r\n.ct-for-you-grid-copy {\r\n  margin: 0 0 1.5rem;\r\n  font-family: \"Futura\", \"Helvetica Neue\", Helvetica, Arial, sans-serif;\r\n  font-size: 1.6rem;\r\n  color: #373737;\r\n}\r\n\r\n#ct-for-you-product-grid {\r\n  list-style: none;\r\n  padding: 0;\r\n  margin: 0;\r\n  display: grid;\r\n  grid-template-columns: repeat(2, minmax(0,1fr));\r\n  gap: 0.4rem;\r\n}\r\n@media (min-width: 768px) {\r\n  #ct-for-you-product-grid { grid-template-columns: repeat(3, minmax(0,1fr)); }\r\n  .ct-for-you-nav-tile{margin-top:5px};\r\n}\r\n\r\n.ct-for-you-tile .product-tile__img-link { display: block; }\r\n.ct-for-you-tile img { width: 100%; display: block; background: #fff; }\r\n.ct-for-you-tile .js-product-tile-name { font-family: Futura, sans-serif; font-size: 1.6rem; color: #373737; }\r\n.ct-for-you-tile .tile__pricing { font-size: 1.6rem; }\r\n.ct-for-you-price-was { text-decoration: line-through; opacity: .7; margin-right: .4rem; color: #8a8a8a; }\r\n.ct-for-you-price-now { font-weight: 600; }\r\n.ct-for-you-grid-empty {\r\n  font-family: \"Futura\", \"Helvetica Neue\", Helvetica, Arial, sans-serif;\r\n  font-size: 1.6rem;\r\n  padding: 1rem 0;\r\n}\r\n\r\n#ct-for-you-heading {\r\n  font-size: 3.2rem;\r\n  letter-spacing: 0;\r\n}\r\n\r\n.ct-for-you-overlay__close-x {\r\n  position: absolute;\r\n  top: 1.5rem;\r\n  right: 1.5rem;\r\n  z-index: 2;\r\n  width: 2.6rem;\r\n  height: 2.6rem;\r\n  padding: 0;\r\n  border: 0;\r\n  border-radius: 999px;\r\n  background: transparent;\r\n  cursor: pointer;\r\n  display: inline-flex;\r\n  align-items: center;\r\n  justify-content: center;\r\n}\r\n.ct-for-you-overlay__close-x svg {\r\n  width: 3.2rem;\r\n  height: 3.2rem;\r\n  fill: #8a8a8a;\r\n}\r\n.ct-for-you-overlay__close-x:focus-visible {\r\n  outline: 2px solid #373737;\r\n  outline-offset: 2px;\r\n}\r\n\r\n.product-tile__collar-label {\r\n  line-height: normal;\r\n  font-size: 1.2rem;\r\n  padding: 0.3rem;\r\n  border-radius: 0 0 0.5rem 0.5rem;\r\n  z-index: 1;\r\n  bottom: -2.2rem;\r\n  left: 0;\r\n}\r\n\r\n.ct-for-you-desktop-tile [data-ct-collar-wrap],\r\n.ct-for-you-nav-tile [data-ct-collar-wrap] {\r\n  position: relative;\r\n  display: block;\r\n}\r\n\r\n.ct-for-you-desktop-tile .product-tile__collar-label,\r\n.ct-for-you-nav-tile .product-tile__collar-label {\r\n  position: absolute;\r\n  width: 100%;\r\n}\r\n\r\n.ct-for-you-desktop-tile [data-ct-collar-wrap].ct-for-you-has-collar + .ct-for-you-desktop-title,\r\n.ct-for-you-nav-tile [data-ct-collar-wrap].ct-for-you-has-collar + .ct-for-you-nav-title {\r\n  margin-top: 2.6rem;\r\n}\r\n\r\n@media (prefers-reduced-motion: reduce) {\r\n  .ct-for-you-overlay,\r\n  .ct-for-you-overlay__panel {\r\n    transition: none !important;\r\n    transform: none !important;\r\n  }\r\n\r\n  .ct-for-you-skel { animation: none; }\r\n\r\n  .ct-for-you-desktop-tile img,\r\n  .ct-for-you-nav-tile img,\r\n  .ct-for-you-tile img { transition: none; }\r\n}`;\r\n      document.head.appendChild(style);\r\n    }\r\n\r\n    const overlay = document.createElement(\"div\");\r\n    overlay.id = \"ct-for-you-overlay\";\r\n    overlay.className = \"ct-for-you-overlay\";\r\n    overlay.setAttribute(\"aria-hidden\", \"true\");\r\n    overlay.innerHTML = `\r\n      \u003cdiv class=\"ct-for-you-overlay__backdrop\" data-ct-for-you-close=\"true\"\u003e\u003c/div\u003e\r\n      \u003cdiv class=\"ct-for-you-overlay__panel\" role=\"dialog\" aria-modal=\"true\" aria-labelledby=\"ct-for-you-heading\"\u003e\r\n        \u003cdiv class=\"primary-content plp-grid primary-content-suits main__primary main__primary--right float-right col-100 p-all-z\"\u003e\r\n          \u003cdiv class=\"ct-for-you-grid-wrapper\"\u003e\r\n            \u003cdiv class=\"d-flex mps-m-bottom-m\"\u003e\r\n              \u003cdiv class=\"col-100 mls-col-50 d-flex flex-direction-column tib-banner flex-grow-1\"\u003e\r\n                \u003cbutton type=\"button\" class=\"ct-for-you-overlay__close-x\" data-ct-for-you-close=\"true\" aria-label=\"Close\"\u003e\r\n                  \u003csvg viewBox=\"0 0 24 24\" aria-hidden=\"true\" focusable=\"false\"\u003e\r\n                    \u003cpath d=\"M6 6L18 18M18 6L6 18\"\r\n                          fill=\"none\"\r\n                          stroke=\"#8a8a8a\"\r\n                          stroke-width=\"1.2\"\r\n                          stroke-linecap=\"round\"\r\n                          stroke-linejoin=\"round\"\u003e\u003c/path\u003e\r\n                  \u003c/svg\u003e\r\n                \u003c/button\u003e\r\n\r\n                \u003cdiv class=\"p-ends-m p-sides-xs col-100 text-left overflow-hidden\"\u003e\r\n                  \u003cp id=\"ct-for-you-heading\"\r\n                    class=\"m-ends-m col-100 grey1 p-sides-z font__secondary medium\"\r\n                    style=\"display:flex;align-items:center;gap:.6rem;\"\u003e\r\n                    For You\r\n                  \u003c/p\u003e\r\n                  \u003csvg aria-hidden=\"true\" focusable=\"false\"\r\n                      style=\"width: 30px; height: 30px; display: inline-block; position: absolute; top: 35px; left: 120px;\"\r\n                      viewBox=\"0 0 23 18\" xmlns=\"http://www.w3.org/2000/svg\"\u003e\r\n                    \u003cpath d=\"M5.43949 1.05205C5.57433 0.495998 6.03716 0.21797 6.5 0.217969C6.96284 0.217968 7.42567 0.495995 7.56051 1.05205L8.30252 4.1121C8.3988 4.50915 8.70882 4.81917 9.10587 4.91545L12.1659 5.65746C13.278 5.92713 13.278 7.50881 12.1659 7.77848L9.10587 8.52049C8.70882 8.61677 8.39881 8.92679 8.30253 9.32384L7.56051 12.3839C7.29084 13.496 5.70917 13.496 5.43949 12.3839L4.69748 9.32384C4.6012 8.92679 4.29118 8.61677 3.89413 8.52049L0.834083 7.77848C-0.278028 7.50881 -0.278028 5.92713 0.834083 5.65746L3.89413 4.91545C4.29118 4.81917 4.6012 4.50915 4.69748 4.1121L5.43949 1.05205Z\" fill=\"currentColor\"/\u003e\r\n                    \u003cpath d=\"M11.5133 2.46797C10.961 2.46797 10.5133 2.02025 10.5133 1.46797C10.5133 0.915684 10.961 0.467969 11.5133 0.467969C12.0656 0.467969 12.5133 0.915684 12.5133 1.46797C12.5133 2.02025 12.0656 2.46797 11.5133 2.46797Z\" fill=\"currentColor\"/\u003e\r\n                    \u003cpath d=\"M19 11.718C18.4477 11.718 18 11.2703 18 10.718C18 10.1657 18.4477 9.71797 19 9.71797C19.5523 9.71797 20 10.1657 20 10.718C20 11.2703 19.5523 11.718 19 11.718Z\" fill=\"currentColor\"/\u003e\r\n                    \u003cpath d=\"M7.56051 17.3706C7.00823 17.3706 6.56051 16.9229 6.56051 16.3706C6.56051 15.8183 7.00823 15.3706 7.56051 15.3706C8.11279 15.3706 8.56051 15.8183 8.56051 16.3706C8.56051 16.9229 8.11279 17.3706 7.56051 17.3706Z\" fill=\"currentColor\"/\u003e\r\n                  \u003c/svg\u003e\r\n                  \u003cdiv class=\"js-tib-id top-info__banner--text col-100 p-sides-z position-relative\"\u003e\r\n                    \u003cp class=\"ct-for-you-grid-copy\"\u003e${COPY.subheading}\u003c/p\u003e\r\n                  \u003c/div\u003e\r\n                \u003c/div\u003e\r\n              \u003c/div\u003e\r\n            \u003c/div\u003e\r\n\r\n            \u003cdiv class=\"mls-d-flex mls-flex-direction-row search-result__container mps-m-top-s\"\u003e\r\n              \u003cdiv class=\"plp-grid__wrapper flex-grow-1 m-top-m mls-m-top-z\"\u003e\r\n                \u003cdiv class=\"js-infinite-scroll search-result-content content__row clearfix tile__items-container m-all-z position-relative\"\u003e\r\n                  \u003cdiv class=\"plp-grid__main-subcat\"\u003e\r\n                    \u003cul id=\"ct-for-you-product-grid\" class=\"js-product-grid-container plp-grid__container plp-grid__container--2-col-mobile plp-grid__container--4-col-desktop\"\u003e\u003c/ul\u003e\r\n                    \u003cp class=\"ct-for-you-grid-empty\" style=\"display:none;\"\u003eNo recommendations available right now. Please try again later.\u003c/p\u003e\r\n                  \u003c/div\u003e\r\n                \u003c/div\u003e\r\n              \u003c/div\u003e\r\n            \u003c/div\u003e\r\n\r\n          \u003c/div\u003e\r\n        \u003c/div\u003e\r\n      \u003c/div\u003e`;\r\n    document.body.appendChild(overlay);\r\n\r\n    overlay.addEventListener(\"click\", (e) =\u003e {\r\n      const closeEl = e.target \u0026\u0026 e.target.closest \u0026\u0026 e.target.closest('[data-ct-for-you-close=\"true\"]');\r\n      if (closeEl) closeOverlay();\r\n    });\r\n  }\r\n\r\n  function openOverlay(triggerEl) {\r\n    ensureOverlay();\r\n    const overlay = document.getElementById(\"ct-for-you-overlay\");\r\n    if (!overlay) return;\r\n\r\n    ctForYouLastFocusedTrigger = triggerEl || document.activeElement || null;\r\n\r\n    overlay.classList.add(\"ct-for-you-overlay--open\");\r\n    overlay.setAttribute(\"aria-hidden\", \"false\");\r\n\r\n    trapOverlayFocus();\r\n    focusOverlayStart();\r\n\r\n    if (!overlay.getAttribute(\"data-ct-loaded\")) {\r\n      overlay.setAttribute(\"data-ct-loaded\", \"true\");\r\n      fetchRecommendations();\r\n    }\r\n  }\r\n\r\n  function closeOverlay() {\r\n    const overlay = document.getElementById(\"ct-for-you-overlay\");\r\n    if (!overlay) return;\r\n\r\n    overlay.classList.remove(\"ct-for-you-overlay--open\");\r\n    overlay.setAttribute(\"aria-hidden\", \"true\");\r\n\r\n    removeOverlayFocusTrap();\r\n\r\n    if (\r\n      ctForYouLastFocusedTrigger \u0026\u0026\r\n      typeof ctForYouLastFocusedTrigger.focus === \"function\" \u0026\u0026\r\n      document.contains(ctForYouLastFocusedTrigger)\r\n    ) {\r\n      requestAnimationFrame(() =\u003e {\r\n        ctForYouLastFocusedTrigger.focus();\r\n      });\r\n    }\r\n  }\r\n\r\n  function wireClicks() {\r\n    const navLink =\r\n      document.getElementById(\"ct-for-you-nav-link\") ||\r\n      document.querySelector(\"#navigation a#ct-for-you-nav-link\");\r\n\r\n    if (navLink \u0026\u0026 !navLink.getAttribute(\"data-ct-bound\")) {\r\n      navLink.setAttribute(\"data-ct-bound\", \"true\");\r\n      markKeyboardInteractionOnTrigger(navLink);\r\n\r\n      navLink.addEventListener(\"click\", (e) =\u003e {\r\n        e.preventDefault();\r\n        trackForYouClick();\r\n        openOverlay(e.currentTarget);\r\n      });\r\n\r\n      const parentLi = navLink.closest(\"li\");\r\n      const subcats = parentLi\r\n        ? parentLi.querySelector('[data-ct-for-you-desktop-subcats=\"true\"]')\r\n        : document.querySelector('[data-ct-for-you-desktop-subcats=\"true\"]');\r\n\r\n      const loadDesktopPanel = () =\u003e {\r\n        if (subcats) fetchRecommendationsIntoDesktopNav(subcats);\r\n      };\r\n\r\n      // Hover intent: a cursor sweeping across the nav should not pull recs\r\n      if (parentLi) {\r\n        parentLi.addEventListener(\"mouseenter\", () =\u003e {\r\n          clearTimeout(ctDesktopHoverTimer);\r\n          ctDesktopHoverTimer = setTimeout(loadDesktopPanel, DESKTOP_HOVER_DELAY_MS);\r\n        });\r\n\r\n        parentLi.addEventListener(\"mouseleave\", () =\u003e {\r\n          clearTimeout(ctDesktopHoverTimer);\r\n        });\r\n      }\r\n\r\n      // Keyboard arrival is unambiguous, so load immediately\r\n      navLink.addEventListener(\"focusin\", loadDesktopPanel);\r\n    }\r\n\r\n    const mobileTopLink = document.getElementById(\"ct-for-you-mobile-nav-link\");\r\n    if (mobileTopLink \u0026\u0026 !mobileTopLink.getAttribute(\"data-ct-bound\")) {\r\n      mobileTopLink.setAttribute(\"data-ct-bound\", \"true\");\r\n      markKeyboardInteractionOnTrigger(mobileTopLink);\r\n\r\n      mobileTopLink.addEventListener(\"click\", (e) =\u003e {\r\n        trackForYouClick();\r\n\r\n        requestAnimationFrame(() =\u003e {\r\n          const subcats = document.querySelector('[data-ct-for-you-subcats=\"true\"]');\r\n          if (subcats) {\r\n            fetchRecommendationsIntoMobileNav(subcats);\r\n            focusMobilePanelStart();\r\n          }\r\n        });\r\n      });\r\n    }\r\n\r\n    const pillLink = Array.from(\r\n      document.querySelectorAll(\".experience-fixedPinsWrapper a\")\r\n    ).find((a) =\u003e a.textContent.trim().toLowerCase() === \"for you\");\r\n\r\n    if (pillLink \u0026\u0026 !pillLink.getAttribute(\"data-ct-bound\")) {\r\n      pillLink.setAttribute(\"data-ct-bound\", \"true\");\r\n      markKeyboardInteractionOnTrigger(pillLink);\r\n\r\n      pillLink.addEventListener(\"click\", (e) =\u003e {\r\n        e.preventDefault();\r\n        openOverlay(e.currentTarget);\r\n      });\r\n    }\r\n  }\r\n\r\n  function hasSaleNavItem() {\r\n    const navRoot = document.querySelector(\"#navigation\");\r\n    if (!navRoot) return false;\r\n\r\n    const lang = String(window.utag_data?.global?.site_language || \"\").toUpperCase();\r\n\r\n    const saleTerms = [\"sale\"];\r\n    if (lang.includes(\"FR\")) saleTerms.push(\"soldes\");\r\n    if (lang.includes(\"DE\")) saleTerms.push(\"angebote\");\r\n\r\n    // Only look at top-level nav \u003cli\u003e items, not sub-menu or promo links\r\n    const topLevelItems = navRoot.querySelectorAll(\r\n      \"li.js-nav-link-main.navigation__li--main \u003e div.experience-component \u003e a\"\r\n    );\r\n\r\n    for (let i = 0; i \u003c topLevelItems.length; i++) {\r\n      // Use direct text nodes only, to avoid picking up nested SVG/span text\r\n      const rawText = Array.from(topLevelItems[i].childNodes)\r\n        .filter(function (n) { return n.nodeType === Node.TEXT_NODE; })\r\n        .map(function (n) { return n.textContent.trim(); })\r\n        .join(\"\")\r\n        .trim()\r\n        .toLowerCase();\r\n\r\n      if (saleTerms.includes(rawText)) return true;\r\n    }\r\n\r\n    return false;\r\n  }\r\n\r\n  function init() {\r\n    if (hasSaleNavItem()) return;\r\n\r\n    bindInteractionModeTracking();\r\n    injectForYouNavItem();\r\n    injectForYouMobileNavItem();\r\n    adjustMobilePillNav();\r\n    ensureOverlay();\r\n    wireClicks();\r\n\r\n    // No prefetch. Recommendations are pulled on hover intent, keyboard focus,\r\n    // mobile nav tap or overlay open, and shared across all three surfaces.\r\n  }\r\n\r\n  poll(\r\n    \"#navigation\",\r\n    () =\u003e {\r\n      try {\r\n        init();\r\n      } catch (e) {\r\n        console \u0026\u0026 console.warn \u0026\u0026 console.warn(\"CT For You overlay init error\", e);\r\n      }\r\n    },\r\n    50,\r\n    60\r\n  );\r\n})();","trigger":{"include_pages":[{"type":"any"}],"exclude_pages":[{"url":"/eu/","type":"contains"}]},"_id":"69b96ed614ffb0ae5bf050d8"},{"uses_overlay":false,"type":"js","parametrized_definition":"(() =\u003e {\n  \"use strict\";\n\n  const RUN_FLAG = \"__CT_PICTURE_DATA_IESRC_TO_IMG__\";\n  if (window[RUN_FLAG]) return;\n  window[RUN_FLAG] = true;\n\n  function processPicture(picture) {\n    if (!picture) return;\n\n    const img = picture.querySelector(\"img\");\n    if (!img) return;\n\n    const ieSrc = picture.getAttribute(\"data-iesrc\");\n    if (!ieSrc) return;\n\n    // Prevent reprocessing\n    if (img.getAttribute(\"data-ct-src-applied\") === \"true\") return;\n\n    img.src = ieSrc;\n    img.setAttribute(\"data-ct-src-applied\", \"true\");\n  }\n\n  function init(root = document) {\n    root.querySelectorAll(\"picture[data-iesrc]\").forEach(processPicture);\n  }\n\n  // Initial run\n  init();\n\n  // Handle dynamic DOM changes (PLP loads, CMS blocks, carousels, etc.)\n  const observer = new MutationObserver((mutations) =\u003e {\n    mutations.forEach((m) =\u003e {\n      m.addedNodes.forEach((node) =\u003e {\n        if (node.nodeType !== 1) return;\n\n        if (node.matches \u0026\u0026 node.matches(\"picture[data-iesrc]\")) {\n          processPicture(node);\n        } else if (node.querySelectorAll) {\n          node.querySelectorAll(\"picture[data-iesrc]\").forEach(processPicture);\n        }\n      });\n    });\n  });\n\n  observer.observe(document.body, {\n    childList: true,\n    subtree: true\n  });\n})();","trigger":{"include_pages":[{"url":"https://www.charlestyrwhitt.com/uk/editorial-style-tips/why-we-love-linen.html","type":"contains"}],"exclude_pages":null},"_id":"69d532ca5566ec5d82491225"},{"uses_overlay":false,"type":"js","parametrized_definition":"\n(() =\u003e {\n  \"use strict\";\n\n  //console.log(\"CT PROMO v022\");\n\n  const RUN_FLAG = \"__CT_PROMO_REMOTE__v022\";\n  if (window[RUN_FLAG]) return;\n  window[RUN_FLAG] = true;\n\n  console.log(RUN_FLAG);\n\n  const DEBUG = false;\n  const log = (...args) =\u003e {\n    if (DEBUG) console.log(...args);\n  };\n\n  try {\n    if (!window.utag_data || !window.utag_data.global) {\n      console.warn(\"[Promo] No utag_data.global, exiting\");\n      return;\n    }\n\n    const CONFIG = {\n      PROMOS_URL: \"https://raw.githubusercontent.com/CTShirts-26/promo-config-proxy/main/promos.json\",\n      BF_MODE: false,\n      ENABLE_PLP: true,\n      ENABLE_PDP: true,\n      ENABLE_TIB: true,\n      ENABLE_SCROLL_FADE: true,\n      ENFORCE_CLEARANCE_GUARD: true,\n      ALL_CAPS: true,\n\n      CATEGORY_KEYWORDS: {\n        SHIRTS: [\"shirts\", \"shirt\", \"hemd\", \"hemden\", \"chemise\", \"chemises\", \"overhemd\", \"overhemden\"],\n        TROUSERS: [\"trousers\", \"trouser\", \"chinos\", \"chino\", \"pants\", \"pant\", \"hose\", \"pantalon\", \"pantalons\", \"broeken\"],\n        BELTS: [\"belts\", \"belt\", \"gürtel\", \"guertel\", \"ceinture\", \"ceintures\", \"riem\", \"riemen\", \"cintura\", \"cinturas\", \"cinturón\", \"cinturon\", \"cinturones\"]\n      },\n\n      CLEARANCE_REGEX: /\\b(clearance|sale|outlet|last[\\s-]?chance)\\b/i,\n\n      SCHEDULING_PREVIEW: {\n        ENABLE: true,\n        ASSUME_UTC: true,\n        TITLE_REGEX:\n          /[()（）\\[\\]]\\s*(?:\\d{4}-\\d{2}-\\d{2}|\\d{1,2}[.\\-\\/]\\d{1,2}[.\\-\\/]\\d{4})\\s+\\d{1,2}[:hH]\\d{2}(?:\\s*(?:[ap]\\s*\\.?\\s*m\\.?))?(?:\\s*[A-Za-zÀ-ÿ]{2,5})?\\s*[\\])）]?/iu,\n        FORMAT_MAP: {\n          US: \"MDY\",\n          \"CA:fr\": \"MDY\",\n          CA: \"DMY\",\n          \"CH:en\": \"MDY\",\n          \"CH:de\": \"DMY\",\n          \"CH:fr\": \"DMY\",\n          \"NL:en\": \"DMY\",\n          \"NL:nl\": \"DMY\",\n          DEFAULT: \"DMY\"\n        },\n        REGION_TO_TIMEZONE: {\n          UK:  \"Europe/London\",       // single timezone\n          DE:  \"Europe/Berlin\",       // single timezone\n          FR:  \"Europe/Paris\",        // single timezone\n          EU:  \"Europe/Paris\",        // single timezone\n          CH:  \"Europe/Zurich\",       // single timezone\n          NL:  \"Europe/Amsterdam\",    // single timezone\n          XBR: \"Europe/London\",       // single timezone\n          US:  \"America/Los_Angeles\", // latest/westernmost US timezone (covers all states)\n          CA:  \"America/Vancouver\",   // Vancouver — used for preview display only\n          AU:  \"Australia/Sydney\",    // AU reference timezone — covers all states with DST\n        },\n\n        // CA date-only rules (e.g. \"2026-06-10\") fire at midnight UTC by default.\n        // CT promos must align with Salesforce/CT MB which start at 02:00 UTC\n        // (= 2am Vancouver PDT, UTC-7). We apply a fixed offset so that\n        // midnight UTC + 9h = 09:00 UTC = 2am Vancouver PDT.\n        // Hardcoded here — no changes needed in the Google Sheet or JSON rules.\n        // NOTE: Update to 10 in November when Vancouver switches to PST (UTC-8).\n        CA_DATE_ONLY_START_OFFSET_HOURS: 9\n      },\n\n      FORCE_REGION: null,\n      FORCE_MESSAGE: null,\n      FORCE_AFFIL_MODE: null,\n      LANG_OVERRIDE: null,\n\n      SELECTORS: {\n        HP_TILE_SELECTOR: \".js-product-tile\",\n        HP_ANCHOR_SELECTOR: \".js-tile-pricing\",\n        PLP_TILE: \".js-product-tile\",\n        PLP_ANCHOR: \".js-tile-pricing\",\n        PDP_ANCHOR: \".col-wrap.flex-justify-space-between.flex-align-center\",\n        TIB_ANCHOR: \"h1.top-info__title, .top-info__title\",\n        BANNER_ANCHOR: \".service-banner.col-100, .service-banner\",\n\n        PDP_MULTIBUY_TEXT: \"div.font__secondary.h5.uppercase.grey2.m-top-xs\",\n        GLOBAL_MULTIBUY_TRACKERS: [\n          \".js-multibuy-tracker-placeholder-mobile\",\n          \".js-multibuy-tracker-placeholder\",\n          \".both-tracker-container\",\n          \".mb-tracker-container.js-accessibility-return.cursor-pointer:not(.tracker-unlocked)\"\n        ],\n\n        TILE_MULTIBUY: \".product-tile__promo, .mb-tracker-container:not(.tracker-unlocked), .both-tracker-container\",\n        PDP_DETAILS_WRAPPER: \".pdp-main__inner-details\",\n\n        PDP_ANCHOR_FALLBACKS: [\n          \".pdp-main__price-row\",\n          \".pdp-main__title\",\n          \".pdp-main__benefits-description\",\n          \".product-detail .product-price\",\n          \".product-detail .product-name\",\n          \"[data-qa='product-price']\",\n          \"[data-qa='pdp-price']\",\n          \".prices\",\n          \".price\"\n        ]\n      },\n\n      STYLES: {\n        BG: \"#bc2e35\",\n        COLOR: \"#fff\",\n        FONT_SIZE: \"1.2rem\",\n        FONT_WEIGHT: 500,\n        PADDING: \"5px 7px\",\n        MARGIN_TOP: \"10px\",\n        BORDER_RADIUS: \"0.5rem\",\n        LETTER_SPACING: \"0.02em\",\n        BF: { BG: \"black\", COLOR: \"#fad000\" },\n        TIB: {\n          COLOR: \"#bc2e35\",\n          FONT_SIZE: \"18px\",\n          FONT_WEIGHT: 600,\n          MARGIN_TOP: \"10px\",\n          LETTER_SPACING: \"0.02em\"\n        },\n        BANNER: {\n          BG: \"#001F49\",\n          COLOR: \"#fff\",\n          FONT_SIZE: \"14px\"\n        }\n      },\n\n      FADE: {\n        THRESHOLD: [0, 0.01],\n        ROOT_MARGIN: \"8px 0px -10% 0px\",\n        DURATION_MS: 200,\n        EASING: \"ease\",\n        TRANSLATE_Y_PX: 6\n      }\n    };\n\n    const siteLang = String(CONFIG.LANG_OVERRIDE || window.utag_data?.global?.site_language || \"\").trim().toLowerCase();\n    const sfccCountry = String(window.utag_data?.global?.sfcc_country || \"\").toUpperCase();\n\n    function getPageType() {\n      return String(window.utag_data?.page?.type || \"\").toLowerCase();\n    }\n\n    function getPlpCategory() {\n      return String(window.utag_data?.page?.category || \"\").toLowerCase();\n    }\n\n    function isProductPage() {\n      const pageType = getPageType();\n      return pageType.includes(\"product\") || pageType.includes(\"pdp\");\n    }\n\n    function isCategoryPage() {\n      const pageType = getPageType();\n      return pageType.includes(\"category\") || pageType.includes(\"plp\");\n    }\n\n    function isCheckoutPage() {\n      const path = String(location.pathname || \"\").toLowerCase();\n      const pageType = getPageType();\n      return pageType.includes(\"checkout\") || /\\/checkout\\b/.test(path);\n    }\n\n    function isCartPage() {\n      const path = String(location.pathname || \"\").toLowerCase();\n      const pageType = getPageType();\n      return /\\/cart\\b/.test(path) || /\\/basket\\b/.test(path) || pageType.includes(\"basket\") || pageType.includes(\"cart\");\n    }\n\n    function isHomePage() {\n      const t = getPageType();\n      if ([\"home\", \"homepage\", \"start\"].includes(t)) return true;\n      const p = String(location.pathname || \"\").replace(/\\/+$/, \"\");\n      return p === \"\" || /^\\/[a-z]{2}(?:_[A-Z]{2})?$/.test(p);\n    }\n\n    function mapSfccCountryToRegion(c) {\n      const m = {\n        US: \"US\", CA: \"CA\", AU: \"AU\", GB: \"UK\", UK: \"UK\",\n        DE: \"DE\", FR: \"FR\", CH: \"CH\", NL: \"NL\", EU: \"EU\", XBR: \"XBR\",\n        // EU language markets — sfcc_country is the language country code\n        // but they all resolve to the EU region and use content.eu\n        IT: \"EU\", // Italian EU site\n        ES: \"EU\", // Spanish EU site (coming soon)\n      };\n      return m[String(c || \"\").toUpperCase()] || \"\";\n    }\n\n    const REGION = CONFIG.FORCE_REGION || mapSfccCountryToRegion(sfccCountry);\n    const rawCampaignSite = String(window.utag_data?.global?.campaign_site || \"\").trim().toLowerCase();\n\n    function normalizeCampaignSiteValue(raw) {\n      return String(raw || \"\").trim().toLowerCase();\n    }\n\n    const currentCampaignSite = normalizeCampaignSiteValue(rawCampaignSite);\n\n    if (!REGION) {\n      console.warn(\"[Promo] No region resolved, exiting\");\n      return;\n    }\n\n    // ── STARTUP LOG ───────────────────────────────────────────────────────\n    (function logRegionAndTime() {\n      const tz = CONFIG.SCHEDULING_PREVIEW?.REGION_TO_TIMEZONE?.[REGION] || \"UTC\";\n      const realMs = Date.now();\n      const previewMs = readPreviewNowMsFromTitle();\n\n      const fmt = function(ms) {\n        return new Intl.DateTimeFormat(\"en-GB\", {\n          timeZone: tz,\n          year: \"numeric\", month: \"2-digit\", day: \"2-digit\",\n          hour: \"2-digit\", minute: \"2-digit\", second: \"2-digit\",\n          hour12: false\n        }).format(new Date(ms));\n      };\n\n      // Always show real current time\n      console.log(\n        \"%c[Promo] Market: \" + REGION +\n        \" | Real time (\" + tz + \"): \" + fmt(realMs) +\n        \" | UTC: \" + new Date(realMs).toISOString(),\n        \"color: #bc2e35; font-weight: bold;\"\n      );\n\n      // If a preview date is detected in the page title, show it as a warning\n      if (previewMs != null) {\n        console.log(\n          \"%c[Promo] ⚠️ PREVIEW MODE | Simulating: \" + fmt(previewMs) +\n          \" (\" + tz + \") | UTC: \" + new Date(previewMs).toISOString(),\n          \"color: orange; font-weight: bold;\"\n        );\n      }\n    })();\n    // ─────────────────────────────────────────────────────────────────────\n\n    function getRuleSiteList(rule, key, fallbacks = []) {\n      const targeting = rule?.targeting || {};\n      let values = targeting[key];\n\n      if (!Array.isArray(values)) {\n        for (const fallback of fallbacks) {\n          if (Array.isArray(targeting[fallback])) {\n            values = targeting[fallback];\n            break;\n          }\n        }\n      }\n\n      return Array.isArray(values)\n        ? values.map(normalizeCampaignSiteValue).filter(Boolean)\n        : [];\n    }\n\n    function getDefaultSites(rule) {\n      return getRuleSiteList(rule, \"defaultCampaignSites\");\n    }\n\n    function getAffiliateSites(rule) {\n      return getRuleSiteList(rule, \"affiliateCampaignSites\", [\"campaignSites\", \"campaignSite\"]);\n    }\n\n    function getAcquisitionSites(rule) {\n      return getRuleSiteList(rule, \"acquisitionCampaignSites\");\n    }\n\n    function getMatchedSiteModeForRule(rule) {\n      const live = currentCampaignSite;\n      const defaults = getDefaultSites(rule);\n      const affiliates = getAffiliateSites(rule);\n      const acquisition = getAcquisitionSites(rule);\n\n      if (!live) return \"default\";\n      if (affiliates.includes(live)) return \"affiliate\";\n      if (acquisition.includes(live)) return \"acquisition\";\n      if (defaults.includes(live)) return \"default\";\n      return \"none\";\n    }\n\n    const isClearanceToken = s =\u003e (s || \"\").includes(\"clr_\") || CONFIG.CLEARANCE_REGEX.test(s || \"\");\n\n    function isClearanceContext() {\n      return (\n        CONFIG.ENFORCE_CLEARANCE_GUARD \u0026\u0026\n        (\n          isClearanceToken(getPlpCategory()) ||\n          /\\/(clearance|sale|outlet)\\//.test(String(location.pathname || \"\").toLowerCase())\n        )\n      );\n    }\n\n    function hasTz(iso) {\n      return /Z|[+\\-]\\d{2}:\\d{2}$/.test(String(iso || \"\"));\n    }\n\n    function parseUtcOrNull(iso) {\n      if (!iso) return null;\n      const str = String(iso).trim();\n\n      // Handle date-only strings like \"2026-04-30\" explicitly using Date.UTC\n      // to avoid mobile browser inconsistencies with Date.parse(\"2026-04-30Z\")\n      // which can return NaN on some iOS/Android browsers causing the date\n      // check to be skipped entirely and promos firing ahead of schedule.\n      const dateOnly = str.match(/^(\\d{4})-(\\d{2})-(\\d{2})$/);\n      if (dateOnly) {\n        const t = Date.UTC(+dateOnly[1], +dateOnly[2] - 1, +dateOnly[3], 0, 0, 0, 0);\n        return Number.isFinite(t) ? t : null;\n      }\n\n      const s = hasTz(str) ? str : str + \"Z\";\n      const t = Date.parse(s);\n      return Number.isFinite(t) ? t : null;\n    }\n\n    function resolveDesiredFormatForPreview() {\n      const langKey = `${REGION}:${siteLang.split(\"_\")[0].toLowerCase()}`;\n      return (\n        CONFIG.SCHEDULING_PREVIEW?.FORMAT_MAP?.[langKey] ||\n        CONFIG.SCHEDULING_PREVIEW?.FORMAT_MAP?.[REGION] ||\n        CONFIG.SCHEDULING_PREVIEW?.FORMAT_MAP?.DEFAULT ||\n        \"DMY\"\n      );\n    }\n\n    function readPreviewNowMsFromTitle() {\n      try {\n        const cfg = CONFIG.SCHEDULING_PREVIEW;\n        if (!cfg?.ENABLE) return null;\n\n        const rawTitle = String(document?.title || \"\");\n        const title = rawTitle.replace(/[\\u00A0\\u202F\\u2007\\u2009\\u200A\\u2002-\\u2006]/g, \" \").trim();\n        if (!title) return null;\n        if (cfg.TITLE_REGEX \u0026\u0026 !cfg.TITLE_REGEX.test(title)) return null;\n\n        const TZ_TO_OFFSET_MIN = {\n          UTC: 0, GMT: 0,\n          BST: 60, CET: 60, CEST: 120,\n          EST: -300, EDT: -240,\n          CST: -360, CDT: -300,\n          MST: -420, MDT: -360,\n          PST: -480, PDT: -420,\n          HNE: -300, HAE: -240, HNC: -360, HAC: -300,\n          HNR: -420, HAR: -360, HNP: -480, HAP: -420\n        };\n\n        const reYMD =\n          /[()（）\\[\\]]\\s*(\\d{4})-(\\d{2})-(\\d{2})\\s+(\\d{1,2})[:hH](\\d{2})(?:\\s*(?:([ap])\\s*\\.?\\s*m\\.?))?(?:\\s*([A-Za-zÀ-ÿ]{2,5}))?\\s*[\\])）]?/iu;\n        const reDMYorMDY =\n          /[()（）\\[\\]]\\s*(\\d{1,2})[.\\-\\/](\\d{1,2})[.\\-\\/](\\d{4})\\s+(\\d{1,2})[:hH](\\d{2})(?:\\s*(?:([ap])\\s*\\.?\\s*m\\.?))?(?:\\s*([A-Za-zÀ-ÿ]{2,5}))?\\s*[\\])）]?/iu;\n\n        function parsePartsFromTitle() {\n          const mYMD = title.match(reYMD);\n          if (mYMD) {\n            let hour = +mYMD[4];\n            const ampmRaw = (mYMD[6] || \"\").toLowerCase();\n            if (ampmRaw) {\n              const isPM = ampmRaw.startsWith(\"p\");\n              if (hour === 12) hour = isPM ? 12 : 0;\n              else if (isPM) hour += 12;\n            }\n\n            return {\n              year: +mYMD[1],\n              month: +mYMD[2],\n              day: +mYMD[3],\n              hour,\n              minute: +mYMD[5],\n              tzAbbr: (mYMD[7] || \"\").toUpperCase()\n            };\n          }\n\n          const m = title.match(reDMYorMDY);\n          if (!m) return null;\n\n          const n1 = +m[1];\n          const n2 = +m[2];\n          const year = +m[3];\n          let hour = +m[4];\n          const minute = +m[5];\n          const ampmRaw = (m[6] || \"\").toLowerCase();\n          const tzAbbr = (m[7] || \"\").toUpperCase();\n\n          let inferredDMY = null;\n          if (n1 \u003e 12 \u0026\u0026 n2 \u003c= 12) inferredDMY = true;\n          else if (n2 \u003e 12 \u0026\u0026 n1 \u003c= 12) inferredDMY = false;\n\n          const configured = resolveDesiredFormatForPreview();\n          const useDMY = inferredDMY === null ? configured !== \"MDY\" : inferredDMY;\n\n          const day = useDMY ? n1 : n2;\n          const month = useDMY ? n2 : n1;\n\n          if (ampmRaw) {\n            const isPM = ampmRaw.startsWith(\"p\");\n            if (hour === 12) hour = isPM ? 12 : 0;\n            else if (isPM) hour += 12;\n          }\n\n          return { year, month, day, hour, minute, tzAbbr };\n        }\n\n        function getTimeZoneOffsetMinutes(timeZone, date) {\n          const dtf = new Intl.DateTimeFormat(\"en-US\", {\n            timeZone,\n            year: \"numeric\",\n            month: \"2-digit\",\n            day: \"2-digit\",\n            hour: \"2-digit\",\n            minute: \"2-digit\",\n            second: \"2-digit\",\n            hourCycle: \"h23\"\n          });\n\n          const parts = dtf.formatToParts(date);\n          const map = {};\n          for (const p of parts) {\n            if (p.type !== \"literal\") map[p.type] = p.value;\n          }\n\n          const asUTC = Date.UTC(\n            +map.year,\n            +map.month - 1,\n            +map.day,\n            +map.hour,\n            +map.minute,\n            +map.second\n          );\n\n          return (asUTC - date.getTime()) / 60000;\n        }\n\n        function zonedLocalToUtcMs(year, month, day, hour, minute, timeZone) {\n          const approxUtc = Date.UTC(year, month - 1, day, hour, minute, 0, 0);\n          const offsetMin = getTimeZoneOffsetMinutes(timeZone, new Date(approxUtc));\n          return approxUtc - offsetMin * 60 * 1000;\n        }\n\n        const parsed = parsePartsFromTitle();\n        if (!parsed) return null;\n\n        const { year, month, day, hour, minute, tzAbbr } = parsed;\n        if ([year, month, day, hour, minute].some(Number.isNaN)) return null;\n\n        if (tzAbbr \u0026\u0026 Object.prototype.hasOwnProperty.call(TZ_TO_OFFSET_MIN, tzAbbr)) {\n          const baseUTC = Date.UTC(year, month - 1, day, hour, minute, 0, 0);\n          return baseUTC - TZ_TO_OFFSET_MIN[tzAbbr] * 60 * 1000;\n        }\n\n        const regionTz = getRegionTimeZone(REGION);\n        return zonedLocalToUtcMs(year, month, day, hour, minute, regionTz);\n      } catch {\n        return null;\n      }\n    }\n\n    function getNowMs() {\n      const previewMs = readPreviewNowMsFromTitle();\n      if (previewMs != null) return previewMs;\n      return Date.now();\n    }\n\n    function getRegionTimeZone(region) {\n      return CONFIG.SCHEDULING_PREVIEW?.REGION_TO_TIMEZONE?.[region] || \"UTC\";\n    }\n\n    function getLocalDateParts(ms, timeZone) {\n      const parts = new Intl.DateTimeFormat(\"en-CA\", {\n        timeZone,\n        year: \"numeric\",\n        month: \"2-digit\",\n        day: \"2-digit\"\n      }).formatToParts(new Date(ms));\n      const map = {};\n      for (const p of parts) {\n        if (p.type !== \"literal\") map[p.type] = p.value;\n      }\n      return { year: +map.year, month: +map.month, day: +map.day };\n    }\n\n    function getLocalDateKey(ms, timeZone) {\n      const p = getLocalDateParts(ms, timeZone);\n      return `${String(p.year)}-${String(p.month).padStart(2, \"0\")}-${String(p.day).padStart(2, \"0\")}`;\n    }\n\n    function getIsoDateKeyFromInput(value) {\n      const match = String(value || \"\").match(/^(\\d{4})-(\\d{2})-(\\d{2})/);\n      return match ? `${match[1]}-${match[2]}-${match[3]}` : null;\n    }\n\n    function resolveBoundaryDateKey(value, timeZone) {\n      // Always convert through parseUtcOrNull so that date-only strings like\n      // \"2026-04-26\" (no T, no Z) are treated as midnight UTC, then converted\n      // to the region's local date — preventing early firing on non-UK markets.\n      // e.g. \"2026-04-26\" + America/New_York = still \"2026-04-25\" at 8pm ET,\n      // so the promo correctly waits until midnight ET before showing.\n      const ms = parseUtcOrNull(value);\n      return ms != null ? getLocalDateKey(ms, timeZone) : null;\n    }\n\n    function hasTimeComponent(value) {\n      return /T\\d{2}:\\d{2}|[ ]\\d{2}:\\d{2}/.test(String(value || \"\"));\n    }\n\n    function isNowInWindow(startUtc, endUtc) {\n      const nowMs = getNowMs();\n      const tz = getRegionTimeZone(REGION);\n\n      // CA date-only rules: apply a fixed UTC offset so the promo fires at\n      // 2am Vancouver PDT (UTC-7) = 09:00 UTC, matching Salesforce and CT MB.\n      // Timed entries (e.g. \"2026-06-10T09:00:00Z\") are unaffected — they\n      // are compared directly. US and all other regions: offsetMs = 0.\n      const caOffsetMs = (REGION === \"CA\")\n        ? ((CONFIG.SCHEDULING_PREVIEW?.CA_DATE_ONLY_START_OFFSET_HOURS || 0) * 3600 * 1000)\n        : 0;\n\n      let startOk = true;\n      if (startUtc) {\n        if (hasTimeComponent(startUtc)) {\n          // Timed entry — compare directly, no offset applied\n          const startMs = parseUtcOrNull(startUtc);\n          startOk = startMs == null || nowMs \u003e= startMs;\n        } else {\n          if (caOffsetMs \u003e 0) {\n            // CA date-only: fire at midnight UTC + offset (= 2am Vancouver PDT)\n            const startMs = parseUtcOrNull(startUtc);\n            startOk = startMs == null || nowMs \u003e= (startMs + caOffsetMs);\n          } else {\n            // All other regions: plain local date string comparison\n            const nowKey = getLocalDateKey(nowMs, tz);\n            const startKey = getIsoDateKeyFromInput(startUtc);\n            startOk = !startKey || nowKey \u003e= startKey;\n          }\n        }\n      }\n\n      let endOk = true;\n      if (endUtc) {\n        if (hasTimeComponent(endUtc)) {\n          // Timed entry — compare directly, no offset applied\n          const endMs = parseUtcOrNull(endUtc);\n          endOk = endMs == null || nowMs \u003c= endMs;\n        } else {\n          if (caOffsetMs \u003e 0) {\n            // CA date-only: end at midnight UTC + offset + 24h (= 2am Vancouver PDT next day)\n            const endMs = parseUtcOrNull(endUtc);\n            endOk = endMs == null || nowMs \u003c (endMs + caOffsetMs + 86400000);\n          } else {\n            // All other regions: plain local date string comparison\n            const nowKey = getLocalDateKey(nowMs, tz);\n            const endKey = getIsoDateKeyFromInput(endUtc);\n            endOk = !endKey || nowKey \u003c= endKey;\n          }\n        }\n      }\n\n      return startOk \u0026\u0026 endOk;\n    }\n\n    function isEndsTonightWindow(endUtc) {\n      if (!endUtc) return false;\n      if (hasTimeComponent(endUtc)) return false; // timed rules don't use ends-tonight\n\n      const nowMs = getNowMs();\n      const tz = getRegionTimeZone(REGION);\n      const caOffsetMs = (REGION === \"CA\")\n        ? ((CONFIG.SCHEDULING_PREVIEW?.CA_DATE_ONLY_START_OFFSET_HOURS || 0) * 3600 * 1000)\n        : 0;\n\n      if (caOffsetMs \u003e 0) {\n        // CA: \"ends tonight\" is true during the CA promo day window\n        // (from endDate midnight UTC + offset, for 24 hours)\n        const endMs = parseUtcOrNull(endUtc);\n        if (endMs == null) return false;\n        const windowStart = endMs + caOffsetMs;\n        const windowEnd   = windowStart + 86400000;\n        return nowMs \u003e= windowStart \u0026\u0026 nowMs \u003c windowEnd;\n      }\n\n      // All other regions: plain local date string comparison\n      const nowKey = getLocalDateKey(nowMs, tz);\n      const endKey = getIsoDateKeyFromInput(endUtc);\n      if (!endKey) return false;\n      return nowKey === endKey;\n    }\n\n    function getBreadcrumbText() {\n      const n = document.querySelector(\".breadcrumb__container,.breadcrumbs,[data-qa='breadcrumbs']\");\n      return n?.textContent?.toLowerCase() || \"\";\n    }\n\n    function buildHaystack() {\n      return [\n        getPlpCategory(),\n        String(window.utag_data?.product?.category || \"\"),\n        String(window.utag_data?.product?.primaryCategory || \"\"),\n        Array.isArray(window.utag_data?.product?.categoryPath) ? window.utag_data.product.categoryPath.join(\" \u003e \") : \"\",\n        String(location.pathname || \"\"),\n        String(document.title || \"\"),\n        getBreadcrumbText()\n      ].join(\" \").toLowerCase();\n    }\n\n    function hasAllValue(arr) {\n      if (!Array.isArray(arr)) return false;\n      return arr.some(v =\u003e {\n        const s = String(v || \"\").trim();\n        return s === \"__ALL__\" || s === \"ALL\" || s.toLowerCase() === \"all\";\n      });\n    }\n\n    function matchesCategory(mainCategories) {\n      if (!Array.isArray(mainCategories) || !mainCategories.length) return true;\n      if (hasAllValue(mainCategories)) return true;\n      const hay = buildHaystack();\n      for (const cat of mainCategories) {\n        const catKey = String(cat || \"\").trim().toUpperCase();\n        const keywords = CONFIG.CATEGORY_KEYWORDS?.[catKey];\n        if (keywords) {\n          for (const kw of keywords) {\n            if (hay.includes(String(kw).toLowerCase())) return true;\n          }\n        } else {\n          if (hay.includes(String(cat || \"\").toLowerCase())) return true;\n        }\n      }\n      return false;\n    }\n\n    function normalizePid(id) {\n      return String(id || \"\").trim().toUpperCase();\n    }\n\n    function getPdpProductId() {\n      const fromArr = window.utag_data?.products?.[0]?.id;\n      if (fromArr) return String(fromArr);\n      const p = window.utag_data?.product?.id || window.utag_data?.product?.product_id || window.utag_data?.product?.sku || window.utag_data?.product?.code;\n      if (p) return String(p);\n      const el = document.querySelector(\"[data-product-id],[data-prod-id],[data-pid]\");\n      return el\n        ? (el.getAttribute(\"data-product-id\") || el.getAttribute(\"data-prod-id\") || el.getAttribute(\"data-pid\"))\n        : \"\";\n    }\n\n    function getTilePid(tile) {\n      return normalizePid(\n        tile?.getAttribute?.(\"data-prod-id\") ||\n        tile?.dataset?.productId ||\n        tile?.querySelector?.(\"[data-prod-id]\")?.getAttribute?.(\"data-prod-id\") ||\n        \"\"\n      );\n    }\n\n    function resolveContentForRegion(rule) {\n      const regionKey = REGION.toLowerCase();\n      const content = rule.content;\n      if (!content) return null;\n      const regionContent = content[regionKey];\n      if (!regionContent) return null;\n\n      if ([\"ca\", \"ch\", \"nl\"].includes(regionKey)) {\n        const lang = siteLang.split(\"_\")[0].toLowerCase();\n\n        if (regionKey === \"ca\") {\n          return lang.startsWith(\"fr\") ? regionContent.fr : regionContent.en;\n        }\n\n        if (regionKey === \"ch\") {\n          if (lang.startsWith(\"fr\")) return regionContent.fr;\n          if (lang.startsWith(\"de\")) return regionContent.de;\n          return regionContent.en;\n        }\n\n        if (regionKey === \"nl\") {\n          // If NL language content exists and has values use it,\n          // otherwise fall back to EN and let Localise translate on the fly.\n          const nlContent = regionContent.nl;\n          const hasNlContent = nlContent \u0026\u0026 Object.values(nlContent).some(block =\u003e {\n            if (typeof block === \"object\" \u0026\u0026 block !== null) {\n              return Object.values(block).some(v =\u003e String(v || \"\").trim() !== \"\");\n            }\n            return String(nlContent || \"\").trim() !== \"\";\n          });\n          return hasNlContent ? nlContent : regionContent.en;\n        }\n      }\n\n      // For single-language markets (US, UK, AU, DE, FR, EU, XBR etc.)\n      // check if the content has any values — if not, try to find an\n      // English sub-key as fallback (future-proofs EU Italian and similar).\n      if (typeof regionContent === \"object\" \u0026\u0026 regionContent !== null) {\n        // Check if it's a multi-lang object (has language sub-keys like en/it/fr)\n        const hasLangKeys = [\"en\",\"fr\",\"de\",\"nl\",\"it\",\"es\"].some(l =\u003e regionContent[l] !== undefined);\n        if (hasLangKeys) {\n          const lang = siteLang.split(\"_\")[0].toLowerCase();\n          // Try requested language first, fall back to English\n          const langContent = regionContent[lang] || regionContent.en;\n          return langContent || null;\n        }\n      }\n\n      return regionContent;\n    }\n\n    function resolveCode(isAffiliate) {\n      const codeEntry = isAffiliate\n        ? CONFIG.AFFILIATE_CODE_BY_REGION?.[REGION]\n        : CONFIG.DEFAULT_CODE_BY_REGION?.[REGION];\n      if (!codeEntry) return \"\";\n      if (typeof codeEntry === \"string\") return codeEntry;\n      const lang = siteLang.split(\"_\")[0].toLowerCase();\n      if (REGION === \"CH\") {\n        if (lang.startsWith(\"fr\")) return codeEntry.fr || codeEntry.en || \"\";\n        if (lang.startsWith(\"de\")) return codeEntry.de || codeEntry.en || \"\";\n        return codeEntry.en || \"\";\n      }\n      if (REGION === \"NL\") return lang.startsWith(\"nl\") ? codeEntry.nl : codeEntry.en || \"\";\n      if (REGION === \"CA\") return lang.startsWith(\"fr\") ? codeEntry.fr : codeEntry.en || \"\";\n      return codeEntry.en || codeEntry.fr || codeEntry.de || \"\";\n    }\n\n    function injectCode(message, isAffiliate) {\n      const code = resolveCode(isAffiliate);\n      if (!message) return \"\";\n      return String(message)\n        .replace(/\\{code\\}/gi, code || \"\")\n        .replace(/\\bXX\\b/g, code || \"\")\n        .replace(/\\s+\\|\\s+$/g, \"\")\n        .trim();\n    }\n\n    const REMOTE = { rules: [], loaded: false, inFlight: null };\n\n    // ─────────────────────────────────────────────────────────────────────────\n\n    async function loadRemoteRules() {\n      if (REMOTE.loaded) return;\n      if (REMOTE.inFlight) {\n        await REMOTE.inFlight;\n        return;\n      }\n\n      REMOTE.inFlight = (async () =\u003e {\n        try {\n          const res = await fetch(CONFIG.PROMOS_URL, { cache: \"no-store\" });\n          if (!res.ok) throw new Error(`HTTP ${res.status}`);\n          const data = await res.json();\n          REMOTE.rules = Array.isArray(data?.rules) ? data.rules : [];\n          REMOTE.loaded = true;\n          console.log(\"[Promo] Rules loaded from GitHub — \" + REMOTE.rules.length + \" rule(s) found\");\n        } catch (e) {\n          console.warn(\"[Promo] Failed to load promos.json\", e);\n          REMOTE.rules = [];\n        }\n      })().finally(() =\u003e {\n        REMOTE.inFlight = null;\n      });\n\n      await REMOTE.inFlight;\n    }\n\n    // Tracks which rule+surface combos have already been logged this page session\n    // so the console doesn't flood with one log per product tile.\n    const _loggedRules = new Set();\n\n  \n    \n    \n    function findMatchingRule(pid, surface = \"generic\") {\n      const pidN = normalizePid(pid);\n      const hay = buildHaystack();\n\n      for (const rule of REMOTE.rules) {\n        const regionKey = REGION.toLowerCase();\n\n        if (!rule?.enabled) continue;\n        if (!rule.countryEnabled?.[regionKey]) continue;\n        if (!isNowInWindow(rule.startUtc, rule.endUtc)) continue;\n\n        // Skip rules that don't apply to the current campaign site at all.\n        // Without this, a rule with broader category/date targeting but the\n        // wrong campaign site can still \"win\" a surface slot (e.g. TIB) purely\n        // by array order, then self-eliminate on payload resolution with no\n        // fallback — leaving that surface empty even though a valid rule exists.\n        if (getMatchedSiteModeForRule(rule) === \"none\") continue;\n\n        // if (surface !== \"tib\" \u0026\u0026 surface !== \"bannerstrip\" \u0026\u0026 rule.hidePromoBox?.[regionKey]) continue;\n\n        if (surface === \"bannerstrip\") {\n          if (rule.scope?.bannerstrip === false) continue;\n          // Banner strip always shows on all PLP/PDP — mainCategories is NOT\n          // applied here. Category filtering only applies to TIB and callouts.\n          const matchKey = rule.ruleId + \"|\" + surface;\n          if (!_loggedRules.has(matchKey)) {\n            _loggedRules.add(matchKey);\n            console.log(\"%c[Promo] Running \\\"\" + rule.ruleId + \"\\\" on \" + REGION + \" (\" + surface + \")\", \"color: green; font-weight: bold;\");\n          }\n          return rule;\n        }\n\n        if (surface === \"tib\") {\n          if (rule.scope?.tibText === false) continue;\n          if (!matchesCategory(rule.targeting?.mainCategories)) continue;\n\n          if (rule.targeting?.excludedCategories?.length) {\n            const excluded = rule.targeting.excludedCategories.some(c =\u003e hay.includes(String(c).toLowerCase()));\n            if (excluded) continue;\n          }\n\n          return rule;\n        }\n\n        if (surface === \"plp\" || surface === \"hp\" || surface === \"pdp\" || surface === \"pdp-tile\") {\n          const plpScopeAllowed = rule.scope?.promoCallout !== false \u0026\u0026 rule.scope?.plpCallout !== false;\n          const pdpScopeAllowed = rule.scope?.promoCallout !== false \u0026\u0026 rule.scope?.pdpCallout !== false;\n\n          if ((surface === \"plp\" || surface === \"hp\" || surface === \"pdp-tile\") \u0026\u0026 !plpScopeAllowed) continue;\n          if (surface === \"pdp\" \u0026\u0026 !pdpScopeAllowed) continue;\n\n          if ((surface === \"plp\" || surface === \"hp\" || surface === \"pdp-tile\") \u0026\u0026 rule.targeting?.showOnPlp === false) continue;\n          if (surface === \"pdp\" \u0026\u0026 rule.targeting?.showOnPdp === false) continue;\n\n          const excludedProductIds = Array.isArray(rule.targeting?.excludedProductIds)\n            ? rule.targeting.excludedProductIds.map(normalizePid)\n            : [];\n\n          if (pidN \u0026\u0026 excludedProductIds.includes(pidN)) continue;\n\n          const productIds = Array.isArray(rule.targeting?.productIds) ? rule.targeting.productIds : [];\n          const hasAllProducts = hasAllValue(productIds);\n\n          if (!pidN) {\n            if (!hasAllProducts) continue;\n          } else if (!hasAllProducts \u0026\u0026 productIds.length) {\n            if (!productIds.map(normalizePid).includes(pidN)) continue;\n          }\n\n          const matchKey2 = rule.ruleId + \"|\" + surface;\n          if (!_loggedRules.has(matchKey2)) {\n            _loggedRules.add(matchKey2);\n            console.log(\"%c[Promo] Running \\\"\" + rule.ruleId + \"\\\" on \" + REGION + \" (\" + surface + \")\", \"color: green; font-weight: bold;\");\n          }\n          return rule;\n        }\n\n        const matchKey3 = rule.ruleId + \"|\" + surface;\n        if (!_loggedRules.has(matchKey3)) {\n          _loggedRules.add(matchKey3);\n          console.log(\"%c[Promo] Running \\\"\" + rule.ruleId + \"\\\" on \" + REGION + \" (\" + surface + \")\", \"color: green; font-weight: bold;\");\n        }\n        return rule;\n      }\n\n      const noMatchKey = \"nomatch|\" + surface;\n      if (!_loggedRules.has(noMatchKey)) {\n        _loggedRules.add(noMatchKey);\n        console.log(\"[Promo] No active rule for \" + REGION + \" (\" + surface + \")\");\n      }\n      return null;\n    }\n\n    function findCartRule() {\n      for (const rule of REMOTE.rules) {\n        const regionKey = REGION.toLowerCase();\n\n        if (!rule?.enabled) continue;\n        if (!rule.countryEnabled?.[regionKey]) continue;\n        if (!isNowInWindow(rule.startUtc, rule.endUtc)) continue;\n\n        const matchedSiteMode = getMatchedSiteModeForRule(rule);\n        if (matchedSiteMode === \"none\") continue;\n\n        if (rule.hidePromoBox?.[regionKey] === true) {\n          return rule;\n        }\n      }\n\n      return null;\n    }\n\n    function resolvePayloadFromRule(rule, pid, surface = \"generic\") {\n      if (!rule) return null;\n\n      const matchedSiteMode = getMatchedSiteModeForRule(rule);\n      if (matchedSiteMode === \"none\") return null;\n\n      const isAffiliate = matchedSiteMode === \"affiliate\";\n      const useEndsTonight = isEndsTonightWindow(rule.endUtc);\n\n      const content = resolveContentForRegion(rule);\n      if (!content) return null;\n\n      const tibText = content.tibText || {};\n      const plpCallout = content.plpCallout || content.promoCallout || {};\n      const pdpCallout = content.pdpCallout || content.promoCallout || {};\n      const bannerstrip = content.bannerstrip || {};\n\n      const tibNormalMessage = isAffiliate\n        ? (tibText.affiliate || tibText.default || \"\")\n        : (tibText.default || \"\");\n\n      const tibEndsTonightMessage = isAffiliate\n        ? (tibText.affiliateEndsTonight || tibText.affiliate || tibText.default || \"\")\n        : (tibText.endsTonight || tibText.default || \"\");\n\n      let tibMessage = useEndsTonight ? tibEndsTonightMessage : tibNormalMessage;\n\n      let plpMessage = isAffiliate\n        ? (plpCallout.affiliate || plpCallout.default || \"\")\n        : (plpCallout.default || \"\");\n\n      let pdpMessage = isAffiliate\n        ? (pdpCallout.affiliate || pdpCallout.default || \"\")\n        : (pdpCallout.default || \"\");\n\n      tibMessage = injectCode(tibMessage, isAffiliate);\n      plpMessage = injectCode(plpMessage, isAffiliate);\n      pdpMessage = injectCode(pdpMessage, isAffiliate);\n\n      const bannerLine1NormalRaw = isAffiliate\n        ? (bannerstrip.line1Affiliate || bannerstrip.line1 || \"\")\n        : (bannerstrip.line1 || \"\");\n\n      const bannerLine2NormalRaw = isAffiliate\n        ? (bannerstrip.line2Affiliate || bannerstrip.line2 || \"\")\n        : (bannerstrip.line2 || \"\");\n\n      const bannerLine3NormalRaw = isAffiliate\n        ? (bannerstrip.line3Affiliate || bannerstrip.line3 || \"\")\n        : (bannerstrip.line3 || \"\");\n\n      const bannerLine1EndsTonightRaw = isAffiliate\n        ? (bannerstrip.line1AffiliateEndsTonight || bannerLine1NormalRaw || \"\")\n        : (bannerstrip.line1EndsTonight || bannerLine1NormalRaw || \"\");\n\n      const bannerLine2EndsTonightRaw = isAffiliate\n        ? (bannerstrip.line2AffiliateEndsTonight || bannerLine2NormalRaw || \"\")\n        : (bannerstrip.line2EndsTonight || bannerLine2NormalRaw || \"\");\n\n      const bannerLine3EndsTonightRaw = isAffiliate\n        ? (bannerstrip.line3AffiliateEndsTonight || bannerLine3NormalRaw || \"\")\n        : (bannerstrip.line3EndsTonight || bannerLine3NormalRaw || \"\");\n\n      const bannerData = {\n        line1: injectCode(useEndsTonight ? bannerLine1EndsTonightRaw : bannerLine1NormalRaw, isAffiliate),\n        line2: injectCode(useEndsTonight ? bannerLine2EndsTonightRaw : bannerLine2NormalRaw, isAffiliate),\n        line3: injectCode(useEndsTonight ? bannerLine3EndsTonightRaw : bannerLine3NormalRaw, isAffiliate)\n      };\n\n      return {\n        tibMessage,\n        plpMessage,\n        pdpMessage: pdpMessage || plpMessage || tibMessage,\n        message: tibMessage,\n        codeToCopy: resolveCode(isAffiliate),\n        bannerData,\n        rule,\n        hideMultibuy: rule?.hideMultibuy === true\n      };\n    }\n\n    const PROMO_ID = \"ct-promo-message\";\n    const TIB_PROMO_ID = \"ct-promo-tib-message\";\n    const TILE_PROMO_ID = \"ct-promo-tile-message\";\n    const BANNER_PROMO_ID = \"ct-promo-banner-strip\";\n    const NATIVE_PROMO_STYLE_ID = \"ct-hide-native-promo\";\n    const PRICE_DIFF_STYLE_ID = \"ct-hide-price-diff\";\n    const TILE_HIDE_MULTIBUY_ATTR = \"data-ct-hide-multibuy\";\n\n    const CART_PANEL_TARGET_SEL = \".coupon-code__panel\";\n    const CART_PANEL_STYLE_ID = \"ct-coupon-panel-swap-style\";\n    const CART_PANEL_RUN_ATTR = \"data-ct-coupon-panel-swapped\";\n    const CART_DIALOG_ID = \"ct-no-further-promos-dialog\";\n\n    let io = null;\n    let pdpMultibuyObserver = null;\n\n    function getCartReplacementCopy() {\n      const lang = siteLang.split(\"_\")[0];\n\n      if (lang === \"fr\") {\n        return {\n          heading: \"Notre meilleure offre\",\n          pill: \"Appliquée\",\n          bodyHtml:\n            'Votre \u003cstrong\u003eoffre\u003c/strong\u003e a été appliquée à cette commande.\u003cbr\u003e\u003cbr\u003eProfitez de nos meilleurs prix - \u003cstrong\u003eaucun code promotionnel requis.\u003c/strong\u003e.',\n          termsTitle: \"Conditions générales\",\n          termsLink: \"Conditions générales\",\n          termsBodyHtml:\n            \"Les prix affichés incluent déjà la remise et sont appliqués à votre commande. Cette offre ne peut pas être cumulée avec d'autres promotions, codes de réduction, bons d'achat ou offres de cashback. Les conditions générales de vente s'appliquent également.\"\n        };\n      }\n\n      if (lang === \"de\") {\n        return {\n          heading: \"Bestes Angebot\",\n          pill: \"Angewandt\",\n          bodyHtml:\n            'Ihr \u003cstrong\u003eAngebot\u003c/strong\u003e wurde auf diese Bestellung angewendet.\u003cbr\u003e\u003cbr\u003eProfitieren Sie noch heute von unseren besten Preisen – \u003cstrong\u003ekein Gutscheincode erforderlich.\u003c/strong\u003e.',\n          termsTitle: \"Allgemeine Geschäftsbedingungen\",\n          termsLink: \"Allgemeine Geschäftsbedingungen\",\n          termsBodyHtml:\n            \"Die angezeigten Preise sind bereits rabattiert und werden auf Ihre Bestellung angewendet. Dieses Angebot kann nicht mit anderen Rabatten, Gutscheinen, Preisnachlässen oder Cashback-Angeboten kombiniert werden. Es gelten die üblichen Geschäftsbedingungen.\"\n        };\n      }\n\n      return {\n        heading: \"This is our best offer\",\n        pill: \"Applied\",\n        bodyHtml:\n          'Your \u003cstrong\u003eoffer\u003c/strong\u003e has been applied to this order.\u003cbr\u003e\u003cbr\u003eEnjoy our best prices today - \u003cstrong\u003eno promo code required\u003c/strong\u003e.',\n        termsTitle: \"Terms and Conditions\",\n        termsLink: \"Terms and Conditions\",\n        termsBodyHtml:\n          \"The prices shown are already discounted and applied to your order. This offer cannot be used in conjunction with other discounts, coupons, money-off vouchers, or cashback deals. Standard terms and conditions also apply.\"\n      };\n    }\n\n    function escapeHtml(str) {\n      return String(str)\n        .replaceAll(\"\u0026\", \"\u0026amp;\")\n        .replaceAll(\"\u003c\", \"\u0026lt;\")\n        .replaceAll(\"\u003e\", \"\u0026gt;\")\n        .replaceAll('\"', \"\u0026quot;\")\n        .replaceAll(\"'\", \"\u0026#039;\");\n    }\n\n    function ensureCartPanelStyles() {\n      if (document.getElementById(CART_PANEL_STYLE_ID)) return;\n\n      const style = document.createElement(\"style\");\n      style.id = CART_PANEL_STYLE_ID;\n      style.textContent = `\n        .coupon-code__panel[${CART_PANEL_RUN_ATTR}=\"true\"]{\n          background-color:#D8EADC !important;\n          border-radius:5px;\n        }\n        .coupon-code__panel[${CART_PANEL_RUN_ATTR}=\"true\"] .offer-box{\n          align-items:center;\n          justify-content:space-between;\n          color:#116A60;\n        }\n        .coupon-code__panel[${CART_PANEL_RUN_ATTR}=\"true\"] .offer-box p{\n          font-size:1.6rem;\n        }\n        .coupon-code__panel[${CART_PANEL_RUN_ATTR}=\"true\"] .appliedPill{\n          background-color:#116A60;\n          color:#fff;\n          padding:4px 8px;\n          border-radius:.5rem;\n          font-size:1.4rem;\n          font-weight:600;\n        }\n      `;\n      document.head.appendChild(style);\n    }\n\n    function buildCartCouponPanelHtml(copy) {\n      const headingSafe = escapeHtml(copy.heading);\n      const pillSafe = escapeHtml(copy.pill);\n      const bodyHtml = String(copy.bodyHtml || \"\");\n      const termsBodyHtml = String(copy.termsBodyHtml || \"\");\n      const termsLinkSafe = escapeHtml(copy.termsLink);\n\n      return `\n\u003cdiv class=\"grey1 bg-blue5 p-all-m m-bottom-m coupon-code__panel text-center\" ${CART_PANEL_RUN_ATTR}=\"true\"\u003e\n  \u003cdiv class=\"content-asset\"\u003e\n    \u003cdiv class=\"m-bottom-m text-center newPanel\"\u003e\n      \u003cdiv class=\"content-asset\"\u003e\n        \u003cdiv class=\"bold text-left p-bottom-s offer-box d-flex flex-direction-row\"\u003e\n          \u003cp class=\"p-all-z m-all-z\"\u003e\n            \u003csvg width=\"18\" height=\"18\" viewBox=\"0 0 18 18\" fill=\"none\"\u003e\n              \u003cpath d=\"M15 4.44434L6.75 12.236L3 8.69434\" stroke=\"#116A60\" stroke-width=\"3\" stroke-linecap=\"round\" stroke-linejoin=\"round\"\u003e\u003c/path\u003e\n            \u003c/svg\u003e\n            ${headingSafe}\n          \u003c/p\u003e\n          \u003cp class=\"m-all-z appliedPill\"\u003e${pillSafe}\u003c/p\u003e\n        \u003c/div\u003e\n        \u003cp class=\"text-left m-all-z\"\u003e${bodyHtml}\u003c/p\u003e\n      \u003c/div\u003e\n    \u003c/div\u003e\n  \u003c/div\u003e\n  \u003ca href=\"#\" class=\"link2 js-termsandconditions\"\u003e${termsLinkSafe}\u003c/a\u003e\n  \u003cdiv class=\"d-none js-no-further-promotions-tc\"\u003e\n    \u003cp class=\"mps-m-top-xl m-bottom-m text-center\"\u003e${termsBodyHtml}\u003c/p\u003e\n  \u003c/div\u003e\n\u003c/div\u003e\n`.trim();\n    }\n\n    function openCartTermsDialog(copy, contentHtml) {\n      if (!window.jQuery || !jQuery.ui || !jQuery.ui.dialog) {\n        alert(contentHtml.replace(/\u003c[^\u003e]*\u003e/g, \"\"));\n        return;\n      }\n\n      let $dialog = jQuery(\"#\" + CART_DIALOG_ID);\n\n      if (!$dialog.length) {\n        $dialog = jQuery('\u003cdiv id=\"' + CART_DIALOG_ID + '\"\u003e\u003c/div\u003e');\n        jQuery(\"body\").append($dialog);\n      }\n\n      $dialog.attr(\"title\", copy.termsTitle || \"Terms and Conditions\");\n\n      $dialog.html(contentHtml).dialog({\n        modal: true,\n        width: 500,\n        resizable: false,\n        draggable: false,\n        close: function () {\n          $dialog.dialog(\"destroy\").remove();\n        }\n      });\n    }\n\n    function bindCartTermsClick(scope, copy) {\n      const link = scope.querySelector(\".js-termsandconditions\");\n      const hidden = scope.querySelector(\".js-no-further-promotions-tc\");\n      if (!link || !hidden) return;\n\n      link.addEventListener(\"click\", function (e) {\n        e.preventDefault();\n        openCartTermsDialog(copy, hidden.innerHTML);\n      });\n    }\n\n    function injectCartCouponReplacement() {\n      if (!isCartPage()) return;\n\n      const panel = document.querySelector(CART_PANEL_TARGET_SEL);\n      if (!panel || panel.getAttribute(CART_PANEL_RUN_ATTR) === \"true\") return;\n\n      ensureCartPanelStyles();\n\n      const copy = getCartReplacementCopy();\n      panel.outerHTML = buildCartCouponPanelHtml(copy);\n\n      const newPanel = document.querySelector(`${CART_PANEL_TARGET_SEL}[${CART_PANEL_RUN_ATTR}=\"true\"]`);\n      if (newPanel) {\n        bindCartTermsClick(newPanel, copy);\n        console.log(\"[Promo] Cart coupon panel replaced\");\n      }\n    }\n\n    function getIO() {\n      if (!CONFIG.ENABLE_SCROLL_FADE) return null;\n      if (io) return io;\n      if (!(\"IntersectionObserver\" in window)) return null;\n      io = new IntersectionObserver(entries =\u003e {\n        entries.forEach(e =\u003e {\n          if (e.isIntersecting || e.intersectionRatio \u003e 0) {\n            e.target.offsetHeight;\n            e.target.classList.add(\"promo-message--visible\");\n            io.unobserve(e.target);\n          }\n        });\n      }, { threshold: 0.01, rootMargin: \"0px 0px -10% 0px\" });\n      return io;\n    }\n\n    function observeForFade(el) {\n      const reduced = window.matchMedia?.(\"(prefers-reduced-motion: reduce)\").matches;\n      if (reduced || !CONFIG.ENABLE_SCROLL_FADE) {\n        el.classList.add(\"promo-message--visible\");\n        return;\n      }\n\n      const inVp = n =\u003e {\n        const r = n.getBoundingClientRect();\n        return r.bottom \u003e= 0 \u0026\u0026 r.top \u003c= (window.innerHeight || 0);\n      };\n\n      const reveal = () =\u003e {\n        el.offsetHeight;\n        requestAnimationFrame(() =\u003e el.classList.add(\"promo-message--visible\"));\n      };\n\n      if (inVp(el)) {\n        reveal();\n        return;\n      }\n\n      const observer = getIO();\n      if (!observer) reveal();\n      else observer.observe(el);\n\n      requestAnimationFrame(() =\u003e {\n        if (inVp(el)) reveal();\n      });\n    }\n\n    function setPromoActive() {\n      try {\n        document.documentElement.setAttribute(\"data-ct-promo-active\", \"1\");\n      } catch {}\n    }\n\n    function copyToClipboard(text) {\n      if (!text) return;\n      navigator.clipboard?.writeText(text).catch(() =\u003e {});\n    }\n\n    function setTileMultibuyState(tile, shouldHide) {\n      if (!tile) return;\n      if (shouldHide) tile.setAttribute(TILE_HIDE_MULTIBUY_ATTR, \"1\");\n      else tile.removeAttribute(TILE_HIDE_MULTIBUY_ATTR);\n    }\n\n    function setInlineHide(el, shouldHide) {\n      if (!el) return;\n\n      if (shouldHide) {\n        el.style.setProperty(\"display\", \"none\", \"important\");\n        return;\n      }\n\n      if (el.style.getPropertyValue(\"display\") === \"none\") {\n        el.style.removeProperty(\"display\");\n        if (!el.getAttribute(\"style\")) el.removeAttribute(\"style\");\n      }\n    }\n\n    function queryUnique(selectors) {\n      const seen = new Set();\n      const out = [];\n      selectors.forEach(selector =\u003e {\n        document.querySelectorAll(selector).forEach(el =\u003e {\n          if (!seen.has(el)) {\n            seen.add(el);\n            out.push(el);\n          }\n        });\n      });\n      return out;\n    }\n\n    function syncNativeMultibuyStates() {\n      document.querySelectorAll(\".both-tracker-container\").forEach(container =\u003e {\n        const locked = container.querySelector(\".mb-tracker-container.js-accessibility-return.cursor-pointer:not(.tracker-unlocked)\");\n        const unlocked = container.querySelector(\".mb-tracker-container.tracker-unlocked\");\n\n        if (!locked || !unlocked) return;\n\n        const unlockedVisible =\n          unlocked.offsetParent !== null ||\n          window.getComputedStyle(unlocked).display !== \"none\";\n\n        if (unlockedVisible) {\n          locked.style.setProperty(\"display\", \"none\", \"important\");\n        } else {\n          if (locked.style.getPropertyValue(\"display\") === \"none\") {\n            locked.style.removeProperty(\"display\");\n            if (!locked.getAttribute(\"style\")) locked.removeAttribute(\"style\");\n          }\n        }\n      });\n    }\n\n    function applyGlobalMultibuyState(shouldHide) {\n      try {\n        if (shouldHide) document.documentElement.setAttribute(\"data-ct-hide-multibuy-global\", \"1\");\n        else document.documentElement.removeAttribute(\"data-ct-hide-multibuy-global\");\n      } catch {}\n\n      const textNodes = queryUnique([CONFIG.SELECTORS.PDP_MULTIBUY_TEXT]);\n      const trackerNodes = queryUnique(CONFIG.SELECTORS.GLOBAL_MULTIBUY_TRACKERS);\n\n      textNodes.forEach(el =\u003e setInlineHide(el, shouldHide));\n      trackerNodes.forEach(el =\u003e setInlineHide(el, shouldHide));\n\n      if (!shouldHide) {\n        syncNativeMultibuyStates();\n      }\n    }\n\n    function syncPdpMultibuyStateFromRule() {\n      const pid = normalizePid(getPdpProductId());\n      const rule = isProductPage() ? findMatchingRule(pid, \"pdp\") : null;\n      const payload = rule ? resolvePayloadFromRule(rule, pid, \"pdp\") : null;\n      applyGlobalMultibuyState(payload?.hideMultibuy === true);\n    }\n\n    function setupPdpMultibuyObserver() {\n      if (!isProductPage()) return;\n\n      if (pdpMultibuyObserver) {\n        try { pdpMultibuyObserver.disconnect(); } catch {}\n        pdpMultibuyObserver = null;\n      }\n\n      const target =\n        document.querySelector(CONFIG.SELECTORS.PDP_DETAILS_WRAPPER) ||\n        document.querySelector(\".product-detail\") ||\n        document.body;\n\n      let t = null;\n\n      const run = () =\u003e {\n        clearTimeout(t);\n        t = setTimeout(() =\u003e {\n          try {\n            syncPdpMultibuyStateFromRule();\n            syncNativeMultibuyStates();\n          } catch (e) {\n            console.warn(\"[Promo] PDP multibuy observer error\", e);\n          }\n        }, 80);\n      };\n\n      run();\n\n      pdpMultibuyObserver = new MutationObserver(run);\n      pdpMultibuyObserver.observe(target, {\n        childList: true,\n        subtree: true,\n        attributes: true,\n        attributeFilter: [\"class\", \"style\"]\n      });\n    }\n\n    function ensureStyles() {\n      // Only remove and re-inject if not already present.\n      // Avoids constant style tag churn (head flashing) on every runInjection call.\n      // We use a data attribute to fingerprint the current config so if BF_MODE\n      // or other style-affecting config changes we still re-inject correctly.\n      const styleFingerprint = [\n        CONFIG.BF_MODE ? \"bf\" : \"normal\",\n        CONFIG.ENABLE_SCROLL_FADE ? \"fade\" : \"nofade\",\n        CONFIG.STYLES.BG,\n        CONFIG.STYLES.BANNER.BG\n      ].join(\"|\");\n\n      const existing = document.getElementById(\"promo-message-style\");\n      if (existing \u0026\u0026 existing.getAttribute(\"data-ct-fingerprint\") === styleFingerprint) return;\n      if (existing) existing.remove();\n\n      const style = document.createElement(\"style\");\n      style.id = \"promo-message-style\";\n      style.setAttribute(\"data-ct-fingerprint\", styleFingerprint);\n      style.textContent = `\n        .promo-message:not(.ct-promo-tib-message) {\n          text-decoration: none !important;\n          font-family: Futura, Arial;\n          cursor: pointer;\n          background-color: ${CONFIG.BF_MODE ? CONFIG.STYLES.BF.BG : CONFIG.STYLES.BG};\n          color: ${CONFIG.BF_MODE ? CONFIG.STYLES.BF.COLOR : CONFIG.STYLES.COLOR};\n          font-size: ${CONFIG.STYLES.FONT_SIZE};\n          font-weight: ${CONFIG.STYLES.FONT_WEIGHT};\n          padding: ${CONFIG.STYLES.PADDING};\n          margin-top: ${CONFIG.STYLES.MARGIN_TOP};\n          display: inline-block;\n          border-radius: ${CONFIG.STYLES.BORDER_RADIUS};\n          letter-spacing: ${CONFIG.STYLES.LETTER_SPACING};\n          ${CONFIG.ENABLE_SCROLL_FADE\n            ? `opacity:0;transform:translateY(${CONFIG.FADE.TRANSLATE_Y_PX}px);transition:opacity ${CONFIG.FADE.DURATION_MS}ms ${CONFIG.FADE.EASING},transform ${CONFIG.FADE.DURATION_MS}ms ${CONFIG.FADE.EASING};will-change:opacity,transform;`\n            : `opacity:1;transform:none;`}\n        }\n        .ct-promo-tile-under-price {\n          display: block !important;\n          width: max-content !important;\n          clear: both;\n          margin-top: 6px !important;\n        }\n        .ct-promo-tib-message {\n          font-family: Futura !important;\n          background: none !important;\n          color: ${CONFIG.STYLES.TIB.COLOR} !important;\n          font-size: ${CONFIG.STYLES.TIB.FONT_SIZE} !important;\n          font-weight: ${CONFIG.STYLES.TIB.FONT_WEIGHT} !important;\n          text-transform: uppercase;\n          letter-spacing: ${CONFIG.STYLES.TIB.LETTER_SPACING};\n          margin-top: ${CONFIG.STYLES.TIB.MARGIN_TOP};\n          margin-bottom: 10px !important;\n          padding: 0 !important;\n          border: 0 !important;\n          border-radius: 0 !important;\n          box-shadow: none !important;\n          display: block !important;\n          width: 100%;\n          text-decoration: none !important;\n          background-image: none !important;\n          ${CONFIG.ENABLE_SCROLL_FADE\n            ? `opacity:0;transform:translateY(${CONFIG.FADE.TRANSLATE_Y_PX}px);transition:opacity ${CONFIG.FADE.DURATION_MS}ms ${CONFIG.FADE.EASING},transform ${CONFIG.FADE.DURATION_MS}ms ${CONFIG.FADE.EASING};will-change:opacity,transform;`\n            : `opacity:1;transform:none;`}\n        }\n        .ct-promo-banner-strip {\n          background-color: ${CONFIG.STYLES.BANNER.BG} !important;\n          font-size: ${CONFIG.STYLES.BANNER.FONT_SIZE} !important;\n          width: 100%;\n        }\n        .ct-promo-banner-strip .banner-strip-carousel {\n          background-color: ${CONFIG.STYLES.BANNER.BG} !important;\n          font-size: ${CONFIG.STYLES.BANNER.FONT_SIZE} !important;\n        }\n        .ct-promo-banner-strip .ct-promo-banner-strip-track {\n          margin: 0;\n          padding: 0;\n          list-style: none;\n        }\n        .ct-promo-banner-strip .ct-promo-banner-strip-slide {\n          list-style: none;\n        }\n        .ct-promo-banner-strip .ct-promo-banner-strip-slide \u003e div {\n          text-align: center;\n        }\n        .ct-promo-banner-strip .ct-promo-banner-strip-slide p {\n          background-color: ${CONFIG.STYLES.BANNER.BG} !important;\n          color: ${CONFIG.STYLES.BANNER.COLOR} !important;\n          font-size: ${CONFIG.STYLES.BANNER.FONT_SIZE} !important;\n          display: inline-block;\n          margin: 0;\n          padding: 6px 0;\n          \n        }\n        .slick-next__icon::before,\n        .slick-prev__icon::before {\n          background: none;\n        }\n        .ct-promo-banner-strip .slick-prev,\n        .ct-promo-banner-strip .slick-next {\n          z-index: 2;\n          width: 20px !important;\n          height: 20px !important;\n          min-width: 20px !important;\n          min-height: 20px !important;\n          padding: 0 !important;\n          margin: 0 !important;\n          background: transparent !important;\n          background-color: transparent !important;\n          border: 0 !important;\n          border-radius: 0 !important;\n          box-shadow: none !important;\n          outline: none !important;\n          appearance: none !important;\n          -webkit-appearance: none !important;\n          display: flex !important;\n          align-items: center !important;\n          justify-content: center !important;\n          top: 50% !important;\n          transform: translateY(-50%) !important;\n          overflow: visible !important;\n          font-size: 0 !important;\n          line-height: 0 !important;\n        }\n        .ct-promo-banner-strip .slick-prev:hover,\n        .ct-promo-banner-strip .slick-next:hover,\n        .ct-promo-banner-strip .slick-prev:focus,\n        .ct-promo-banner-strip .slick-next:focus,\n        .ct-promo-banner-strip .slick-prev:active,\n        .ct-promo-banner-strip .slick-next:active {\n          background: transparent !important;\n          background-color: transparent !important;\n          border: 0 !important;\n          box-shadow: none !important;\n          outline: none !important;\n        }\n        .ct-promo-banner-strip .slick-prev {\n          left: 8px !important;\n        }\n        .ct-promo-banner-strip .slick-next {\n          right: 8px !important;\n        }\n        .ct-promo-banner-strip .slick-prev::before,\n        .ct-promo-banner-strip .slick-next::before {\n          content: none !important;\n        }\n        .ct-promo-banner-strip .slick-prev__icon,\n        .ct-promo-banner-strip .slick-next__icon {\n          position: relative !important;\n          display: block !important;\n          width: 20px !important;\n          height: 20px !important;\n          background: transparent !important;\n          border: 0 !important;\n          box-shadow: none !important;\n        }\n        .ct-promo-banner-strip .slick-prev__icon::after,\n        .ct-promo-banner-strip .slick-next__icon::after {\n          content: \"\" !important;\n          position: absolute !important;\n          top: 50% !important;\n          left: 50% !important;\n          width: 10px !important;\n          height: 10px !important;\n          padding: 0 !important;\n          margin: 0 !important;\n          display: block !important;\n          background: transparent !important;\n          border: solid #fff !important;\n          border-width: 0 1px 1px 0 !important;\n        }\n        .ct-promo-banner-strip .slick-next__icon::after {\n          transform: translate(-70%, -50%) rotate(-45deg) !important;\n        }\n        .ct-promo-banner-strip .slick-prev__icon::after {\n          transform: translate(-30%, -50%) rotate(135deg) !important;\n        }\n        .ct-promo-banner-strip .accessibility-hidden {\n          position: absolute !important;\n          width: 1px !important;\n          height: 1px !important;\n          padding: 0 !important;\n          margin: -1px !important;\n          overflow: hidden !important;\n          clip: rect(0, 0, 0, 0) !important;\n          white-space: nowrap !important;\n          border: 0 !important;\n        }\n\n        .font__secondary.h5.uppercase.grey2.m-top-xs {\n          display: block !important;\n        }\n\n        [${TILE_HIDE_MULTIBUY_ATTR}=\"1\"] .product-tile__promo,\n        [${TILE_HIDE_MULTIBUY_ATTR}=\"1\"] .mb-tracker-container:not(.tracker-unlocked),\n        [${TILE_HIDE_MULTIBUY_ATTR}=\"1\"] .both-tracker-container,\n        [${TILE_HIDE_MULTIBUY_ATTR}=\"1\"] .js-tile-pricing ~ .font__secondary {\n          display: none !important;\n        }\n\n        html[data-ct-hide-multibuy-global=\"1\"] .font__secondary.h5.uppercase.grey2.m-top-xs,\n        html[data-ct-hide-multibuy-global=\"1\"] .js-multibuy-tracker-placeholder-mobile,\n        html[data-ct-hide-multibuy-global=\"1\"] .js-multibuy-tracker-placeholder,\n        html[data-ct-hide-multibuy-global=\"1\"] .both-tracker-container,\n        html[data-ct-hide-multibuy-global=\"1\"] .mb-tracker-container.js-accessibility-return.cursor-pointer:not(.tracker-unlocked) {\n          display: none !important;\n        }\n\n        ${CONFIG.ENABLE_SCROLL_FADE\n          ? `.promo-message--visible{opacity:1!important;transform:translateY(0)!important;}@media(prefers-reduced-motion:reduce){.promo-message,.ct-promo-tib-message,.promo-message--visible{transition:none!important;transform:none!important;opacity:1!important;}}`\n          : ``}\n      `;\n      document.head.appendChild(style);\n    }\n\n    function ensureStyleOnce(id, css) {\n      if (document.getElementById(id)) return;\n\n      const hasPromoNode = document.querySelector(\n        `.promo-message[data-ct-promo-id=\"${PROMO_ID}\"],\n         .promo-message[data-ct-promo-id=\"${TILE_PROMO_ID}\"],\n         .promo-message[data-ct-promo-id=\"${TIB_PROMO_ID}\"]`\n      );\n\n      if (!hasPromoNode) return;\n\n      const s = document.createElement(\"style\");\n      s.id = id;\n      s.textContent = css;\n      document.head.appendChild(s);\n    }\n\n    function markTileHasPromoCallout(node) {\n      try {\n        const tile = node?.closest?.(CONFIG.SELECTORS.PLP_TILE) || node?.closest?.(CONFIG.SELECTORS.HP_TILE_SELECTOR);\n        if (tile) tile.setAttribute(\"data-ct-promo-has-callout\", \"1\");\n      } catch {}\n    }\n\n    function createNode(message, href, copyCode, options = {}) {\n      const el = document.createElement(href ? \"a\" : \"div\");\n\n      if (options.extraClass \u0026\u0026 options.skipBaseClass) {\n        el.className = options.extraClass;\n      } else if (options.extraClass) {\n        el.className = `promo-message ${options.extraClass}`;\n      } else {\n        el.className = \"promo-message\";\n      }\n\n      el.setAttribute(\"data-ct-promo-id\", options.id || PROMO_ID);\n\n      if (href) {\n        el.setAttribute(\"href\", href);\n        el.setAttribute(\"tabindex\", \"0\");\n      }\n\n      const raw = String(message || \"\").trim();\n      if (!raw) return null;\n\n      const finalText = CONFIG.ALL_CAPS ? raw.toUpperCase() : raw;\n      el.textContent = finalText;\n\n      // Store the original English text on a data attribute so idempotency\n      // checks compare against our source text rather than the DOM text\n      // which Localise may have already translated to another language.\n      el.setAttribute(\"data-ct-promo-text\", finalText);\n\n      if (copyCode) {\n        el.addEventListener(\"click\", e =\u003e {\n          copyToClipboard(copyCode);\n          if (!href) {\n            e.preventDefault();\n            e.stopPropagation();\n          }\n        });\n      }\n\n      if (!CONFIG.ENABLE_SCROLL_FADE) el.classList.add(\"promo-message--visible\");\n      return el;\n    }\n\n    function firstExistingSelector(selectors) {\n      for (const s of selectors) {\n        const n = document.querySelector(s);\n        if (n) return n;\n      }\n      return null;\n    }\n\n    function getNativeBannerNodes(wrapper) {\n      if (!wrapper) return [];\n\n      return [...wrapper.children].filter(node =\u003e {\n        if (node.getAttribute(\"data-ct-promo-id\") === BANNER_PROMO_ID) return false;\n        return true;\n      });\n    }\n\n    function hideNativeBannerNodes(wrapper) {\n      getNativeBannerNodes(wrapper).forEach(node =\u003e {\n        if (!node.hasAttribute(\"data-ct-prev-style\")) {\n          node.setAttribute(\"data-ct-prev-style\", node.getAttribute(\"style\") || \"\");\n        }\n        node.style.setProperty(\"display\", \"none\", \"important\");\n      });\n    }\n\n    function restoreNativeBannerNodes(wrapper) {\n      if (!wrapper) return;\n\n      [...wrapper.children].forEach(node =\u003e {\n        if (!node.hasAttribute(\"data-ct-prev-style\")) return;\n\n        const prev = node.getAttribute(\"data-ct-prev-style\");\n        node.removeAttribute(\"data-ct-prev-style\");\n\n        if (prev) {\n          node.setAttribute(\"style\", prev);\n        } else {\n          node.removeAttribute(\"style\");\n        }\n      });\n    }\n\n    function destroyInjectedBannerStrip() {\n      const existing = document.querySelector(`[data-ct-promo-id=\"${BANNER_PROMO_ID}\"]`);\n\n      if (existing) {\n        try {\n          if (window.jQuery) {\n            const $track = window.jQuery(existing).find(\".ct-promo-banner-strip-track.slick-initialized\");\n            if ($track.length \u0026\u0026 typeof $track.slick === \"function\") {\n              $track.slick(\"unslick\");\n            }\n          }\n        } catch {}\n        existing.remove();\n      }\n\n      // Restore native content for all possible container types\n      const nativeContainer = findNativeBannerContainer();\n      if (nativeContainer) restoreNativeBannerNodes(nativeContainer.el);\n\n      // Remove active-service-banner class so sticky header offset resets\n      const headerWrapper = document.querySelector(\".js-header-wrapper\");\n      if (headerWrapper) headerWrapper.classList.remove(\"active-service-banner\");\n    }\n\n    function getBannerLines(bannerData) {\n      return [\n        String(bannerData?.line1 || \"\").trim(),\n        String(bannerData?.line2 || \"\").trim(),\n        String(bannerData?.line3 || \"\").trim()\n      ].filter(Boolean);\n    }\n\n    function buildBannerSignature(slides) {\n      return JSON.stringify(\n        slides.map(slide =\u003e ({\n          ruleId: slide.ruleId,\n          text: slide.text\n        }))\n      );\n    }\n\n    function createPrevArrow(slideCount) {\n      return `\n        \u003cbutton type=\"button\" aria-label=\"Previous banner message\" class=\"slick-prev keyboard-focus-outline slick-arrow\"\u003e\n          \u003cspan class=\"slick-prev__icon position-relative\"\u003e\u003c/span\u003e\n          \u003cp class=\"accessibility-hidden text-transform-none\"\u003eShowing item 1 of ${slideCount}\u003c/p\u003e\n        \u003c/button\u003e\n      `;\n    }\n\n    function createNextArrow() {\n      return `\n        \u003cbutton type=\"button\" aria-label=\"Next banner message\" class=\"slick-next keyboard-focus-outline slick-arrow\"\u003e\n          \u003cspan class=\"slick-next__icon position-relative\"\u003e\u003c/span\u003e\n        \u003c/button\u003e\n      `;\n    }\n\n    function initInjectedBannerStrip(node, slideCount) {\n      if (!window.jQuery || slideCount \u003c= 1) return;\n\n      const $ = window.jQuery;\n      const $track = $(node).find(\".ct-promo-banner-strip-track\");\n\n      if (!$track.length) return;\n      if (typeof $track.slick !== \"function\") return;\n      if ($track.hasClass(\"slick-initialized\")) return;\n\n      $track.slick({\n        slidesToShow: 1,\n        slidesToScroll: 1,\n        arrows: true,\n        dots: false,\n        infinite: slideCount \u003e 1,\n        autoplay: slideCount \u003e 1,\n        autoplaySpeed: 3000,\n        speed: 350,\n        cssEase: \"ease\",\n        pauseOnHover: true,\n        pauseOnFocus: false,\n        adaptiveHeight: false,\n        prevArrow: createPrevArrow(slideCount),\n        nextArrow: createNextArrow()\n      });\n\n      $(node).on(\"click\", \".slick-prev, .slick-next\", function () {\n        this.blur();\n        setTimeout(() =\u003e {\n          if ($track.hasClass(\"slick-initialized\")) {\n            $track.slick(\"slickPlay\");\n          }\n        }, 50);\n      });\n    }\n\n    function createBannerStripNode(slides) {\n      const wrapper = document.createElement(\"div\");\n      wrapper.className = \"banner-strip ct-promo-banner-strip d-none-sticky\";\n      wrapper.setAttribute(\"data-ct-promo-id\", BANNER_PROMO_ID);\n      wrapper.setAttribute(\"data-ct-banner-signature\", buildBannerSignature(slides));\n      wrapper.style.backgroundColor = CONFIG.STYLES.BANNER.BG;\n      wrapper.style.fontSize = CONFIG.STYLES.BANNER.FONT_SIZE;\n\n      const carousel = document.createElement(\"div\");\n      carousel.className = \"banner-strip-carousel js-banner-strip-carousel mps-col-40 m-auto\";\n      carousel.style.backgroundColor = CONFIG.STYLES.BANNER.BG;\n      carousel.style.fontSize = CONFIG.STYLES.BANNER.FONT_SIZE;\n\n      const ul = document.createElement(\"ul\");\n      ul.className = \"ct-promo-banner-strip-track\";\n\n      slides.forEach(slide =\u003e {\n        const li = document.createElement(\"li\");\n        li.className = \"ct-promo-banner-strip-slide\";\n\n        const inner = document.createElement(\"div\");\n        const p = document.createElement(\"p\");\n        p.className = \"text-center bg-blue1 white m-all-z\";\n        p.style.backgroundColor = CONFIG.STYLES.BANNER.BG;\n        p.style.fontSize = CONFIG.STYLES.BANNER.FONT_SIZE;\n        p.style.display = \"inline-block\";\n        p.textContent = slide.text;\n\n        inner.appendChild(p);\n        li.appendChild(inner);\n        ul.appendChild(li);\n      });\n\n      carousel.appendChild(ul);\n      wrapper.appendChild(carousel);\n\n      requestAnimationFrame(() =\u003e initInjectedBannerStrip(wrapper, slides.length));\n      return wrapper;\n    }\n\n    function collectMatchingBannerSlides() {\n      const slides = [];\n      for (const rule of REMOTE.rules) {\n        const regionKey = REGION.toLowerCase();\n        if (!rule?.enabled) continue;\n        if (!rule.countryEnabled?.[regionKey]) continue;\n        if (!isNowInWindow(rule.startUtc, rule.endUtc)) continue;\n        if (rule.scope?.bannerstrip === false) continue;\n        const payload = resolvePayloadFromRule(rule, \"\", \"bannerstrip\");\n        if (!payload) continue;\n        const lines = getBannerLines(payload.bannerData);\n        if (!lines.length) continue;\n        lines.forEach(line =\u003e slides.push({ ruleId: rule.ruleId, text: line }));\n      }\n      return slides;\n    }\n\n    function findNativeBannerContainer() {\n      // Case A: standard service-banner (UK/EU/US markets)\n      const serviceBanner = document.querySelector(\".service-banner\");\n      if (serviceBanner) return { el: serviceBanner, type: \"service-banner\" };\n\n      // Case B: custom-asset banner (AU and other markets using content asset)\n      // Identified by .custom-asset inside the banner wrapper area\n      const customAsset = document.querySelector(\".banner-strip__wrapper .custom-asset, .js-header-wrapper .custom-asset\");\n      if (customAsset) return { el: customAsset, type: \"custom-asset\" };\n\n      // Case C: banner-strip__wrapper exists but is empty — always present in page structure\n      // This is the correct injection point — it sits above the header in js-header-wrapper\n      // so the sticky header offset accounts for it correctly\n      const bannerWrapper = document.querySelector(\".banner-strip__wrapper\");\n      if (bannerWrapper) return { el: bannerWrapper, type: \"banner-strip__wrapper\" };\n\n      // No container found at all\n      return null;\n    }\n\n    function injectSitewideBannerStrip() {\n      // Never inject on homepage or checkout.\n      // Banner strip has NO clearance/sale restriction — it shows on all pages\n      // (PLP, PDP, cart, sale, clearance) as long as a promo is active.\n      if (isHomePage() || isCheckoutPage()) {\n        destroyInjectedBannerStrip();\n        return;\n      }\n\n      // Only inject on PLP, PDP and cart pages\n      if (!isCategoryPage() \u0026\u0026 !isProductPage() \u0026\u0026 !isCartPage()) return;\n\n      const slides = collectMatchingBannerSlides();\n      const existing = document.querySelector(`[data-ct-promo-id=\"${BANNER_PROMO_ID}\"]`);\n\n      // No active banner rules — clean up and restore native\n      if (!slides.length) {\n        if (existing) destroyInjectedBannerStrip();\n        return;\n      }\n\n      const signature = buildBannerSignature(slides);\n      const currentSig = existing?.getAttribute(\"data-ct-banner-signature\") || \"\";\n\n      // ── CASE A \u0026 B: a native banner container exists ────────────────────────\n      // We hide its content and inject ours inside it, regardless of whether\n      // it is a .service-banner or a .custom-asset content block.\n      const nativeContainer = findNativeBannerContainer();\n\n      if (nativeContainer) {\n        const { el, type } = nativeContainer;\n        const isInsideContainer = !!existing \u0026\u0026 el.contains(existing);\n\n        // Already correctly injected — nothing to do\n        if (existing \u0026\u0026 currentSig === signature \u0026\u0026 isInsideContainer) return;\n\n        // Remove stale injection\n        if (existing) {\n          try {\n            if (window.jQuery) {\n              const $track = window.jQuery(existing).find(\".ct-promo-banner-strip-track.slick-initialized\");\n              if ($track.length \u0026\u0026 typeof $track.slick === \"function\") $track.slick(\"unslick\");\n            }\n          } catch {}\n          existing.remove();\n        }\n\n        // Hide all native content inside the container\n        hideNativeBannerNodes(el);\n\n        // If it's a service-banner, also make its wrapper visible\n        // (wrapper has d-none by default and relies on active-service-banner class)\n        // For all cases, ensure js-header-wrapper has active-service-banner class\n        // so the sticky header offset correctly accounts for the banner height\n        const headerWrapper = document.querySelector(\".js-header-wrapper\");\n        if (headerWrapper) headerWrapper.classList.add(\"active-service-banner\");\n\n        if (type === \"service-banner\") {\n          const wrapper = el.closest(\".service-banner__wrapper, .banner-strip__wrapper\");\n          if (wrapper) {\n            wrapper.style.removeProperty(\"display\");\n            wrapper.classList.remove(\"d-none\");\n          }\n        }\n\n        if (type === \"banner-strip__wrapper\") {\n          // The wrapper itself is our container — make it visible\n          el.style.removeProperty(\"display\");\n          el.classList.remove(\"d-none\");\n        }\n\n        const node = createBannerStripNode(slides);\n        el.appendChild(node);\n        if (!_loggedRules.has(\"banner|injected-native\")) {\n          _loggedRules.add(\"banner|injected-native\");\n          console.log(\"[Promo] Banner injected into native container (\" + type + \")\");\n        }\n        return;\n      }\n\n      // ── CASE C: no container at all — build our own before header ───────────\n      if (existing \u0026\u0026 currentSig === signature) return;\n\n      if (existing) {\n        try {\n          if (window.jQuery) {\n            const $track = window.jQuery(existing).find(\".ct-promo-banner-strip-track.slick-initialized\");\n            if ($track.length \u0026\u0026 typeof $track.slick === \"function\") $track.slick(\"unslick\");\n          }\n        } catch {}\n        existing.remove();\n      }\n\n      const node = createBannerStripNode(slides);\n      const header = document.querySelector(\"header#header\");\n\n      if (header) {\n        header.insertAdjacentElement(\"beforebegin\", node);\n      } else {\n        document.body.insertAdjacentElement(\"afterbegin\", node);\n      }\n\n      // Ensure sticky header accounts for our banner height\n      const headerWrapperFallback = document.querySelector(\".js-header-wrapper\");\n      if (headerWrapperFallback) headerWrapperFallback.classList.add(\"active-service-banner\");\n\n      if (!_loggedRules.has(\"banner|injected-standalone\")) {\n        _loggedRules.add(\"banner|injected-standalone\");\n        console.log(\"[Promo] Banner injected as standalone (no native banner found)\");\n      }\n    }\n\n    function injectTIB() {\n      // On clearance/sale pages, only show TIB if the rule has specific\n      // mainCategories set — i.e. it's deliberately targeting those PLPs.\n      // If mainCategories is blank (sitewide promo), suppress TIB on clearance\n      // as normal. Non-clearance pages are unaffected.\n      if (!CONFIG.ENABLE_TIB || !isCategoryPage()) {\n        const existing = document.querySelector(`[data-ct-promo-id=\"${TIB_PROMO_ID}\"]`);\n        if (existing) existing.remove();\n        return;\n      }\n\n      const existing = document.querySelector(`[data-ct-promo-id=\"${TIB_PROMO_ID}\"]`);\n      const rule = findMatchingRule(\"\", \"tib\");\n\n      if (isClearanceContext()) {\n        const hasCategories = Array.isArray(rule?.targeting?.mainCategories) \u0026\u0026\n          rule.targeting.mainCategories.length \u003e 0 \u0026\u0026\n          !hasAllValue(rule.targeting.mainCategories);\n\n        // On clearance/sale pages, mainCategories must be populated AND must\n        // contain an exact match for the current page category.\n        // We cannot rely on matchesCategory() here because its keyword fuzzy\n        // logic (e.g. \"shirts\" keyword matching \"clr_shirts\") causes standard\n        // promo rules to bleed into clearance PLPs they were never meant for.\n        // Only rules that explicitly list the clearance category ID\n        // (e.g. \"clr_shirts\") should show TIB on that clearance PLP.\n        if (!hasCategories) {\n          if (existing) existing.remove();\n          return;\n        }\n\n        const currentCat = getPlpCategory();\n        const explicitMatch = rule.targeting.mainCategories.some(cat =\u003e\n          String(cat || \"\").toLowerCase() === currentCat\n        );\n        if (!explicitMatch) {\n          if (existing) existing.remove();\n          return;\n        }\n      }\n\n      if (!rule) {\n        if (existing) existing.remove();\n        return;\n      }\n\n      const payload = resolvePayloadFromRule(rule, \"\", \"tib\");\n      if (!payload?.tibMessage?.trim()) {\n        if (existing) existing.remove();\n        return;\n      }\n\n      const anchor = document.querySelector(CONFIG.SELECTORS.TIB_ANCHOR);\n      if (!anchor) return;\n\n      if (existing) {\n        const nextText = CONFIG.ALL_CAPS ? payload.tibMessage.toUpperCase() : payload.tibMessage;\n        // Compare against stored source text, not DOM text (Localise may have translated it)\n        const storedText = existing.getAttribute(\"data-ct-promo-text\") || String(existing.textContent || \"\").trim();\n        if (storedText === nextText) return;\n        existing.remove();\n      }\n\n      const node = createNode(payload.tibMessage, null, payload.codeToCopy, {\n        id: TIB_PROMO_ID,\n        extraClass: \"ct-promo-tib-message\",\n        skipBaseClass: true\n      });\n\n      if (!node) return;\n\n      anchor.insertAdjacentElement(\"afterend\", node);\n      setPromoActive();\n      observeForFade(node);\n    }\n\n    // ─── TILE HELPER ─────────────────────────────────────────────────────────\n    // Returns the best element to insert the promo callout *after* within a tile.\n    // If a multibuy element exists after the price anchor in DOM order, use that\n    // so the red box always appears last. Otherwise falls back to the price anchor.\n    function getPromoInsertionAnchor(tile, priceAnchor) {\n      const candidates = tile.querySelectorAll(CONFIG.SELECTORS.TILE_MULTIBUY);\n      for (const candidate of candidates) {\n        if (\n          candidate !== priceAnchor \u0026\u0026\n          !candidate.contains(priceAnchor) \u0026\u0026\n          (priceAnchor.compareDocumentPosition(candidate) \u0026 Node.DOCUMENT_POSITION_FOLLOWING)\n        ) {\n          return candidate;\n        }\n      }\n      return priceAnchor;\n    }\n\n    // ─── PDP HELPER ──────────────────────────────────────────────────────────\n    // On PDP there is no tile wrapper to scope to — multibuy elements are\n    // siblings (or sibling-descendants) of the price anchor in the flat DOM.\n    // Walk next siblings to find the last multibuy-related element before any\n    // unrelated content, then insert the red box after it.\n    function getPdpPromoInsertionAnchor(priceAnchor) {\n      const multibuySels = [\n        CONFIG.SELECTORS.PDP_MULTIBUY_TEXT,       // div.font__secondary.h5.uppercase.grey2.m-top-xs\n        ...CONFIG.SELECTORS.GLOBAL_MULTIBUY_TRACKERS  // tracker placeholders\n      ].join(\", \");\n\n      let best = priceAnchor;\n      let sibling = priceAnchor.nextElementSibling;\n\n      while (sibling) {\n        if (sibling.matches(multibuySels) || sibling.querySelector(multibuySels)) {\n          best = sibling;\n        }\n        sibling = sibling.nextElementSibling;\n      }\n\n      return best;\n    }\n    // ─────────────────────────────────────────────────────────────────────────\n\n    function injectPLP() {\n      if (!CONFIG.ENABLE_PLP || !isCategoryPage() || isClearanceContext()) {\n        document.querySelectorAll(`.promo-message[data-ct-promo-id=\"${PROMO_ID}\"]`).forEach(n =\u003e n.remove());\n        return;\n      }\n\n      document.querySelectorAll(CONFIG.SELECTORS.PLP_TILE).forEach(tile =\u003e {\n        const pid = getTilePid(tile);\n        const anchor = tile.querySelector(CONFIG.SELECTORS.PLP_ANCHOR);\n\n        if (!anchor) {\n          setTileMultibuyState(tile, false);\n          tile.removeAttribute(\"data-ct-winning-rule-id\");\n          tile.removeAttribute(\"data-ct-hide-multibuy\");\n          return;\n        }\n\n        const existing = tile.querySelector(`.promo-message[data-ct-promo-id=\"${PROMO_ID}\"]`);\n        const rule = findMatchingRule(pid, \"plp\");\n\n        if (!rule) {\n          setTileMultibuyState(tile, false);\n          tile.removeAttribute(\"data-ct-winning-rule-id\");\n          tile.removeAttribute(\"data-ct-hide-multibuy\");\n          if (existing) existing.remove();\n          return;\n        }\n\n        const payload = resolvePayloadFromRule(rule, pid, \"plp\");\n        if (!payload?.plpMessage?.trim()) {\n          setTileMultibuyState(tile, false);\n          tile.removeAttribute(\"data-ct-winning-rule-id\");\n          tile.removeAttribute(\"data-ct-hide-multibuy\");\n          if (existing) existing.remove();\n          return;\n        }\n\n        const shouldHideMultibuy = payload.hideMultibuy === true;\n        setTileMultibuyState(tile, shouldHideMultibuy);\n        tile.setAttribute(\"data-ct-winning-rule-id\", payload.rule?.ruleId || \"\");\n        tile.setAttribute(\"data-ct-hide-multibuy\", shouldHideMultibuy ? \"1\" : \"0\");\n\n        const nextText = CONFIG.ALL_CAPS ? payload.plpMessage.toUpperCase() : payload.plpMessage;\n\n        if (existing) {\n          // Compare against stored source text, not DOM text (Localise may have translated it)\n          const storedText = existing.getAttribute(\"data-ct-promo-text\") || String(existing.textContent || \"\").trim();\n          existing.setAttribute(\"data-ct-rule-id\", payload.rule?.ruleId || \"\");\n          existing.setAttribute(\"data-ct-hide-multibuy\", shouldHideMultibuy ? \"1\" : \"0\");\n          if (storedText === nextText) return;\n          existing.remove();\n        }\n\n        const productLinkEl = tile.querySelector(\"a.js-product-tile-image,a.product-tile__img-link,a.product-tile__name-link,a.js-product-tile-name\");\n        const href = productLinkEl?.getAttribute(\"href\") || null;\n        const node = createNode(payload.plpMessage, href, payload.codeToCopy);\n        if (!node) return;\n\n        node.setAttribute(\"data-ct-rule-id\", payload.rule?.ruleId || \"\");\n        node.setAttribute(\"data-ct-hide-multibuy\", shouldHideMultibuy ? \"1\" : \"0\");\n\n        // Insert after multibuy element if present, otherwise after price anchor\n        getPromoInsertionAnchor(tile, anchor).insertAdjacentElement(\"afterend\", node);\n\n        if (pid) tile.dataset.ctPromoPid = pid;\n        setPromoActive();\n        ensureStyleOnce(PRICE_DIFF_STYLE_ID, `.pt_product-details .price-diff{display:none!important;}`);\n        markTileHasPromoCallout(node);\n        ensureStyleOnce(NATIVE_PROMO_STYLE_ID, `.promo-message[data-ct-promo-id=\"${PROMO_ID}\"]+div,.promo-message[data-ct-promo-id=\"${TILE_PROMO_ID}\"]+div{display:none!important;}`);\n        observeForFade(node);\n      });\n    }\n\n    function injectPDP() {\n      if (!CONFIG.ENABLE_PDP || !isProductPage() || isClearanceContext()) {\n        const existing = document.querySelector(`.promo-message[data-ct-promo-id=\"${PROMO_ID}\"]`);\n        applyGlobalMultibuyState(false);\n        if (existing) existing.remove();\n        return;\n      }\n\n      const pid = normalizePid(getPdpProductId());\n      const rule = findMatchingRule(pid, \"pdp\");\n      const existing = document.querySelector(`.promo-message[data-ct-promo-id=\"${PROMO_ID}\"]`);\n\n      if (!rule) {\n        applyGlobalMultibuyState(false);\n        if (existing) existing.remove();\n        return;\n      }\n\n      const payload = resolvePayloadFromRule(rule, pid, \"pdp\");\n      if (!payload?.pdpMessage?.trim()) {\n        applyGlobalMultibuyState(false);\n        if (existing) existing.remove();\n        return;\n      }\n\n      applyGlobalMultibuyState(payload.hideMultibuy === true);\n\n      const anchor = firstExistingSelector([CONFIG.SELECTORS.PDP_ANCHOR, ...CONFIG.SELECTORS.PDP_ANCHOR_FALLBACKS]);\n      if (!anchor) return;\n\n      const nextText = CONFIG.ALL_CAPS ? payload.pdpMessage.toUpperCase() : payload.pdpMessage;\n\n      if (existing) {\n        // Compare against stored source text, not DOM text (Localise may have translated it)\n        const storedText = existing.getAttribute(\"data-ct-promo-text\") || String(existing.textContent || \"\").trim();\n        if (storedText === nextText) return;\n        existing.remove();\n      }\n\n      const node = createNode(payload.pdpMessage, null, payload.codeToCopy);\n      if (!node) return;\n\n      // Insert after multibuy element if present as a sibling, otherwise after price anchor\n      getPdpPromoInsertionAnchor(anchor).insertAdjacentElement(\"afterend\", node);\n      setPromoActive();\n      ensureStyleOnce(PRICE_DIFF_STYLE_ID, `.pt_product-details .price-diff{display:none!important;}`);\n      observeForFade(node);\n    }\n\n    function injectPDPProductTiles() {\n      if (!isProductPage() || isClearanceContext()) {\n        document.querySelectorAll(`.promo-message[data-ct-promo-id=\"${TILE_PROMO_ID}\"]`).forEach(n =\u003e n.remove());\n        return;\n      }\n\n      document.querySelectorAll(CONFIG.SELECTORS.PLP_TILE).forEach(tile =\u003e {\n        const pid = getTilePid(tile);\n        const anchor = tile.querySelector(CONFIG.SELECTORS.PLP_ANCHOR);\n\n        if (!pid || !anchor) {\n          setTileMultibuyState(tile, false);\n          tile.removeAttribute(\"data-ct-winning-rule-id\");\n          tile.removeAttribute(\"data-ct-hide-multibuy\");\n          return;\n        }\n\n        const existing = tile.querySelector(`.promo-message[data-ct-promo-id=\"${TILE_PROMO_ID}\"]`);\n        const rule = findMatchingRule(pid, \"pdp-tile\");\n\n        if (!rule) {\n          setTileMultibuyState(tile, false);\n          tile.removeAttribute(\"data-ct-winning-rule-id\");\n          tile.removeAttribute(\"data-ct-hide-multibuy\");\n          if (existing) existing.remove();\n          return;\n        }\n\n        const payload = resolvePayloadFromRule(rule, pid, \"plp\");\n        if (!payload?.plpMessage?.trim()) {\n          setTileMultibuyState(tile, false);\n          tile.removeAttribute(\"data-ct-winning-rule-id\");\n          tile.removeAttribute(\"data-ct-hide-multibuy\");\n          if (existing) existing.remove();\n          return;\n        }\n\n        const shouldHideMultibuy = payload.hideMultibuy === true;\n        setTileMultibuyState(tile, shouldHideMultibuy);\n        tile.setAttribute(\"data-ct-winning-rule-id\", payload.rule?.ruleId || \"\");\n        tile.setAttribute(\"data-ct-hide-multibuy\", shouldHideMultibuy ? \"1\" : \"0\");\n\n        const nextText = CONFIG.ALL_CAPS ? payload.plpMessage.toUpperCase() : payload.plpMessage;\n\n        if (existing) {\n          // Compare against stored source text, not DOM text (Localise may have translated it)\n          const storedText = existing.getAttribute(\"data-ct-promo-text\") || String(existing.textContent || \"\").trim();\n          existing.setAttribute(\"data-ct-rule-id\", payload.rule?.ruleId || \"\");\n          existing.setAttribute(\"data-ct-hide-multibuy\", shouldHideMultibuy ? \"1\" : \"0\");\n          if (storedText === nextText) return;\n          existing.remove();\n        }\n\n        const productLinkEl = tile.querySelector(\"a.js-product-tile-image,a.product-tile__img-link,a.product-tile__name-link,a.js-product-tile-name\");\n        const href = productLinkEl?.getAttribute(\"href\") || null;\n        const node = createNode(payload.plpMessage, href, payload.codeToCopy, {\n          id: TILE_PROMO_ID,\n          extraClass: \"ct-promo-tile-under-price\"\n        });\n\n        if (!node) return;\n\n        node.setAttribute(\"data-ct-rule-id\", payload.rule?.ruleId || \"\");\n        node.setAttribute(\"data-ct-hide-multibuy\", shouldHideMultibuy ? \"1\" : \"0\");\n\n        // Insert after multibuy element if present, otherwise after price anchor\n        getPromoInsertionAnchor(tile, anchor).insertAdjacentElement(\"afterend\", node);\n\n        if (pid) tile.dataset.ctPromoPid = pid;\n        setPromoActive();\n        ensureStyleOnce(PRICE_DIFF_STYLE_ID, `.pt_product-details .price-diff{display:none!important;}`);\n        markTileHasPromoCallout(node);\n        ensureStyleOnce(NATIVE_PROMO_STYLE_ID, `.promo-message[data-ct-promo-id=\"${PROMO_ID}\"]+div,.promo-message[data-ct-promo-id=\"${TILE_PROMO_ID}\"]+div{display:none!important;}`);\n        observeForFade(node);\n      });\n    }\n\n    function injectHPTiles() {\n      if (!isHomePage()) {\n        document.querySelectorAll(`.promo-message[data-ct-promo-id=\"${TILE_PROMO_ID}\"]`).forEach(n =\u003e {\n          if (n.closest(CONFIG.SELECTORS.HP_TILE_SELECTOR)) n.remove();\n        });\n        return;\n      }\n\n      document.querySelectorAll(CONFIG.SELECTORS.HP_TILE_SELECTOR).forEach(tile =\u003e {\n        const anchor = tile.querySelector(CONFIG.SELECTORS.HP_ANCHOR_SELECTOR);\n        const pid = normalizePid(tile.getAttribute(\"data-prod-id\") || tile.dataset.productId || \"\");\n\n        if (!pid || !anchor) {\n          setTileMultibuyState(tile, false);\n          tile.removeAttribute(\"data-ct-winning-rule-id\");\n          tile.removeAttribute(\"data-ct-hide-multibuy\");\n          return;\n        }\n\n        const existing = tile.querySelector(`.promo-message[data-ct-promo-id=\"${TILE_PROMO_ID}\"]`);\n        const rule = findMatchingRule(pid, \"hp\");\n\n        if (!rule) {\n          setTileMultibuyState(tile, false);\n          tile.removeAttribute(\"data-ct-winning-rule-id\");\n          tile.removeAttribute(\"data-ct-hide-multibuy\");\n          if (existing) existing.remove();\n          return;\n        }\n\n        const payload = resolvePayloadFromRule(rule, pid, \"hp\");\n        if (!payload?.plpMessage?.trim()) {\n          setTileMultibuyState(tile, false);\n          tile.removeAttribute(\"data-ct-winning-rule-id\");\n          tile.removeAttribute(\"data-ct-hide-multibuy\");\n          if (existing) existing.remove();\n          return;\n        }\n\n        const shouldHideMultibuy = payload.hideMultibuy === true;\n        setTileMultibuyState(tile, shouldHideMultibuy);\n        tile.setAttribute(\"data-ct-winning-rule-id\", payload.rule?.ruleId || \"\");\n        tile.setAttribute(\"data-ct-hide-multibuy\", shouldHideMultibuy ? \"1\" : \"0\");\n\n        const nextText = CONFIG.ALL_CAPS ? payload.plpMessage.toUpperCase() : payload.plpMessage;\n\n        if (existing) {\n          // Compare against stored source text, not DOM text (Localise may have translated it)\n          const storedText = existing.getAttribute(\"data-ct-promo-text\") || String(existing.textContent || \"\").trim();\n          existing.setAttribute(\"data-ct-rule-id\", payload.rule?.ruleId || \"\");\n          existing.setAttribute(\"data-ct-hide-multibuy\", shouldHideMultibuy ? \"1\" : \"0\");\n          if (storedText === nextText) return;\n          existing.remove();\n        }\n\n        const a = tile.querySelector(\"a.js-product-tile-image,a.product-tile__img-link,a.product-tile__name-link,a.js-product-tile-name\");\n        const node = createNode(payload.plpMessage, a?.getAttribute(\"href\") || null, payload.codeToCopy, {\n          id: TILE_PROMO_ID,\n          extraClass: \"ct-promo-tile-under-price\"\n        });\n\n        if (!node) return;\n\n        node.setAttribute(\"data-ct-rule-id\", payload.rule?.ruleId || \"\");\n        node.setAttribute(\"data-ct-hide-multibuy\", shouldHideMultibuy ? \"1\" : \"0\");\n\n        // Insert after multibuy element if present, otherwise after price anchor\n        getPromoInsertionAnchor(tile, anchor).insertAdjacentElement(\"afterend\", node);\n\n        setPromoActive();\n        ensureStyleOnce(PRICE_DIFF_STYLE_ID, `.pt_product-details .price-diff{display:none!important;}`);\n        markTileHasPromoCallout(node);\n        ensureStyleOnce(NATIVE_PROMO_STYLE_ID, `.promo-message[data-ct-promo-id=\"${PROMO_ID}\"]+div,.promo-message[data-ct-promo-id=\"${TILE_PROMO_ID}\"]+div{display:none!important;}`);\n        observeForFade(node);\n      });\n    }\n\n    function getWinningPlpPayload() {\n      const allPromos = document.querySelectorAll(\n        `.promo-message[data-ct-promo-id=\"${PROMO_ID}\"][data-ct-hide-multibuy],\n         .promo-message[data-ct-promo-id=\"${TILE_PROMO_ID}\"][data-ct-hide-multibuy]`\n      );\n\n      if (allPromos.length) {\n        const shouldHide = [...allPromos].some(n =\u003e n.getAttribute(\"data-ct-hide-multibuy\") === \"1\");\n        return {\n          rule: { ruleId: allPromos[0].getAttribute(\"data-ct-rule-id\") || \"unknown\" },\n          hideMultibuy: shouldHide\n        };\n      }\n\n      const tile = document.querySelector(`${CONFIG.SELECTORS.PLP_TILE}[data-ct-hide-multibuy=\"1\"]`);\n      if (tile) {\n        return {\n          rule: { ruleId: tile.getAttribute(\"data-ct-winning-rule-id\") || \"unknown\" },\n          hideMultibuy: true\n        };\n      }\n\n      return null;\n    }\n\n    function revealPending() {\n      document.querySelectorAll(\".promo-message:not(.promo-message--visible), .ct-promo-tib-message:not(.promo-message--visible)\").forEach(observeForFade);\n    }\n\n    async function runInjection() {\n      if (!window.utag_data || !window.utag_data.global) return;\n\n      if (String(getPlpCategory() || \"\").includes(\"evening\")) {\n        console.warn(\"[Promo] Evening category, exiting current run\");\n        return;\n      }\n\n      ensureStyles();\n      await loadRemoteRules();\n\n      if (!REMOTE.rules.length) {\n        applyGlobalMultibuyState(false);\n        document.querySelectorAll(`[${TILE_HIDE_MULTIBUY_ATTR}=\"1\"]`).forEach(node =\u003e node.removeAttribute(TILE_HIDE_MULTIBUY_ATTR));\n        return;\n      }\n\n      if (isCartPage()) {\n        const cartRule = findCartRule();\n        if (cartRule) {\n          injectCartCouponReplacement();\n        }\n        injectSitewideBannerStrip();\n        return;\n      }\n\n      injectSitewideBannerStrip();\n\n      if (isCategoryPage()) {\n        injectTIB();\n        injectPLP();\n\n        const plpPayload = getWinningPlpPayload();\n        applyGlobalMultibuyState(plpPayload?.hideMultibuy === true);\n\n        syncNativeMultibuyStates();\n        revealPending();\n        return;\n      }\n\n      if (isProductPage()) {\n        injectPDP();\n        injectPDPProductTiles();\n        setupPdpMultibuyObserver();\n        syncNativeMultibuyStates();\n      } else {\n        applyGlobalMultibuyState(false);\n      }\n\n      if (isHomePage()) injectHPTiles();\n      revealPending();\n    }\n\n    runInjection().catch(e =\u003e console.warn(\"[Promo] runInjection error\", e));\n\n    (function observeSitewideChanges() {\n      let t = null;\n\n      const isOurNode = (n) =\u003e {\n        if (!n || n.nodeType !== 1) return false;\n        // Is it one of our promo elements?\n        if (n.getAttribute \u0026\u0026 n.getAttribute(\"data-ct-promo-id\")) return true;\n        // Is it inside one of our promo elements?\n        if (n.closest \u0026\u0026 n.closest(\"[data-ct-promo-id]\")) return true;\n        // Does it contain one of our promo elements?\n        if (n.querySelector \u0026\u0026 n.querySelector(\"[data-ct-promo-id]\")) return true;\n        return false;\n      };\n\n      const run = (mutations) =\u003e {\n        // Ignore mutations caused by our own injected promo nodes.\n        // Bloomreach localisation/translate touches our nodes which triggers\n        // this observer, causing re-injection → infinite loop.\n        // We filter out any mutation where the target or changed nodes\n        // are our own elements, including parent elements that contain them.\n        //\n        // NOTE: mutations may be a MutationRecord array (from MutationObserver)\n        // or an Event object (from scroll/popstate/hashchange listeners).\n        // We only apply the filter when it's a real mutations array.\n        if (Array.isArray(mutations) \u0026\u0026 mutations.length \u0026\u0026 mutations.every(m =\u003e {\n          // Ignore if the mutated element is or contains our promo nodes\n          if (isOurNode(m.target)) return true;\n          // Ignore if added/removed nodes are or contain our promo nodes\n          const allNodes = [...(m.addedNodes || []), ...(m.removedNodes || [])];\n          if (allNodes.some(n =\u003e isOurNode(n))) return true;\n          // Ignore attribute changes on elements that contain our promo nodes\n          if (m.type === \"attributes\" \u0026\u0026 m.target.querySelector \u0026\u0026\n              m.target.querySelector(\"[data-ct-promo-id]\")) return true;\n          return false;\n        })) return;\n\n        clearTimeout(t);\n        t = setTimeout(() =\u003e {\n          runInjection().catch(e =\u003e console.warn(\"[Promo] global observer error\", e));\n        }, 120);\n      };\n\n      const mo = new MutationObserver(run);\n\n      mo.observe(document.body, {\n        childList: true,\n        subtree: true,\n        attributes: true,\n        attributeFilter: [\"class\", \"style\", \"data-prod-id\", \"data-product-id\", \"href\"]\n      });\n\n      window.addEventListener(\"scroll\", run, { passive: true });\n      window.addEventListener(\"popstate\", run);\n      window.addEventListener(\"hashchange\", run);\n    })();\n\n    if (document.readyState === \"complete\") revealPending();\n    else window.addEventListener(\"load\", revealPending, { once: true });\n\n    window.addEventListener(\"resize\", () =\u003e {\n      runInjection().catch(e =\u003e console.warn(\"[Promo] resize refresh error\", e));\n    }, { passive: true });\n\n    window.CTPromo = {\n      refresh(forceReloadRemote = false) {\n        if (forceReloadRemote) {\n          REMOTE.loaded = false;\n          REMOTE.rules = [];\n          REMOTE.inFlight = null;\n        }\n\n        document.querySelectorAll(`.promo-message[data-ct-promo-id=\"${PROMO_ID}\"]`).forEach(n =\u003e n.remove());\n        document.querySelectorAll(`.promo-message[data-ct-promo-id=\"${TILE_PROMO_ID}\"]`).forEach(n =\u003e n.remove());\n        document.querySelectorAll(`[data-ct-promo-id=\"${TIB_PROMO_ID}\"]`).forEach(n =\u003e n.remove());\n\n        applyGlobalMultibuyState(false);\n        document.querySelectorAll(`[${TILE_HIDE_MULTIBUY_ATTR}=\"1\"]`).forEach(node =\u003e node.removeAttribute(TILE_HIDE_MULTIBUY_ATTR));\n        destroyInjectedBannerStrip();\n\n        try { pdpMultibuyObserver?.disconnect(); } catch {}\n        pdpMultibuyObserver = null;\n\n        runInjection().catch(e =\u003e console.warn(\"[Promo] refresh error\", e));\n      }\n    };\n\n  } catch (e) {\n    console.warn(\"[Promo] Error\", e);\n  }\n})();\n\n","trigger":{"include_pages":[{"type":"any"}],"exclude_pages":null},"_id":"69eb3e44fdb3dcf3e41c6d07"},{"uses_overlay":false,"type":"js","parametrized_definition":"(() =\u003e {\n  \"use strict\";\n\n  const RUN_FLAG = \"__CT_BASKET_GUARANTEE_COPY_TEST_V3__\";\n  if (window[RUN_FLAG]) return;\n  window[RUN_FLAG] = true;\n\n  // ─────────────────────────────────────────────\n  // VARIANT COPY\n  // Edit these for each experiment variant\n  // ─────────────────────────────────────────────\n  const COPY = {\n    headline: \"6 Month Quality Guarantee\",\n    subcopy: \"We're so confident in Tyrwhitt quality, if you're not happy you can get a full refund up to 6 months later.\"\n  };\n\n  const STYLE_ID = \"ct-basket-guarantee-test-style-v3\";\n  const PROCESSED_FLAG = \"data-ct-guarantee-styled\";\n\n  function injectStyles() {\n    if (document.getElementById(STYLE_ID)) return;\n\n    const style = document.createElement(\"style\");\n    style.id = STYLE_ID;\n    style.textContent = `\n      .cart-summary__guarantee[${PROCESSED_FLAG}=\"true\"] {\n        background: #F5F5F5;\n        border-radius: 5px;\n        padding: 16px;\n        margin: 0 0 16px 0 !important;\n      }\n\n      .cart-summary__guarantee[${PROCESSED_FLAG}=\"true\"] .content-asset,\n      .cart-summary__guarantee[${PROCESSED_FLAG}=\"true\"] .content-asset \u003e div {\n        margin-bottom: 0 !important;\n      }\n\n      .cart-summary__guarantee[${PROCESSED_FLAG}=\"true\"] h4 {\n        margin: 0 0 6px 0 !important;\n      }\n\n      .cart-summary__guarantee[${PROCESSED_FLAG}=\"true\"] p {\n        margin: 0 !important;\n      }\n\n      .cart-summary__guarantee[${PROCESSED_FLAG}=\"true\"] img {\n        flex: 0 0 auto;\n      }\n    `;\n    document.head.appendChild(style);\n  }\n\n  function updateCopy(guarantee) {\n  const heading = guarantee.querySelector(\"h4\");\n  const paragraph = guarantee.querySelector(\"p\");\n  if (!heading || !paragraph) return;\n\n  heading.textContent = COPY.headline;\n\n  const tcLink = paragraph.querySelector(\"#js-bml-tc\");\n\n  if (!tcLink) {\n    paragraph.textContent = COPY.subcopy;\n    return;\n  }\n\n  const nodes = Array.from(paragraph.childNodes);\n  nodes.forEach((node) =\u003e {\n    if (node !== tcLink) paragraph.removeChild(node);\n  });\n\n  paragraph.insertBefore(document.createTextNode(COPY.subcopy + \" \"), tcLink);\n}\n\n  function processDesktop() {\n    const summary = document.querySelector(\".cart__summary\");\n    if (!summary) return;\n\n    const guarantee = summary.querySelector(\".cart-summary__guarantee\");\n    const cartActions = summary.querySelector(\".cart-actions\");\n    if (!guarantee || !cartActions || !cartActions.parentNode) return;\n\n    updateCopy(guarantee);\n\n    const correctParent = cartActions.parentNode;\n    const alreadyPlaced =\n      guarantee.parentNode === correctParent \u0026\u0026\n      guarantee.nextElementSibling === cartActions;\n\n    if (!alreadyPlaced) {\n      correctParent.insertBefore(guarantee, cartActions);\n    }\n\n    guarantee.setAttribute(PROCESSED_FLAG, \"true\");\n  }\n\n  function processMobile() {\n    const mobileSummary = document.querySelector(\".cart__summary--mobile\");\n    if (!mobileSummary) return;\n\n    const guarantee = mobileSummary.querySelector(\".cart-summary__guarantee\");\n    const checkoutForm = mobileSummary.querySelector(\"form.js-cart-action-checkout\");\n    if (!guarantee || !checkoutForm || !checkoutForm.parentNode) return;\n\n    updateCopy(guarantee);\n\n    const correctParent = checkoutForm.parentNode;\n    const alreadyPlaced =\n      guarantee.parentNode === correctParent \u0026\u0026\n      guarantee.nextElementSibling === checkoutForm;\n\n    if (!alreadyPlaced) {\n      correctParent.insertBefore(guarantee, checkoutForm);\n    }\n\n    guarantee.setAttribute(PROCESSED_FLAG, \"true\");\n  }\n\n  function run() {\n    injectStyles();\n    processDesktop();\n    processMobile();\n  }\n\n  let ticking = false;\n  function scheduleRun() {\n    if (ticking) return;\n    ticking = true;\n    requestAnimationFrame(() =\u003e {\n      ticking = false;\n      run();\n    });\n  }\n\n  function init() {\n    run();\n\n    const desktopRoot = document.querySelector(\".cart__summary\");\n    const mobileRoot = document.querySelector(\".cart__summary--mobile\");\n\n    if (desktopRoot) {\n      new MutationObserver(scheduleRun).observe(desktopRoot, {\n        childList: true,\n        subtree: true\n      });\n    }\n\n    if (mobileRoot) {\n      new MutationObserver(scheduleRun).observe(mobileRoot, {\n        childList: true,\n        subtree: true\n      });\n    }\n\n    window.addEventListener(\"resize\", scheduleRun, { passive: true });\n  }\n\n  if (document.readyState === \"loading\") {\n    document.addEventListener(\"DOMContentLoaded\", init);\n  } else {\n    init();\n  }\n})();","trigger":{"include_pages":[{"url":"/uk/cart","type":"contains"},{"url":"/us/cart","type":"contains"}],"exclude_pages":null},"_id":"6a7ed2dca93116c6d7adcdfe"},{"uses_overlay":false,"type":"js","parametrized_definition":"(function () {\r\n  \"use strict\";\r\n\r\n  var STYLE_ID = \"ct-online-exclusive-badge-style\";\r\n  var BADGE_ID = \"ct-online-exclusive-badge\";\r\n  var WRAP_SEL = \".pdpimage__wrap.js-main-carousel\";\r\n  var RUN_FLAG = \"data-ct-online-exclusive-init\";\r\n\r\n  var ELIGIBLE_IDS = {\r\n    SCS0110WHT: true,\r\n    CSH0028COB: true,\r\n    KNM0015MCA: true,\r\n    JEP0448OLV: true,\r\n    KNJ0444NKB: true,\r\n    CSH0028AQA: true,\r\n    SCS0117DRD: true,\r\n    CSH0031LLC: true,\r\n    KNT0018NAV: true,\r\n    JEP0453CRM: true,\r\n    JEP0458SLV: true,\r\n    SCS0115BLU: true,\r\n    JEP0409PET: true,\r\n    SCS0115PNK: true,\r\n    JEP0453BLK: true,\r\n    JEP0456NWT: true,\r\n    JEP0422WHT: true,\r\n    JEP0456FRG: true,\r\n    TRC0300STN: true,\r\n    JEP0398OLV: true,\r\n    CSH0018COB: true,\r\n    JEP0456TEL: true,\r\n    KNM0012GRY: true,\r\n    CSR0988OCE: true,\r\n    KNM0008SLV: true,\r\n    JEP0463PET: true,\r\n    KNT0012TPK: true,\r\n    KNM0015PNK: true,\r\n    SCS0113MBU: true,\r\n    JEP0459OLV: true,\r\n    JEP0399OLV: true,\r\n    JEP0455CHC: true,\r\n    CSH0031GLD: true,\r\n    JEP0447GRP: true,\r\n    SHC0258DCL: true,\r\n    JEP0453WNE: true,\r\n    SCS0107WHT: true,\r\n    ACB0239TAN: true,\r\n    KNM0009NKB: true,\r\n    ACB0227BRN: true,\r\n    JEP0442WNE: true,\r\n    CSR2125LLC: true,\r\n    KNJ0070OAT: true,\r\n    JEP0466SKY: true,\r\n    SCS0107NAV: true,\r\n    KNM0008OAT: true,\r\n    JEP0466WHT: true,\r\n    KNC0099NAV: true,\r\n    KNM0002GRY: true,\r\n    JEX0036NAV: true,\r\n    CSM0016NKB: true,\r\n    TRC0300NAV: true,\r\n    SHB0283CBR: true,\r\n    CSH0034PNK: true,\r\n    SHW0262DTN: true,\r\n    KNM0011OLV: true,\r\n    SHW0246CHA: true,\r\n    SHW0246SND: true,\r\n    JEX0034NAV: true,\r\n    SHB0272CHC: true,\r\n    KNC0099GRY: true,\r\n    ACB0225TAN: true,\r\n    SCS0108CEB: true,\r\n    CSM0032MBU: true,\r\n    CSM0032WHT: true,\r\n    ACB0224CHC: true,\r\n    OUR0035BLK: true,\r\n    TRH0049NKB: true,\r\n    JEY0003CHA: true,\r\n    CSM0032RED: true,\r\n    SHB0283NAV: true,\r\n    JEX0035NAV: true,\r\n    CSM0030MCA: true,\r\n    OUF0085NAV: true,\r\n    TRH0045TPE: true,\r\n    CSC0031SLG: true,\r\n    TRH0048OCE: true,\r\n    TRH0045SKY: true,\r\n    SHW0257CHC: true,\r\n    TRH0052TPE: true,\r\n    SCS0117LLC: true\r\n  };\r\n\r\n  function getProductId() {\r\n    try {\r\n      return window.utag_data \u0026\u0026\r\n        window.utag_data.products \u0026\u0026\r\n        window.utag_data.products[0] \u0026\u0026\r\n        window.utag_data.products[0].id\r\n        ? String(window.utag_data.products[0].id).toUpperCase().trim()\r\n        : \"\";\r\n    } catch (e) {\r\n      return \"\";\r\n    }\r\n  }\r\n\r\n  function shouldRun() {\r\n    try {\r\n      var ud = window.utag_data || {};\r\n      var pageType = ud.page \u0026\u0026 ud.page.type;\r\n      var country = ud.global \u0026\u0026 ud.global.sfcc_country;\r\n      var productId = getProductId();\r\n\r\n      return (\r\n        pageType === \"product\" \u0026\u0026\r\n        country === \"US\" \u0026\u0026\r\n        !!ELIGIBLE_IDS[productId]\r\n      );\r\n    } catch (e) {\r\n      return false;\r\n    }\r\n  }\r\n\r\n  function injectStyles() {\r\n    if (document.getElementById(STYLE_ID)) return;\r\n\r\n    var css = `\r\n      #${BADGE_ID} {\r\n        position: absolute;\r\n        z-index: 7;\r\n        display: inline-flex;\r\n        align-items: center;\r\n        gap: 6px;\r\n        background: #ffffff;\r\n        color: #2b2b2b;\r\n        border-radius: 5px;\r\n        padding: 6px 10px;\r\n        font-family: \"Futura\", \"Trebuchet MS\", Arial, sans-serif;\r\n        font-size: 1.2rem;\r\n        line-height: 1;\r\n        font-weight: 400;\r\n        white-space: nowrap;\r\n        box-shadow: 0 1px 2px rgba(0,0,0,0.08);\r\n        pointer-events: none;\r\n      }\r\n\r\n      #${BADGE_ID} .ct-online-exclusive-dot {\r\n        display: flex;\r\n        align-items: center;\r\n        justify-content: center;\r\n        width: 6px;\r\n        height: 6px;\r\n        flex: 0 0 6px;\r\n      }\r\n\r\n      #${BADGE_ID} .ct-online-exclusive-dot svg {\r\n        display: block;\r\n        width: 6px;\r\n        height: 6px;\r\n      }\r\n\r\n      #${BADGE_ID} .ct-online-exclusive-text {\r\n        display: block;\r\n        line-height: 1;\r\n      }\r\n\r\n      @media (min-width: 768px) {\r\n        #${BADGE_ID} {\r\n          top: 12px;\r\n          right: 12px;\r\n          left: auto;\r\n          bottom: auto;\r\n        }\r\n      }\r\n\r\n      @media (max-width: 767px) {\r\n        #${BADGE_ID} {\r\n          left: -8px;\r\n          right: auto;\r\n          bottom: 55px;\r\n          top: auto;\r\n          padding: 6px 10px 6px 14px;\r\n        }\r\n      }\r\n    `;\r\n\r\n    var style = document.createElement(\"style\");\r\n    style.id = STYLE_ID;\r\n    style.textContent = css;\r\n    document.head.appendChild(style);\r\n  }\r\n\r\n  function makeBadge() {\r\n    var badge = document.createElement(\"div\");\r\n    badge.id = BADGE_ID;\r\n    badge.setAttribute(\"aria-label\", \"Online Exclusive\");\r\n    badge.innerHTML = `\r\n      \u003cspan class=\"ct-online-exclusive-dot\" aria-hidden=\"true\"\u003e\r\n        \u003csvg width=\"6\" height=\"6\" viewBox=\"0 0 6 6\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"\u003e\r\n          \u003crect width=\"6\" height=\"6\" rx=\"3\" fill=\"#36817A\"\u003e\u003c/rect\u003e\r\n        \u003c/svg\u003e\r\n      \u003c/span\u003e\r\n      \u003cspan class=\"ct-online-exclusive-text\"\u003eOnline Exclusive\u003c/span\u003e\r\n    `;\r\n    return badge;\r\n  }\r\n\r\n  function ensurePositionContext(wrap) {\r\n    var computed = window.getComputedStyle(wrap);\r\n    if (computed.position === \"static\") {\r\n      wrap.style.position = \"relative\";\r\n    }\r\n  }\r\n\r\n  function addBadge(wrap) {\r\n    if (!wrap) return;\r\n\r\n    var existing = wrap.querySelector(\"#\" + BADGE_ID);\r\n    if (existing) return;\r\n\r\n    ensurePositionContext(wrap);\r\n    wrap.appendChild(makeBadge());\r\n  }\r\n\r\n  function removeBadge() {\r\n    var existing = document.getElementById(BADGE_ID);\r\n    if (existing \u0026\u0026 existing.parentNode) {\r\n      existing.parentNode.removeChild(existing);\r\n    }\r\n  }\r\n\r\n  function init(root) {\r\n    if (!shouldRun()) {\r\n      removeBadge();\r\n      return false;\r\n    }\r\n\r\n    var wrap = (root || document).querySelector(WRAP_SEL);\r\n    if (!wrap) return false;\r\n\r\n    wrap.setAttribute(RUN_FLAG, \"true\");\r\n    addBadge(wrap);\r\n    return true;\r\n  }\r\n\r\n  function watch() {\r\n    var obs = new MutationObserver(function () {\r\n      init();\r\n    });\r\n\r\n    obs.observe(document.documentElement, {\r\n      childList: true,\r\n      subtree: true\r\n    });\r\n  }\r\n\r\n  injectStyles();\r\n  init();\r\n  watch();\r\n})();","trigger":{"include_pages":[{"type":"any"}],"exclude_pages":null},"_id":"69e1d8d41620a75065c86547"},{"uses_overlay":false,"type":"js","parametrized_definition":"(function ($) {\n  // Gate: suits PDP on UK site only\n  if (!(window.utag_data \n        \u0026\u0026 utag_data.page \n        \u0026\u0026 utag_data.page.type === \"product set\" \n        \u0026\u0026 utag_data.global \n        \u0026\u0026 utag_data.global.sfcc_country === \"UK\")) {\n    return;\n  }\n\n  var DELAY = 20000; // set to 25000 for 25s live\n  var STYLE_ID = \"suitsModal-styles\";\n  var MODAL_ID = \"signupModal\";\n  var OVERLAY_ID = \"suitsOverlay\";\n\n  // ----- CSS -----\n  if (!document.getElementById(STYLE_ID)) {\n    var css = `\n      body.no-scroll-suits { overflow: hidden; }\n\n      .suitsOverlay {\n        position: fixed; inset: 0;\n        background-color: rgba(186,186,186,0.75);\n        z-index: 99; display: none; opacity: 0; transition: opacity 220ms ease;\n      }\n      .suitsOverlay.is-open { display: block; opacity: 1; }\n\n      .suitsModal {\n    \tdisplay:none;\n        z-index: 100; background-color: #fff; text-align: center;\n        width: 90%; max-width: 650px;\n        position: fixed; top: -100%; left: 50%; transform: translate(-50%, -50%);\n        box-shadow: 0 12px 30px rgba(0,0,0,0.25);\n      }\n\n      @media (max-width: 600px) {\n        .suitsModal {\n          width: 100%; max-width: none;\n          left: 0; transform: none;\n          bottom: -100%; top: auto;\n          border-radius: 12px 12px 0 0;\n        }\n        #image_container { display: none; }\n      }\n\n      .suitsModal .close-icon {\n        position: absolute;\n        top: 0px;\n        right: 0px;\n        background: none;\n        border: none;\n        cursor: pointer;\n      }\n\n      .suitsClose:focus {\n        outline: #001F49 solid 1px;\n      }\n\n      #content_container { display: flex; }\n      #image_container { flex: 1; height: 100%; }\n      #newsletter_info_container { flex: 1; }\n    `;\n    $(\"\u003cstyle\u003e\", { id: STYLE_ID, text: css }).appendTo(\"head\");\n  }\n\n  // ----- HTML -----\n  var overlayHtml = '\u003cdiv id=\"' + OVERLAY_ID + '\" class=\"suitsOverlay\" aria-hidden=\"true\"\u003e\u003c/div\u003e';\n\n  var modalHtml = `\n    \u003cdiv id=\"${MODAL_ID}\" class=\"suitsModal\" role=\"dialog\" aria-labelledby=\"dialog-title-SignUp\" aria-describedby=\"dialog-description-SignUp\" tabindex=\"-1\"\u003e\n      \u003cbutton aria-label=\"Close\" class=\"close-icon suitsClose\"\u003e\n        \u003csvg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\"\n             xmlns=\"http://www.w3.org/2000/svg\"\u003e\n          \u003cpath d=\"M2.99867 13L12.998 3\" stroke=\"#000\" stroke-width=\"1.5\"\n                stroke-linecap=\"round\" stroke-linejoin=\"round\"\u003e\u003c/path\u003e\n          \u003cpath d=\"M12.9987 13L2.998 3\" stroke=\"#000\" stroke-width=\"1.5\"\n                stroke-linecap=\"round\" stroke-linejoin=\"round\"\u003e\u003c/path\u003e\n        \u003c/svg\u003e\n      \u003c/button\u003e\n\n      \u003cdiv id=\"content_container\"\u003e\n        \u003cdiv id=\"image_container\"\u003e\n          \u003cimg src=\"/on/demandware.static/-/Library-Sites-CTShirtsSharedLibrary/default/va22a0af4c1de0ac91509302495404ab121b7b684/merchAssets/content/Suit-Pdp-Popup.jpg\"\n               alt=\"charlestyrwhitt\" style=\"width:100%;height:100%;object-fit:cover;\"\u003e\n        \u003c/div\u003e\n        \u003cdiv id=\"newsletter_info_container\"\u003e\n          \u003ch1 id=\"dialog-title-SignUp\" class=\"visually-hidden\"\u003eCharles Tyrwhitt Sign up modal\u003c/h1\u003e\n          \u003cp id=\"dialog-description-SignUp\" class=\"visually-hidden\"\u003e\u003c/p\u003e\n\n          \u003cdiv class=\"p-all-s wrapper body-wrapper h-100\" style=\"height:100%;display:flex;justify-content:center;align-items:center;\"\u003e\n            \u003csection\u003e\n              \u003cp class=\"m-ends-m h2\" style=\"font-size:1.6rem;\"\u003eNeed help finding your perfect size?\u003c/p\u003e\n              \u003cp class=\"m-ends-m h2 heading--center\" style=\"font-size:4.3rem;\"\u003e10% OFF SUITS\u003c/p\u003e\n              \u003cp class=\"pre-sub m-ends-m m-bottom-z p-sides-m\"\u003eGet measured and enjoy 10% off suits in-store.\u003c/p\u003e\n              \u003ch4 class=\"m-top-m\"\u003eUse code: \u003cstrong\u003eAPPT10\u003c/strong\u003e to claim \u003cstrong\u003ein-store\u003c/strong\u003e\u003c/h4\u003e\n              \u003ca id=\"suitsModalCTA\" href=\"https://www.charlestyrwhitt.com/uk/store-appointments.html#cm_sp=HP-HP6_book-an-appointment\"\n                 class=\"m-top-m button bg-grey1\" style=\"display:block;margin:auto;width:100%;\"\u003eBook Appointment\u003c/a\u003e\n            \u003c/section\u003e\n          \u003c/div\u003e\n        \u003c/div\u003e\n      \u003c/div\u003e\n    \u003c/div\u003e\n  `;\n\n  // ----- Functions -----\n  function openModal() {\n    if ($(\"#\" + MODAL_ID).length) return;\n    $(\"body\").append(overlayHtml + modalHtml).addClass(\"no-scroll-suits\");\n\n    var $modal = $(\"#\" + MODAL_ID);\n    var isMobile = window.matchMedia(\"(max-width: 600px)\").matches;\n\n    if (isMobile) {\n      $modal.animate({ bottom: \"0\" }, 400);\n    } else {\n      $modal.animate({ top: \"50%\" }, 400);\n    }\n\n    $(\"#\" + OVERLAY_ID).addClass(\"is-open\");\n    $modal.focus();\n  }\n\n  function closeModal() {\n    var $modal = $(\"#\" + MODAL_ID);\n    var isMobile = window.matchMedia(\"(max-width: 600px)\").matches;\n\n    if (isMobile) {\n      $modal.animate({ bottom: \"-100%\" }, 300, removeModal);\n    } else {\n      $modal.animate({ top: \"-100%\" }, 300, removeModal);\n    }\n  }\n\n  function removeModal() {\n    $(\"#\" + OVERLAY_ID).remove();\n    $(\"#\" + MODAL_ID).remove();\n    $(\"body\").removeClass(\"no-scroll-suits\");\n  }\n\n  // ----- Events -----\n  //setTimeout(openModal, DELAY);\n\n  $(document).on(\"click\", \"#\" + MODAL_ID + \" .suitsClose\", closeModal);\n  $(document).on(\"click\", \"#\" + OVERLAY_ID, closeModal);\n  $(document).on(\"keydown\", function (e) {\n    if (e.key === \"Escape\" \u0026\u0026 $(\"#\" + MODAL_ID).length) closeModal();\n  });\n\n  // CTA tracking\n  $(document).on(\"click\", \"#suitsModalCTA\", function () {\n    if (typeof exponea !== \"undefined\" \u0026\u0026 exponea.track) {\n      exponea.track(\"Clicked Suits Hesitation Modal\", {});\n    }\n  });\n\n})(jQuery);\n\n(function () {\n  const ID = \"ct-store-hero-msg\";\n  const STYLE_ID = ID + \"-styles\";\n\n  // ====== Gate ======\n  if (!(window.utag_data \n        \u0026\u0026 utag_data.page?.name === \"store-appointments\" \n        \u0026\u0026 utag_data.global?.sfcc_country === \"UK\")) {\n    return;\n  }\n\n  const target = document.querySelector(\".storeReopening .bg-hero\");\n  if (!target) return;\n\n  // Idempotent\n  document.getElementById(ID)?.remove();\n  document.getElementById(STYLE_ID)?.remove();\n\n  // Ensure target can anchor absolutely-positioned child\n  try {\n    const pos = getComputedStyle(target).position;\n    if (pos === \"static\") target.style.position = \"relative\";\n  } catch (e) {}\n\n  // ====== Styles ======\n  const css = `\n    #${ID} {\n      position: absolute;\n      inset: 0;\n      display: flex;\n      align-items: center;\n      justify-content: center;\n      padding: 24px;\n      text-align: center;\n      z-index: 2;\n    }\n    #${ID}::before {\n      content: \"\";\n      position: absolute;\n      inset: 0;\n      background: rgba(55,55,55,0.40);\n      z-index: -1;\n    }\n    #${ID} .${ID}-text {\n      color: #fff;\n      max-width: 1000px;\n      width: 100%;\n      margin: 0 auto;\n    }\n    #${ID} .${ID}-headline {\n      text-transform: uppercase;\n      font-size: 28px;\n      line-height: 1.1;\n      font-weight: 700;\n      letter-spacing: 0.2px;\n    }\n    #${ID} .${ID}-subline {\n      margin-top: 8px;\n      font-size: 20px;\n      font-weight: 400;\n    }\n    #${ID} .${ID}-subline strong { font-weight: 500; }\n    #${ID} .${ID}-disclaimer {\n      margin-top: 6px;\n      font-size: 14px;\n      font-weight: 300;\n      opacity: 0.9;\n    }\n    @media (min-width: 768px) {\n      #${ID} .${ID}-headline { font-size: 48px; }\n    }\n  `;\n  const style = document.createElement(\"style\");\n  style.id = STYLE_ID;\n  style.textContent = css;\n  document.head.appendChild(style);\n\n  // ====== Markup (no CTA) ======\n  const wrap = document.createElement(\"div\");\n  wrap.id = ID;\n  wrap.setAttribute(\"role\", \"region\");\n  wrap.setAttribute(\"aria-label\", \"In-store appointment message\");\n\n  wrap.innerHTML = `\n    \u003cdiv class=\"${ID}-text\"\u003e\n      \u003cdiv class=\"${ID}-headline\"\u003e10% Off Suits\u003c/div\u003e\n      \u003cdiv class=\"${ID}-subline\"\u003eBook an appointment and \u003cstrong\u003euse code APPT10 in store to claim\u003c/strong\u003e\u003c/div\u003e\n      \u003cdiv class=\"${ID}-disclaimer\"\u003eOffer code only valid in store\u003c/div\u003e\n    \u003c/div\u003e\n  `;\n\n  target.appendChild(wrap);\n})();\n\n","trigger":{"include_pages":[{"type":"any"}],"exclude_pages":null},"_id":"68bff31995524e9158b97c95"},{"uses_overlay":false,"type":"js","parametrized_definition":"(function () {\n  var SELECTORS = ['.js-service-banner-carousel', '.banner-strip--carousel'].join(',');\n\n  var reduceMotion = window.matchMedia \u0026\u0026\n    window.matchMedia('(prefers-reduced-motion: reduce)').matches;\n\n  var $carousels = $(SELECTORS);\n  if (!$carousels.length) return;\n\n  function enableAutoplay($el) {\n    try {\n      if (reduceMotion) {\n        // Do not autoplay for reduced motion users\n        $el.slick('slickSetOption', 'autoplay', false, true);\n        $el.slick('slickPause');\n        return;\n      }\n\n      // Enable autoplay\n      $el.slick('slickSetOption', 'autoplay', true, true);\n      $el.slick('slickPlay');\n\n      // Pause on hover + keyboard focus\n      $el\n        .off('.ctA11y')\n        .on('mouseenter.ctA11y focusin.ctA11y', function () {\n          try { $el.slick('slickPause'); } catch (e) {}\n        })\n        .on('mouseleave.ctA11y focusout.ctA11y', function () {\n          try { $el.slick('slickPlay'); } catch (e) {}\n        });\n\n    } catch (e) {}\n  }\n\n  $carousels.each(function () {\n    var $carousel = $(this);\n\n    if ($carousel.hasClass('slick-initialized')) {\n      enableAutoplay($carousel);\n    } else {\n      $carousel.on('init.ctAutoplayA11y', function () {\n        enableAutoplay($carousel);\n      });\n    }\n  });\n})();\n","trigger":{"include_pages":[{"type":"any"}],"exclude_pages":null},"_id":"69788d378d6d75a802a23b03"},{"uses_overlay":false,"type":"js","parametrized_definition":"(() =\u003e {\n  \"use strict\";\n\n  // PLP only\n  try {\n    const pageType = String(window.utag_data?.page?.type || \"\").toLowerCase();\n    if (!pageType.includes(\"category\")) return;\n  } catch {\n    return;\n  }\n\n  const RUN_FLAG = \"__CRO_SOCIALPROOF_SWATCH_OFFSET__\";\n  if (window[RUN_FLAG]) return;\n  window[RUN_FLAG] = true;\n\n  const SWATCH_MORE_SEL = \".js-more-swatches\";\n  const BADGE_SEL =\n    \".weblayer--box-notification.socialProof.socialProofTile.slide-in-init.slide-in\";\n\n  const STYLE_ID = \"cro-socialproof-styles\";\n\n  function ensureStyles() {\n    if (document.getElementById(STYLE_ID)) return;\n\n    const style = document.createElement(\"style\");\n    style.id = STYLE_ID;\n    style.textContent = `\n      .weblayer--box-notification {\n        max-width: 100% !important;\n      }\n\n      .cro-sp-swatch-open ${BADGE_SEL} {\n        bottom: 6.5rem !important;\n      }\n    `;\n    document.head.appendChild(style);\n  }\n\n  function isDisplayed(el) {\n    if (!el) return false;\n    return window.getComputedStyle(el).display !== \"none\";\n  }\n\n  function updateTile(tile) {\n    if (!tile) return;\n\n    const moreSwatches = tile.querySelector(SWATCH_MORE_SEL);\n    const swatchOpened = isDisplayed(moreSwatches);\n\n    tile.classList.toggle(\"cro-sp-swatch-open\", swatchOpened);\n  }\n\n  function updateAll() {\n    ensureStyles();\n    document\n      .querySelectorAll(\".product-tile, li, .product, .grid-item\")\n      .forEach(updateTile);\n  }\n\n  updateAll();\n\n  const mo = new MutationObserver(() =\u003e updateAll());\n  mo.observe(document.documentElement, {\n    subtree: true,\n    childList: true,\n    attributes: true,\n    attributeFilter: [\"style\", \"class\"]\n  });\n})();\n","trigger":{"include_pages":[{"type":"any"}],"exclude_pages":null},"_id":"6992eb007382ab5934687afb"},{"uses_overlay":false,"type":"js","parametrized_definition":"(function () {\n  try {\n    var pageType = utag_data?.page?.type || '';\n    var country  = utag_data?.global?.sfcc_country || '';\n\n    // Only run on US basket or checkout\n    if (country !== 'US') return;\n    if (pageType !== 'basket' \u0026\u0026 pageType !== 'checkout') return;\n\n    // Create banner\n    var banner = document.createElement('div');\n    banner.className = 'ct-tariff-banner';\n    banner.textContent = pageType === 'checkout'\n      ? 'Prices inclusive of duties and tariffs'\n      : 'Prices inclusive of duties and tariffs - no surprises at checkout.';\n\n    // Style it inline\n    banner.style.background = '#F5F5F5';\n    banner.style.textAlign = 'center';\n    banner.style.height = '40px';\n    banner.style.lineHeight = '40px';\n    banner.style.fontSize = '14px';\n    banner.style.color = '#333';\n    banner.style.fontWeight = '500';\n\n    // Insert after #header\n    var header = document.querySelector('#header');\n    if (header \u0026\u0026 header.parentNode) {\n      header.parentNode.insertBefore(banner, header.nextSibling);\n    }\n  } catch (e) {\n    console.error('[Tariff Banner Injection Error]', e);\n  }\n})();\n","trigger":{"include_pages":[{"url":"/us/cart","type":"contains"}],"exclude_pages":null},"_id":"6a7d82daf4d75ca00a2e6cae"},{"uses_overlay":false,"type":"js","parametrized_definition":"(function () {\r\n  const pageType = window.utag_data \u0026\u0026 window.utag_data.page \u0026\u0026 window.utag_data.page.type;\r\n  const pageCategory = window.utag_data \u0026\u0026 window.utag_data.page \u0026\u0026 window.utag_data.page.category;\r\n\r\n  // ── Homepage logic (unchanged) ──────────────────────────────────────────────\r\n  if (pageType === 'Homepage') {\r\n    const anchors = document.querySelectorAll('a');\r\n    const regex = /(HP-)(HeroCarousel[^\u0026]*)/;\r\n    const tilesToAssignSlots = [];\r\n    anchors.forEach(anchor =\u003e {\r\n      const href = anchor.getAttribute('href');\r\n      if (href \u0026\u0026 regex.test(href) \u0026\u0026 $(anchor).find('img:visible').length) {\r\n        tilesToAssignSlots.push($(anchor));\r\n      }\r\n    });\r\n    tilesToAssignSlots.forEach((tile, index) =\u003e {\r\n      var incrementedIndex = index + 1;\r\n      tile.closest('.fpHpCatImg').addClass('CarouselSlot' + index);\r\n      $('.CarouselSlot' + index).find('a:visible').each(function (linkIndex) {\r\n        const href = $(this).attr('href');\r\n        if (href \u0026\u0026 regex.test(href)) {\r\n          var url = new URL(href, window.location.origin);\r\n          url.searchParams.set(\"cm_sp\", \"HP-HeroCarousel_Tile\" + incrementedIndex + \"_Link\" + (linkIndex + 1));\r\n          $(this).attr('href', url.toString());\r\n        }\r\n      });\r\n    });\r\n    return;\r\n  }\r\n\r\n  // ── Category page logic ─────────────────────────────────────────────────────\r\n  if (pageType === 'category') {\r\n    const plpTiles = document.querySelectorAll('[id*=\"plptile\"]');\r\n    plpTiles.forEach(tile =\u003e {\r\n      const id = tile.id;\r\n      const parts = id.split('-');\r\n      const plptileIndex = parts.indexOf('plptile');\r\n      if (plptileIndex === -1) return;\r\n      const season = parts[0];\r\n      const cgid = parts.slice(plptileIndex + 2).join('-');\r\n      if (!season || !cgid) return;\r\n      const trackingParam = `PLP_${cgid}-${season}${pageCategory ? '_' + pageCategory : ''}`;\r\n      tile.querySelectorAll('a').forEach(anchor =\u003e {\r\n        const href = anchor.getAttribute('href');\r\n        if (!href) return;\r\n        try {\r\n          const url = new URL(href, window.location.origin);\r\n          url.searchParams.set('cm_sp', trackingParam);\r\n          anchor.setAttribute('href', url.toString());\r\n        } catch (e) {\r\n          // Skip any malformed hrefs\r\n        }\r\n      });\r\n    });\r\n    return;\r\n  }\r\n})();","trigger":{"include_pages":[{"type":"any"}],"exclude_pages":null},"_id":"68ae06e807dd0d4b9d47e54a"},{"uses_overlay":false,"type":"js","parametrized_definition":"(function() {\n  try {\n    if (utag_data?.page?.type === 'category') {\n      var style = document.createElement('style');\n      style.innerHTML = `\n        .product-tile__swatch-img {\n          border-radius: 0.5rem !important;\n        }\n      `;\n      document.head.appendChild(style);\n    }\n  } catch(e) {\n    console.warn(\"Swatch style injection failed\", e);\n  }\n})();\n","trigger":{"include_pages":[{"type":"any"}],"exclude_pages":null},"_id":"68af1636d151d5422a0efc15"},{"uses_overlay":false,"type":"js","parametrized_definition":"(function () {\r\n  try {\r\n    if (!(window.utag_data \u0026\u0026 utag_data.global \u0026\u0026 utag_data.page)) return;\r\n\r\n    const isStaffOrder = utag_data.global.campaign_site === \"stafforder\";\r\n    const isBasketPage = utag_data.page.type === \"basket\";\r\n\r\n    if (!isStaffOrder || !isBasketPage) return;\r\n\r\n    const STYLE_ID = \"ct-hide-special-offers\";\r\n\r\n    // Avoid duplicate injections\r\n    if (document.getElementById(STYLE_ID)) return;\r\n\r\n    const css = `\r\n      #special-offers {\r\n        display: none !important;\r\n      }\r\n    `;\r\n\r\n    const styleEl = document.createElement(\"style\");\r\n    styleEl.id = STYLE_ID;\r\n    styleEl.textContent = css;\r\n    document.head.appendChild(styleEl);\r\n\r\n    console.log(\"[ct-custom] Special offers hidden for stafforder basket page\");\r\n  } catch (e) {\r\n    console.error(\"[ct-custom] Error injecting style\", e);\r\n  }\r\n})();\r\n","trigger":{"include_pages":[{"type":"any"}],"exclude_pages":null},"_id":"68c40df86fa9646f78402586"},{"uses_overlay":false,"type":"js","parametrized_definition":"(function() {\n  try {\n    // ✅ Gate: Only run if consent group 3 is active\n    if (typeof OptanonActiveGroups === \"undefined\" || OptanonActiveGroups.indexOf(\"3\") === -1) return;\n\n    // ✅ Gate: Only run if utag_data exists\n    if (!(window.utag_data \u0026\u0026 utag_data.global \u0026\u0026 utag_data.page)) return;\n\n    // ✅ Gate: Only on US or UK sites\n    var country = utag_data.global.sfcc_country || \"\";\n    if ([\"US\", \"UK\"].indexOf(country) === -1) return;\n\n    // ✅ Gate: Only on confirmation pages\n    var pageName = (utag_data.page.name || \"\").toLowerCase();\n    if (pageName.indexOf(\"confirmation\") === -1) return;\n\n    // ---- Build items ----\n    var transformedItems = [];\n    if (Array.isArray(utag_data.bag)) {\n      for (let i = 0; i \u003c utag_data.bag.length; i++) {\n        var item = utag_data.bag[i];\n        transformedItems.push({\n          productId: item.id,\n          productVariantId: item.sku,\n          name: item.name,\n          category: item.category,\n          price: {\n            value: item.unit_price,\n            currency: utag_data.order.currency\n          }\n        });\n      }\n    }\n\n    // ---- Fire attentive event ----\n    if (window.attentive \u0026\u0026 attentive.analytics \u0026\u0026 typeof attentive.analytics.purchase === \"function\") {\n      attentive.analytics.purchase({\n        items: transformedItems,\n        order: {\n          orderId: utag_data.order.id\n        }\n      });\n    }\n  } catch (e) {\n    console.warn(\"[CT] attentive purchase script failed\", e);\n  }\n})();\n","trigger":{"include_pages":[{"type":"any"}],"exclude_pages":null},"_id":"68cc00f3e4f99619b6ef5d2e"},{"uses_overlay":false,"type":"html","parametrized_definition":"\u003cstyle\u003e\n    .internal_linking_container {\n        padding-top: 15px;\n    }\n\n    .il_title {\n        font-size: 1.6rem;\n        font-weight: 600;\n        margin-bottom: 5px;\n    }\n\u003c/style\u003e\n\n\n\u003cscript\u003e\n    $(function() {\n        var internalLinking = {\n\n            internalLinkingMessage: function() {\n\n                var SEF0349TPE_il_product_info = {\n                    id: 'TRT0439TPE',\n                    name: 'Linen Trousers - Taupe',\n                    nameUs: 'Linen Pants - Taupe',\n                    nameDe: 'Leinenhose - Taupe',\n                    nameEu: 'Linen Trousers - Taupe',\n                    nameAu: 'Linen Pants - Taupe',\n                    price: '£120',\n                    usPrice: '$200',\n                    dePrice: '€160',\n                    euPrice: '€160',\n                    auPrice: '$200',\n                    url: 'TRT0439TPE.html?pf=internal_tracking_linen'\n                }\n\n                var TRT0439TPESB_il_product_info = {\n                    id: 'SEF0349TPE',\n                    name: 'Linen Jacket - Taupe',\n                    nameUs: 'Linen Jacket - Taupe',\n                    nameDe: 'Leinen-Sakko - Taupe',\n                    nameEu: 'Linen Jacket - Taupe',\n                    nameAu: 'Linen Jacket - Taupe',\n                    price: '£279',\n                    usPrice: '$449',\n                    dePrice: '€369',\n                    euPrice: '€369',\n                    auPrice: '$499',\n                    url: 'SEF0349TPE.html?pf=internal_tracking_linen'\n                }\n\n\n                var SEF0349RYL_il_product_info = {\n                    id: 'TRT0439RYL',\n                    name: 'Linen Trousers - Royal Blue',\n                    nameUs: 'Linen Pants - Royal Blue',\n                    nameDe: 'Leinenhose - Königsblau',\n                    nameEu: 'Linen Trousers - Royal Blue',\n                    nameAu: 'Linen Pants - Royal Blue',\n                    price: '£120',\n                    usPrice: '$200',\n                    dePrice: '€160',\n                    euPrice: '€160',\n                    auPrice: '$200',\n                    url: 'TRT0439RYL.html?pf=internal_tracking_linen'\n                }\n\n                var TRT0439RYL_il_product_info = {\n                    id: 'SEF0349RYL',\n                    name: 'Linen Jacket - Royal Blue',\n                    nameUs: 'Linen Jacket - Royal Blue',\n                    nameDe: 'Leinen-Sakko - Königsblau',\n                    nameEu: 'Linen Jacket - Royal Blue',\n                    nameAu: 'Linen Jacket - Royal Blue',\n                    price: '£279',\n                    usPrice: '$449',\n                    dePrice: '€369',\n                    euPrice: '€369',\n                    auPrice: '$499',\n                    url: 'SEF0349RYL.html?pf=internal_tracking_linen'\n                }\n\n                //\n                var SEF0349OLV_il_product_info = {\n                    id: 'TRT0439OLV',\n                    name: 'Linen Trousers - Olive Green',\n                    nameUs: 'Linen Pants - Olive Green',\n                    nameDe: 'Leinenhose - Olivgrün',\n                    nameEu: 'Linen Trousers - Olive Green',\n                    nameAu: 'Linen Pants - Olive Green',\n                    price: '£120',\n                    usPrice: '$200',\n                    dePrice: '€160',\n                    euPrice: '€160',\n                    auPrice: '$200',\n                    url: 'TRT0439OLV.html?pf=internal_tracking_linen'\n                }\n\n                var TRT0439OLV_il_product_info = {\n                    id: 'SEF0349OLV',\n                    name: 'Linen Jacket - Olive Green',\n                    nameUs: 'Linen Jacket - Olive Green',\n                    nameDe: 'Leinen-Sakko - Olivgrün',\n                    nameEu: 'Linen Jacket - Olive Green',\n                    nameAu: 'Linen Jacket - Olive Green',\n                    price: '£249.95',\n                    usPrice: '$449',\n                    dePrice: '€349,95',\n                    euPrice: '€349,95',\n                    auPrice: '$499',\n                    url: 'SEF0349OLV.html?pf=internal_tracking_linen'\n                }\n\n                //\n                var SEF0349DNY_il_product_info = {\n                    id: 'TRT0439DNY',\n                    name: 'Linen Trousers - Dark Navy',\n                    nameUs: 'Linen Pants - Dark Navy',\n                    nameDe: 'Leinenhose - Tiefblau',\n                    nameEu: 'Linen Trousers - Dark Navy',\n                    nameAu: 'Linen Pants - Dark Navy',\n                    price: '£120',\n                    usPrice: '$200',\n                    dePrice: '€160',\n                    euPrice: '€160',\n                    auPrice: '$200',\n                    url: 'TRT0439DNY.html?pf=internal_tracking_linen'\n                }\n\n                var TRT0439DNY_il_product_info = {\n                    id: 'SEF0349DNY',\n                    name: 'Linen Jacket - Dark Navy',\n                    nameUs: 'Linen Jacket - Dark Navy',\n                    nameDe: 'Leinen-Sakko - Tiefblau',\n                    nameEu: 'Linen Jacket - Dark Navy',\n                    nameAu: 'Linen Jacket - Dark Navy',\n                    price: '£279.95',\n                    usPrice: '$449',\n                    dePrice: '€349,95',\n                    euPrice: '€349,95',\n                    auPrice: '$499',\n                    url: 'SEF0349DNY.html?pf=internal_tracking_linen'\n                }\n\n                //\n                var SEF0350TPE_il_product_info = {\n                    id: 'TRT0439TPE',\n                    name: 'Linen Trousers - Taupe',\n                    nameUs: 'Linen Pants - Taupe',\n                    nameDe: 'Leinenhose - Taupe',\n                    nameEu: 'Linen Trousers - Taupe',\n                    nameAu: 'Linen Pants - Taupe',\n                    price: '£120',\n                    usPrice: '$200',\n                    dePrice: '€160',\n                    euPrice: '€160',\n                    auPrice: '$200',\n                    url: 'TRT0439TPE.html?pf=internal_tracking_linen'\n                }\n\n                var TRT0439TPE_il_product_info = {\n                    id: 'SEF0350TPE',\n                    name: 'Double Breasted Linen Jacket - Taupe',\n                    nameUs: 'Double Breasted Linen Jacket - Taupe',\n                    nameDe: 'Leinen-Sakko - Taupe',\n                    nameEu: 'Double Breasted Linen Jacket - Taupe',\n                    nameAu: 'Double Breasted Linen Jacket - Taupe',\n                    price: '£279.95',\n                    usPrice: '$449',\n                    dePrice: '€349,95',\n                    euPrice: '€349,95',\n                    auPrice: '$499',\n                    url: 'SEF0350TPE.html?pf=internal_tracking_linen'\n                }\n\n\n                if (utag_data.products[0].id == 'SEF0349TPE') {\n                    var price = '';\n                    var name = '';\n                    var regionalTitle = '';\n                    if (utag_data.global.sfcc_country == 'UK') {\n                        price = SEF0349TPE_il_product_info.price\n                        name = SEF0349TPE_il_product_info.name\n                        regionalTitle = 'Shop the matching Trousers'\n                    } else if (utag_data.global.sfcc_country == 'US') {\n                        price = SEF0349TPE_il_product_info.usPrice\n                        name = SEF0349TPE_il_product_info.nameUs\n                        regionalTitle = 'Shop the matching Pants'\n                    } else if (utag_data.global.sfcc_country == 'DE') {\n                        price = SEF0349TPE_il_product_info.dePrice\n                        name = SEF0349TPE_il_product_info.nameDe\n                        regionalTitle = 'Entdecken Sie die passenden Hosen'\n                    } else if (utag_data.global.sfcc_country == 'EU') {\n                        price = SEF0349TPE_il_product_info.euPrice\n                        name = SEF0349TPE_il_product_info.nameEu\n                        regionalTitle = 'Shop the matching Trousers'\n                    } else if (utag_data.global.sfcc_country == 'AU') {\n                        price = SEF0349TPE_il_product_info.auPrice\n                        name = SEF0349TPE_il_product_info.nameAu\n                        regionalTitle = 'Shop the matching Pants'\n                    }\n\n\n                    var ilMessageJacketHTML =\n                        `\n               \u003cdiv class=\"internal_linking_container\"\u003e\n               \u003cdiv class=\"il_title\"\u003e` + regionalTitle + `\u003c/div\u003e\n               \u003cdiv class=\"il_message\"\u003e\u003ca href=` + SEF0349TPE_il_product_info.url + `\u003e` + name + ` - \u003cstrong\u003e` + price + `\u003c/strong\u003e\u003c/a\u003e\u003c/div\u003e\n               \u003c/div\u003e\n               `\n\n                    var ilJacketMessage = $(ilMessageJacketHTML);\n                    var pdpMainInfo = $('.pdp-main__more-info');\n                    ilJacketMessage.insertBefore(pdpMainInfo);\n\n                }\n\n                if (utag_data.products[0].id == 'TRT0439TPE') {\n                    var price = '';\n                    var name = '';\n                    var regionalTitle = '';\n                    if (utag_data.global.sfcc_country == 'UK') {\n                        price = TRT0439TPESB_il_product_info.price\n                        name = TRT0439TPESB_il_product_info.name\n                        regionalTitle = 'Shop the matching Jacket'\n                    } else if (utag_data.global.sfcc_country == 'US') {\n                        price = TRT0439TPESB_il_product_info.usPrice\n                        name = TRT0439TPESB_il_product_info.nameUs\n                        regionalTitle = 'Shop the matching Jacket'\n                    } else if (utag_data.global.sfcc_country == 'DE') {\n                        price = TRT0439TPESB_il_product_info.dePrice\n                        name = TRT0439TPESB_il_product_info.nameDe\n                        regionalTitle = 'Entdecken Sie die passende Jacke'\n                    } else if (utag_data.global.sfcc_country == 'EU') {\n                        price = TRT0439TPESB_il_product_info.euPrice\n                        name = TRT0439TPESB_il_product_info.nameEu\n                        regionalTitle = 'Shop the matching Jacket'\n                    } else if (utag_data.global.sfcc_country == 'AU') {\n                        price = TRT0439TPESB_il_product_info.auPrice\n                        name = TRT0439TPESB_il_product_info.nameAu\n                        regionalTitle = 'Shop the matching Jacket'\n                    }\n\n                    var ilMessageTrousersHTML =\n                        `\n                    \u003cdiv class=\"internal_linking_container\"\u003e\n                    \u003cdiv class=\"il_title\"\u003e` + regionalTitle + `\u003c/div\u003e\n                    \u003cdiv class=\"il_message\"\u003e\u003ca href=` + TRT0439TPESB_il_product_info.url + `\u003e` + name + ` - \u003cstrong\u003e` + price + `\u003c/strong\u003e\u003c/a\u003e\u003c/div\u003e\n                    \u003c/div\u003e\n                    `\n\n                    var ilTrousersMessage = $(ilMessageTrousersHTML);\n                    var pdpMainInfo = $('.pdp-main__more-info');\n                    ilTrousersMessage.insertBefore(pdpMainInfo);\n\n                }\n\n\n                ///\n                if (utag_data.products[0].id == 'SEF0350TPE') {\n\n                    var price = '';\n                    var name = '';\n                    var regionalTitle = '';\n                    if (utag_data.global.sfcc_country == 'UK') {\n                        price = SEF0350TPE_il_product_info.price\n                        name = SEF0350TPE_il_product_info.name\n                        regionalTitle = 'Shop the matching Trousers'\n                    } else if (utag_data.global.sfcc_country == 'US') {\n                        price = SEF0350TPE_il_product_info.usPrice\n                        name = SEF0350TPE_il_product_info.nameUs\n                        regionalTitle = 'Shop the matching Pants'\n                    } else if (utag_data.global.sfcc_country == 'DE') {\n                        price = SEF0350TPE_il_product_info.dePrice\n                        name = SEF0350TPE_il_product_info.nameDe\n                        regionalTitle = 'Entdecken Sie die passenden Hosen'\n                    } else if (utag_data.global.sfcc_country == 'EU') {\n                        price = SEF0350TPE_il_product_info.euPrice\n                        name = SEF0350TPE_il_product_info.nameEu\n                        regionalTitle = 'Shop the matching Trousers'\n                    } else if (utag_data.global.sfcc_country == 'AU') {\n                        price = SEF0350TPE_il_product_info.auPrice\n                        name = SEF0350TPE_il_product_info.nameAu\n                        regionalTitle = 'Shop the matching Pants'\n                    }\n\n\n                    var ilMessageJacketHTML =\n                        `\n  \u003cdiv class=\"internal_linking_container\"\u003e\n  \u003cdiv class=\"il_title\"\u003e` + regionalTitle + `\u003c/div\u003e\n  \u003cdiv class=\"il_message\"\u003e\u003ca href=` + SEF0350TPE_il_product_info.url + `\u003e` + name + ` - \u003cstrong\u003e` + price + `\u003c/strong\u003e\u003c/a\u003e\u003c/div\u003e\n  \u003c/div\u003e\n  `\n\n                    var ilJacketMessage = $(ilMessageJacketHTML);\n                    var pdpMainInfo = $('.pdp-main__more-info');\n                    ilJacketMessage.insertBefore(pdpMainInfo);\n\n                }\n\n                if (utag_data.products[0].id == 'TRT0439TPE') {\n                    var price = '';\n                    var name = '';\n                    var regionalTitle = '';\n                    if (utag_data.global.sfcc_country == 'UK') {\n                        price = TRT0439TPE_il_product_info.price\n                        name = TRT0439TPE_il_product_info.name\n                        regionalTitle = 'Shop the matching Jacket'\n                    } else if (utag_data.global.sfcc_country == 'US') {\n                        price = TRT0439TPE_il_product_info.usPrice\n                        name = TRT0439TPE_il_product_info.nameUs\n                        regionalTitle = 'Shop the matching Jacket'\n                    } else if (utag_data.global.sfcc_country == 'DE') {\n                        price = TRT0439TPE_il_product_info.dePrice\n                        name = TRT0439TPE_il_product_info.nameDe\n                        regionalTitle = 'Entdecken Sie die passende Jacke'\n                    } else if (utag_data.global.sfcc_country == 'EU') {\n                        price = TRT0439TPE_il_product_info.euPrice\n                        name = TRT0439TPE_il_product_info.nameEu\n                        regionalTitle = 'Shop the matching Jacket'\n                    } else if (utag_data.global.sfcc_country == 'AU') {\n                        price = TRT0439TPE_il_product_info.auPrice\n                        name = TRT0439TPE_il_product_info.nameAu\n                        regionalTitle = 'Shop the matching Jacket'\n                    }\n\n                    var ilMessageTrousersHTML =\n                        `\n  \u003cdiv class=\"internal_linking_container\"\u003e\n  \u003cdiv class=\"il_title\"\u003e` + regionalTitle + `\u003c/div\u003e\n  \u003cdiv class=\"il_message\"\u003e\u003ca href=` + TRT0439TPE_il_product_info.url + `\u003e` + name + ` - \u003cstrong\u003e` + price + `\u003c/strong\u003e\u003c/a\u003e\u003c/div\u003e\n  \u003c/div\u003e\n  `\n\n                    var ilTrousersMessage = $(ilMessageTrousersHTML);\n                    var pdpMainInfo = $('.pdp-main__more-info');\n                    ilTrousersMessage.insertBefore(pdpMainInfo);\n\n                }\n\n\n\n                ///\n\n\n\n                //   if (utag_data.products[0].id == 'SEF0349RYL') {\n\n                //     var price = '';\n                //     var name = '';\n                //     var regionalTitle = '';\n                //     if (utag_data.global.sfcc_country == 'UK') {\n                //       price = SEF0349RYL_il_product_info.price\n                //       name = SEF0349RYL_il_product_info.name\n                //       regionalTitle = 'Shop the matching Trousers'\n                //     }\n                //     else if (utag_data.global.sfcc_country == 'US') {\n                //       price = SEF0349RYL_il_product_info.usPrice\n                //       name = SEF0349RYL_il_product_info.nameUs\n                //       regionalTitle = 'Shop the matching Pants'\n                //     }\n                //     else if (utag_data.global.sfcc_country == 'DE') {\n                //       price = SEF0349RYL_il_product_info.dePrice\n                //       name = SEF0349RYL_il_product_info.nameDe\n                //       regionalTitle = 'Entdecken Sie die passenden Hosen'\n                //     }\n                //     else if (utag_data.global.sfcc_country == 'EU') {\n                //       price = SEF0349RYL_il_product_info.euPrice\n                //       name = SEF0349RYL_il_product_info.nameEu\n                //       regionalTitle = 'Shop the matching Trousers'\n                //     }\n                //     else if (utag_data.global.sfcc_country == 'AU') {\n                //       price = SEF0349RYL_il_product_info.auPrice\n                //       name = SEF0349RYL_il_product_info.nameAu\n                //       regionalTitle = 'Shop the matching Pants'\n                //     }\n\n\n                //     var ilMessageJacketHTML =\n                //       `\n                //             \u003cdiv class=\"internal_linking_container\"\u003e\n                //             \u003cdiv class=\"il_title\"\u003e`+ regionalTitle + `\u003c/div\u003e\n                //             \u003cdiv class=\"il_message\"\u003e\u003ca href=`+ SEF0349RYL_il_product_info.url + `\u003e` + name + ` - \u003cstrong\u003e` + price + `\u003c/strong\u003e\u003c/a\u003e\u003c/div\u003e\n                //             \u003c/div\u003e\n                //             `\n\n                //     var ilJacketMessage = $(ilMessageJacketHTML);\n                //     var pdpMainInfo = $('.pdp-main__more-info');\n                //     ilJacketMessage.insertBefore(pdpMainInfo);\n\n                //   }\n\n                //   if (utag_data.products[0].id == 'TRT0439RYL') {\n                //     var price = '';\n                //     var name = '';\n                //     var regionalTitle = '';\n                //     if (utag_data.global.sfcc_country == 'UK') {\n                //       price = TRT0439RYL_il_product_info.price\n                //       name = TRT0439RYL_il_product_info.name\n                //       regionalTitle = 'Shop the matching Jacket'\n                //     }\n                //     else if (utag_data.global.sfcc_country == 'US') {\n                //       price = TRT0439RYL_il_product_info.usPrice\n                //       name = TRT0439RYL_il_product_info.nameUs\n                //       regionalTitle = 'Shop the matching Jacket'\n                //     }\n                //     else if (utag_data.global.sfcc_country == 'DE') {\n                //       price = TRT0439RYL_il_product_info.dePrice\n                //       name = TRT0439RYL_il_product_info.nameDe\n                //       regionalTitle = 'Entdecken Sie die passende Jacke'\n                //     }\n                //     else if (utag_data.global.sfcc_country == 'EU') {\n                //       price = TRT0439RYL_il_product_info.euPrice\n                //       name = TRT0439RYL_il_product_info.nameEu\n                //       regionalTitle = 'Shop the matching Jacket'\n                //     }\n                //     else if (utag_data.global.sfcc_country == 'AU') {\n                //       price = TRT0439RYL_il_product_info.auPrice\n                //       name = TRT0439RYL_il_product_info.nameAu\n                //       regionalTitle = 'Shop the matching Jacket'\n                //     }\n\n                //     var ilMessageTrousersHTML =\n                //       `\n                //             \u003cdiv class=\"internal_linking_container\"\u003e\n                //             \u003cdiv class=\"il_title\"\u003e`+ regionalTitle + `\u003c/div\u003e\n                //             \u003cdiv class=\"il_message\"\u003e\u003ca href=`+ TRT0439RYL_il_product_info.url + `\u003e` + name + ` - \u003cstrong\u003e` + price + `\u003c/strong\u003e\u003c/a\u003e\u003c/div\u003e\n                //             \u003c/div\u003e\n                //             `\n\n                //     var ilTrousersMessage = $(ilMessageTrousersHTML);\n                //     var pdpMainInfo = $('.pdp-main__more-info');\n                //     ilTrousersMessage.insertBefore(pdpMainInfo);\n\n                //   }\n\n                //           if (utag_data.products[0].id == 'SEF0349OLV') {\n\n                //             var price = '';\n                //             var name = '';\n                //             var regionalTitle = '';\n                //             if (utag_data.global.sfcc_country == 'UK') {\n                //               price = SEF0349OLV_il_product_info.price\n                //               name = SEF0349OLV_il_product_info.name\n                //               regionalTitle = 'Shop the matching Trousers'\n                //             }\n                //             else if (utag_data.global.sfcc_country == 'US') {\n                //               price = SEF0349OLV_il_product_info.usPrice\n                //               name = SEF0349OLV_il_product_info.nameUs\n                //               regionalTitle = 'Shop the matching Pants'\n                //             }\n                //             else if (utag_data.global.sfcc_country == 'DE') {\n                //               price = SEF0349OLV_il_product_info.dePrice\n                //               name = SEF0349OLV_il_product_info.nameDe\n                //               regionalTitle = 'Entdecken Sie die passenden Hosen'\n                //             }\n                //             else if (utag_data.global.sfcc_country == 'EU') {\n                //               price = SEF0349OLV_il_product_info.euPrice\n                //               name = SEF0349OLV_il_product_info.nameEu\n                //               regionalTitle = 'Shop the matching Trousers'\n                //             }\n                //             else if (utag_data.global.sfcc_country == 'AU') {\n                //               price = SEF0349OLV_il_product_info.auPrice\n                //               name = SEF0349OLV_il_product_info.nameAu\n                //               regionalTitle = 'Shop the matching Pants'\n                //             }\n\n\n                //             var ilMessageJacketHTML =\n                //               `\n                //   \u003cdiv class=\"internal_linking_container\"\u003e\n                //   \u003cdiv class=\"il_title\"\u003e`+ regionalTitle + `\u003c/div\u003e\n                //   \u003cdiv class=\"il_message\"\u003e\u003ca href=`+ SEF0349OLV_il_product_info.url + `\u003e` + name + ` - \u003cstrong\u003e` + price + `\u003c/strong\u003e\u003c/a\u003e\u003c/div\u003e\n                //   \u003c/div\u003e\n                //   `\n\n                //             var ilJacketMessage = $(ilMessageJacketHTML);\n                //             var pdpMainInfo = $('.pdp-main__more-info');\n                //             ilJacketMessage.insertBefore(pdpMainInfo);\n\n                //           }\n\n                //           if (utag_data.products[0].id == 'TRT0439OLV') {\n                //             var price = '';\n                //             var name = '';\n                //             var regionalTitle = '';\n                //             if (utag_data.global.sfcc_country == 'UK') {\n                //               price = TRT0439OLV_il_product_info.price\n                //               name = TRT0439OLV_il_product_info.name\n                //               regionalTitle = 'Shop the matching Jacket'\n                //             }\n                //             else if (utag_data.global.sfcc_country == 'US') {\n                //               price = TRT0439OLV_il_product_info.usPrice\n                //               name = TRT0439OLV_il_product_info.nameUs\n                //               regionalTitle = 'Shop the matching Jacket'\n                //             }\n                //             else if (utag_data.global.sfcc_country == 'DE') {\n                //               price = TRT0439OLV_il_product_info.dePrice\n                //               name = TRT0439OLV_il_product_info.nameDe\n                //               regionalTitle = 'Entdecken Sie die passende Jacke'\n                //             }\n                //             else if (utag_data.global.sfcc_country == 'EU') {\n                //               price = TRT0439OLV_il_product_info.euPrice\n                //               name = TRT0439OLV_il_product_info.nameEu\n                //               regionalTitle = 'Shop the matching Jacket'\n                //             }\n                //             else if (utag_data.global.sfcc_country == 'AU') {\n                //               price = TRT0439OLV_il_product_info.auPrice\n                //               name = TRT0439OLV_il_product_info.nameAu\n                //               regionalTitle = 'Shop the matching Jacket'\n                //             }\n\n                //             var ilMessageTrousersHTML =\n                //               `\n                //   \u003cdiv class=\"internal_linking_container\"\u003e\n                //   \u003cdiv class=\"il_title\"\u003e`+ regionalTitle + `\u003c/div\u003e\n                //   \u003cdiv class=\"il_message\"\u003e\u003ca href=`+ TRT0439OLV_il_product_info.url + `\u003e` + name + ` - \u003cstrong\u003e` + price + `\u003c/strong\u003e\u003c/a\u003e\u003c/div\u003e\n                //   \u003c/div\u003e\n                //   `\n\n                //             var ilTrousersMessage = $(ilMessageTrousersHTML);\n                //             var pdpMainInfo = $('.pdp-main__more-info');\n                //             ilTrousersMessage.insertBefore(pdpMainInfo);\n\n                //           }\n\n\n                if (utag_data.products[0].id == 'SEF0349DNY') {\n\n                    var price = '';\n                    var name = '';\n                    var regionalTitle = '';\n                    if (utag_data.global.sfcc_country == 'UK') {\n                        price = SEF0349DNY_il_product_info.price\n                        name = SEF0349DNY_il_product_info.name\n                        regionalTitle = 'Shop the matching Trousers'\n                    } else if (utag_data.global.sfcc_country == 'US') {\n                        price = SEF0349DNY_il_product_info.usPrice\n                        name = SEF0349DNY_il_product_info.nameUs\n                        regionalTitle = 'Shop the matching Pants'\n                    } else if (utag_data.global.sfcc_country == 'DE') {\n                        price = SEF0349DNY_il_product_info.dePrice\n                        name = SEF0349DNY_il_product_info.nameDe\n                        regionalTitle = 'Entdecken Sie die passenden Hosen'\n                    } else if (utag_data.global.sfcc_country == 'EU') {\n                        price = SEF0349DNY_il_product_info.euPrice\n                        name = SEF0349DNY_il_product_info.nameEu\n                        regionalTitle = 'Shop the matching Trousers'\n                    } else if (utag_data.global.sfcc_country == 'AU') {\n                        price = SEF0349DNY_il_product_info.auPrice\n                        name = SEF0349DNY_il_product_info.nameAu\n                        regionalTitle = 'Shop the matching Pants'\n                    }\n\n\n                    var ilMessageJacketHTML =\n                        `\n  \u003cdiv class=\"internal_linking_container\"\u003e\n  \u003cdiv class=\"il_title\"\u003e` + regionalTitle + `\u003c/div\u003e\n  \u003cdiv class=\"il_message\"\u003e\u003ca href=` + SEF0349DNY_il_product_info.url + `\u003e` + name + ` - \u003cstrong\u003e` + price + `\u003c/strong\u003e\u003c/a\u003e\u003c/div\u003e\n  \u003c/div\u003e\n  `\n\n                    var ilJacketMessage = $(ilMessageJacketHTML);\n                    var pdpMainInfo = $('.pdp-main__more-info');\n                    ilJacketMessage.insertBefore(pdpMainInfo);\n\n                }\n\n                if (utag_data.products[0].id == 'TRT0439DNY') {\n                    var price = '';\n                    var name = '';\n                    var regionalTitle = '';\n                    if (utag_data.global.sfcc_country == 'UK') {\n                        price = TRT0439DNY_il_product_info.price\n                        name = TRT0439DNY_il_product_info.name\n                        regionalTitle = 'Shop the matching Jacket'\n                    } else if (utag_data.global.sfcc_country == 'US') {\n                        price = TRT0439DNY_il_product_info.usPrice\n                        name = TRT0439DNY_il_product_info.nameUs\n                        regionalTitle = 'Shop the matching Jacket'\n                    } else if (utag_data.global.sfcc_country == 'DE') {\n                        price = TRT0439DNY_il_product_info.dePrice\n                        name = TRT0439DNY_il_product_info.nameDe\n                        regionalTitle = 'Entdecken Sie die passende Jacke'\n                    } else if (utag_data.global.sfcc_country == 'EU') {\n                        price = TRT0439DNY_il_product_info.euPrice\n                        name = TRT0439DNY_il_product_info.nameEu\n                        regionalTitle = 'Shop the matching Jacket'\n                    } else if (utag_data.global.sfcc_country == 'AU') {\n                        price = TRT0439DNY_il_product_info.auPrice\n                        name = TRT0439DNY_il_product_info.nameAu\n                        regionalTitle = 'Shop the matching Jacket'\n                    }\n\n                    var ilMessageTrousersHTML =\n                        `\n  \u003cdiv class=\"internal_linking_container\"\u003e\n  \u003cdiv class=\"il_title\"\u003e` + regionalTitle + `\u003c/div\u003e\n  \u003cdiv class=\"il_message\"\u003e\u003ca href=` + TRT0439DNY_il_product_info.url + `\u003e` + name + ` - \u003cstrong\u003e` + price + `\u003c/strong\u003e\u003c/a\u003e\u003c/div\u003e\n  \u003c/div\u003e\n  `\n\n                    var ilTrousersMessage = $(ilMessageTrousersHTML);\n                    var pdpMainInfo = $('.pdp-main__more-info');\n                    ilTrousersMessage.insertBefore(pdpMainInfo);\n\n                }\n\n                //    if(utag_data.products[0].id == 'SEU0220FRG') {\n\n                //        var price = '';\n                //        var name = '';\n                //        var regionalTitle = '';\n\n                //        if (utag_data.global.sfcc_country == 'UK') {\n                //            price = SEU0220FRG_il_product_info.price\n                //            name = SEU0220FRG_il_product_info.name\n                //            regionalTitle = 'Shop the matching Trousers'\n                //        }\n                //        else if (utag_data.global.sfcc_country == 'US') {\n                //            price = SEU0220FRG_il_product_info.usPrice\n                //            name = SEU0220FRG_il_product_info.nameUs\n                //            regionalTitle = 'Shop the matching Pants'\n                //        }\n                //        else if (utag_data.global.sfcc_country == 'DE') {\n                //            price = SEU0220FRG_il_product_info.dePrice\n                //            name = SEU0220FRG_il_product_info.nameDe\n                //            regionalTitle = 'Entdecken Sie die passenden Hosen'\n                //        }\n                //        else if (utag_data.global.sfcc_country == 'EU') {\n                //            price = SEU0220FRG_il_product_info.euPrice\n                //            name = SEU0220FRG_il_product_info.nameEu\n                //            regionalTitle = 'Shop the matching Trousers'\n                //        }\n                //        else if (utag_data.global.sfcc_country == 'AU') {\n                //         price = SEU0220FRG_il_product_info.auPrice\n                //         name = SEU0220FRG_il_product_info.nameAu\n                //         regionalTitle = 'Shop the matching Pants'\n                //        }\n\n\n                //        var ilMessageJacketHTML =\n                //        `\n                //            \u003cdiv class=\"internal_linking_container\"\u003e\n                //            \u003cdiv class=\"il_title\"\u003e`+ regionalTitle +`\u003c/div\u003e\n                //            \u003cdiv class=\"il_message\"\u003e\u003ca href=`+ SEU0220FRG_il_product_info.url +`\u003e`+ name +` - \u003cstrong\u003e`+ price +`\u003c/strong\u003e\u003c/a\u003e\u003c/div\u003e\n                //            \u003c/div\u003e\n                //        `\n\n                //     var ilJacketMessage = $(ilMessageJacketHTML);\n                //     var pdpMainInfo = $('.pdp-main__more-info');\n                //     ilJacketMessage.insertBefore(pdpMainInfo);\n\n                // }\n\n                //    if(utag_data.products[0].id == 'TRT0430FRG') {\n\n                //        var price = '';\n                //        var name = '';\n                //        var regionalTitle = '';\n                //        if (utag_data.global.sfcc_country == 'UK') {\n                //           price = TRT0430FRG_il_product_info.price\n                //           name = TRT0430FRG_il_product_info.name\n                //           regionalTitle = 'Shop the matching Jacket'\n                //        }\n                //        else if (utag_data.global.sfcc_country == 'US') {\n                //           price = TRT0430FRG_il_product_info.usPrice\n                //           name = TRT0430FRG_il_product_info.nameUs\n                //           regionalTitle = 'Shop the matching Jacket'\n                //        }\n                //        else if (utag_data.global.sfcc_country == 'DE') {\n                //            price = TRT0430FRG_il_product_info.dePrice\n                //            name = TRT0430FRG_il_product_info.nameDe\n                //            regionalTitle = 'Entdecken Sie die passende Jacke'\n                //        }\n                //        else if (utag_data.global.sfcc_country == 'EU') {\n                //            price = TRT0430FRG_il_product_info.euPrice\n                //            name = TRT0430FRG_il_product_info.nameEu\n                //            regionalTitle = 'Shop the matching Jacket'\n                //        }\n                //        else if (utag_data.global.sfcc_country == 'AU') {\n                //         price = TRT0430FRG_il_product_info.auPrice\n                //         name = TRT0430FRG_il_product_info.nameAu\n                //         regionalTitle = 'Shop the matching Jacket'\n                //        }\n\n                //    var ilMessageTrousersHTML =\n                //    `\n                //    \u003cdiv class=\"internal_linking_container\"\u003e\n                //    \u003cdiv class=\"il_title\"\u003e`+ regionalTitle +`\u003c/div\u003e\n                //    \u003cdiv class=\"il_message\"\u003e\u003ca href=`+ TRT0430FRG_il_product_info.url +`\u003e`+ name +` - \u003cstrong\u003e`+ price +`\u003c/strong\u003e\u003c/a\u003e\u003c/div\u003e\n                //    \u003c/div\u003e\n                //    `\n\n                //    var ilTrousersMessage = $(ilMessageTrousersHTML);\n                //    var pdpMainInfo = $('.pdp-main__more-info');\n                //    ilTrousersMessage.insertBefore(pdpMainInfo);\n\n                //    }\n\n                //    if(utag_data.products[0].id == 'SEU0220NAV') {\n\n                //        var price = '';\n                //        var name = '';\n                //        var regionalTitle = '';\n                //        if (utag_data.global.sfcc_country == 'UK') {\n                //            price = SEU0220NAV_il_product_info.price\n                //            name = SEU0220NAV_il_product_info.name\n                //            regionalTitle = 'Shop the matching Trousers'\n                //        }\n                //        else if (utag_data.global.sfcc_country == 'US') {\n                //            price = SEU0220NAV_il_product_info.usPrice\n                //            name = SEU0220NAV_il_product_info.nameUs\n                //            regionalTitle = 'Shop the matching Pants'\n                //        }\n                //        else if (utag_data.global.sfcc_country == 'DE') {\n                //            price = SEU0220NAV_il_product_info.dePrice\n                //            name = SEU0220NAV_il_product_info.nameDe\n                //            regionalTitle = 'Entdecken Sie die passenden Hosen'\n                //        }\n                //        else if (utag_data.global.sfcc_country == 'EU') {\n                //            price = SEU0220NAV_il_product_info.euPrice\n                //            name = SEU0220NAV_il_product_info.nameEu\n                //            regionalTitle = 'Shop the matching Trousers'\n                //        }\n                //        else if (utag_data.global.sfcc_country == 'AU') {\n                //         price = SEU0220NAV_il_product_info.auPrice\n                //         name = SEU0220NAV_il_product_info.nameAu\n                //         regionalTitle = 'Shop the matching Pants'\n                //        }\n\n\n                //        var ilMessageJacketHTML =\n                //        `\n                //        \u003cdiv class=\"internal_linking_container\"\u003e\n                //        \u003cdiv class=\"il_title\"\u003e`+ regionalTitle +`\u003c/div\u003e\n                //        \u003cdiv class=\"il_message\"\u003e\u003ca href=`+ SEU0220NAV_il_product_info.url +`\u003e`+ name +` - \u003cstrong\u003e`+ price +`\u003c/strong\u003e\u003c/a\u003e\u003c/div\u003e\n                //        \u003c/div\u003e\n                //        `\n\n                //        var ilJacketMessage = $(ilMessageJacketHTML);\n                //        var pdpMainInfo = $('.pdp-main__more-info');\n                //        ilJacketMessage.insertBefore(pdpMainInfo);\n\n                //    }\n\n                //    if(utag_data.products[0].id == 'TRT0430DNY') {\n\n                //        var price = '';\n                //        var name = '';\n                //        var regionalTitle = '';\n                //        if (utag_data.global.sfcc_country == 'UK') {\n                //           price = TRT0430DNY_il_product_info.price\n                //           name = TRT0430DNY_il_product_info.name\n                //           regionalTitle = 'Shop the matching Jacket'\n                //        }\n                //        else if (utag_data.global.sfcc_country == 'US') {\n                //           price = TRT0430DNY_il_product_info.usPrice\n                //           name = TRT0430DNY_il_product_info.nameUs\n                //           regionalTitle = 'Shop the matching Jacket'\n                //        }\n                //        else if (utag_data.global.sfcc_country == 'DE') {\n                //         price = TRT0430DNY_il_product_info.dePrice\n                //         name = TRT0430DNY_il_product_info.nameDe\n                //         regionalTitle = 'Entdecken Sie die passende Jacke'\n                //        }\n                //        else if (utag_data.global.sfcc_country == 'EU') {\n                //            price = TRT0430DNY_il_product_info.euPrice\n                //            name = TRT0430DNY_il_product_info.nameEu\n                //            regionalTitle = 'Shop the matching Jacket'\n                //        }\n                //        else if (utag_data.global.sfcc_country == 'AU') {\n                //         price = TRT0430DNY_il_product_info.auPrice\n                //         name = TRT0430DNY_il_product_info.nameAu\n                //         regionalTitle = 'Shop the matching Jacket'\n                //        }\n\n                //    var ilMessageTrousersHTML =\n                //    `\n                //    \u003cdiv class=\"internal_linking_container\"\u003e\n                //    \u003cdiv class=\"il_title\"\u003e`+ regionalTitle +`\u003c/div\u003e\n                //    \u003cdiv class=\"il_message\"\u003e\u003ca href=`+ TRT0430DNY_il_product_info.url +`\u003e`+ name +` - \u003cstrong\u003e`+ price +`\u003c/strong\u003e\u003c/a\u003e\u003c/div\u003e\n                //    \u003c/div\u003e\n                //    `\n\n                //    var ilTrousersMessage = $(ilMessageTrousersHTML);\n                //    var pdpMainInfo = $('.pdp-main__more-info');\n                //    ilTrousersMessage.insertBefore(pdpMainInfo);\n\n                //    }\n            }\n        }\n\nif(utag_data.page.type == 'product'){\n\tif(utag_data.global.sfcc_country == 'UK' || utag_data.global.sfcc_country == 'US' || utag_data.global.sfcc_country == 'DE' || utag_data.global.sfcc_country == 'EU' || utag_data.global.sfcc_country == 'AU'){\n\t\t    internalLinking.internalLinkingMessage();\n\t}\n}\n\n});\n\n\n  \n\u003c/script\u003e","trigger":{"include_pages":[{"type":"any"}],"exclude_pages":null},"_id":"68cc18fdfbf6ffb814948944"},{"uses_overlay":false,"type":"js","parametrized_definition":"(() =\u003e {\n  try {\n    const SELECTOR = '.pt_product-search-noresult';\n    const EVENT_NAME = 'engagement.failedSearchRecs';\n\n    const isSearchPage =\n      window.utag_data \u0026\u0026\n      window.utag_data.page \u0026\u0026\n      window.utag_data.page.type \u0026\u0026\n      window.utag_data.page.type.toLowerCase() === 'search';\n\n    if (!isSearchPage) {\n      console.log(`[DBG] Not a search page (utag_data.page.type != 'search') — exiting`);\n      return;\n    }\n\n    const pushEvent = () =\u003e {\n      try {\n        window.dataLayer = window.dataLayer || [];\n        window.dataLayer.push({ event: EVENT_NAME });\n        console.log(`[DBG] Pushed ${EVENT_NAME} to dataLayer`);\n      } catch (err) {\n        console.error('[ERR] Failed to push event:', err);\n      }\n    };\n\n    const checkAndPush = () =\u003e {\n      const el = document.querySelector(SELECTOR);\n      if (el) {\n        console.log(`[DBG] ${SELECTOR} found – triggering ${EVENT_NAME}`);\n        pushEvent();\n        return true;\n      }\n      return false;\n    };\n\n    // Initial check\n    if (checkAndPush()) return;\n\n    // Observe DOM for delayed renders\n    const observer = new MutationObserver(() =\u003e {\n      if (checkAndPush()) observer.disconnect();\n    });\n\n    observer.observe(document.body, { childList: true, subtree: true });\n    console.log(`[DBG] Watching for ${SELECTOR} on search page to trigger ${EVENT_NAME}`);\n  } catch (err) {\n    console.error('[ERR] Failed search trigger script error:', err);\n  }\n})();\n","trigger":{"include_pages":[{"type":"any"}],"exclude_pages":null},"_id":"68e6391e41160b86f0aeca81"},{"uses_overlay":false,"type":"js","parametrized_definition":"/* cheq-inject.js\n   Single-file injector:\n   - adds CHEQ async invocation script into \u003chead\u003e\n   - adds CHEQ noscript iframe immediately after \u003cbody\u003e opening\n   Idempotent: will not duplicate elements if already present.\n*/\n\n(function () {\n  'use strict';\n  window.adobeDataLayer = window.adobeDataLayer || [];\n\n  const SCRIPT_SRC = 'https://euob.powerstarsbuilding.com/sxp/i/63dc751600d687b518fd822c927dbd13.js';\n  const SCRIPT_CLASS = 'ct_clicktrue_78534';\n  const DATA_CH = 'charlestyrwhitt';\n  const DATA_JSONP = 'onCheqResponse';\n\n  const NOSCRIPT_IFRAME_SRC = 'https://obseu.powerstarsbuilding.com/ns/63dc751600d687b518fd822c927dbd13.html?ch=charlestyrwhitt';\n  const NOSCRIPT_MARKER = 'cheq-noscript-marker';\n\n  function injectCheq() {\n    try {\n      // --- Inject script into head (idempotent) ---\n      if (!document.querySelector('script.' + SCRIPT_CLASS)) {\n        const s = document.createElement('script');\n        s.async = true;\n        s.src = SCRIPT_SRC;\n        s.className = SCRIPT_CLASS;\n        s.setAttribute('data-ch', DATA_CH);\n        s.setAttribute('datajsonp', DATA_JSONP);\n        // Give a clear attribute so it's easy to find later\n        s.setAttribute('data-cheq-injected', 'true');\n\n        // Prefer head, fallback to documentElement\n        const parent = document.head || document.getElementsByTagName('head')[0] || document.documentElement;\n        parent.insertBefore(s, parent.firstChild);\n        console.debug('[cheq-inject] injected CHEQ script into head');\n      } else {\n        console.debug('[cheq-inject] CHEQ script already present; skipping injection');\n      }\n\n      // --- Inject a noscript containing iframe immediately after body opening ---\n      // This will NOT help users who have JS disabled (because this code won't run),\n      // but keeps the noscript available to the DOM for tooling/maintenance when JS is enabled.\n      if (document.body) {\n        const existing = document.querySelector('noscript[data-cheq-noscript]');\n        if (!existing) {\n          const ns = document.createElement('noscript');\n          ns.setAttribute('data-cheq-noscript', 'true');\n          // Use innerHTML because noscript must contain the raw iframe markup\n          ns.innerHTML = '\u003ciframe src=\"' + NOSCRIPT_IFRAME_SRC + '\" width=\"0\" height=\"0\" style=\"display:none\"\u003e\u003c/iframe\u003e';\n          // Insert as first child of body (immediately after opening \u003cbody\u003e)\n          document.body.insertBefore(ns, document.body.firstChild);\n          console.debug('[cheq-inject] injected CHEQ noscript iframe into body (first child)');\n        } else {\n          console.debug('[cheq-inject] CHEQ noscript already present; skipping injection');\n        }\n      } else {\n        console.warn('[cheq-inject] document.body not available yet; noscript insertion deferred');\n      }\n    } catch (err) {\n      console.error('[cheq-inject] failed to inject CHEQ assets', err);\n    }\n  }\n\n  // If DOM is ready, run immediately; otherwise wait.\n  if (document.readyState === 'complete' || document.readyState === 'interactive') {\n    injectCheq();\n  } else {\n    document.addEventListener('DOMContentLoaded', injectCheq, { once: true });\n  }\n\n  // Expose small API for debugging / idempotent re-run if needed elsewhere\n  window.__cheqInject = {\n    inject: injectCheq,\n    scriptSelector: 'script.' + SCRIPT_CLASS + '[data-cheq-injected=\"true\"]',\n    noscriptSelector: 'noscript[data-cheq-noscript=\"true\"]'\n  };\n})();\n","trigger":{"include_pages":[{"type":"any"}],"exclude_pages":null},"_id":"68ed09ca8ebf29d016b5e7d7"},{"uses_overlay":false,"type":"js","parametrized_definition":"(() =\u003e {\n  try {\n    if (!window.utag_data || !utag_data.global) return;\n    if (utag_data.global.sfcc_country !== \"DE\") return;\n\n    const STYLE_ID = \"ct-trustbadge-style\";\n    document.getElementById(STYLE_ID)?.remove();\n\n    const isPDP = String(utag_data?.page?.type || \"\").includes(\"product\");\n    const trustBadgeZ = isPDP ? 5 : 1;\n\n    const css = `\n      [id^=\"trustbadge-container-\"] {\n        z-index: ${trustBadgeZ} !important;\n      }\n\n      /* Keep PLP filters above trustbadge on desktop */\n      @media only screen and (min-width: 1024px) {\n        .filtering-wrapper {\n          z-index: 2 !important;\n        }\n      }\n    `;\n\n    const style = document.createElement(\"style\");\n    style.id = STYLE_ID;\n    style.textContent = css.trim();\n    document.head.appendChild(style);\n\n    console.log(\n      \"[CT Style Inject] Trustbadge z-index applied\",\n      isPDP ? \"(PDP = 5)\" : \"(PLP = 1)\"\n    );\n  } catch (err) {\n    console.error(\"[CT Style Inject] Error:\", err);\n  }\n})();\n","trigger":{"include_pages":[{"url":"/de/","type":"contains"}],"exclude_pages":null},"_id":"68f0b39f7e7d419964cc6a7f"},{"uses_overlay":false,"type":"js","parametrized_definition":"(() =\u003e {\n  document.addEventListener(\"click\", e =\u003e {\n    const link = e.target.closest('a[class^=\"navigationLink-\"]');\n    if (!link) return;\n\n\n    const sub = (link.textContent || \"\").trim();\n\n    const top = link\n      .closest(\".navigation__li--main, .navigation-li-container\")\n      ?.querySelector(\".navigation__li-link--has-sub\")\n      ?.textContent.trim() || \"unknown\";\n\n    const val = `top nav|${top}|${sub}`;\n\n    console.log(\"Sending eVar10:\", val);\n\n    if (window.s) {\n      s.eVar10 = val;\n      s.linkTrackVars = \"eVar10\";\n      s.tl(true, \"o\", val);\n    }\n  });\n})();\n","trigger":{"include_pages":[{"type":"any"}],"exclude_pages":null},"_id":"69170d1d606537e7c64e31f0"},{"uses_overlay":false,"type":"js","parametrized_definition":"(function () {\r\n  \"use strict\";\r\n  \r\n  var UI_CONFIG = {\r\n  ENABLE_HOMEPAGE: false,\r\n  ENABLE_PLP: false,\r\n  ENABLE_PDP: false,\r\n  ENABLE_BASKET: true\r\n};\r\n\r\n  /* ========================================================================== *\r\n   *  MULTIBUY: Banner + Slideout + Recs + Price Formatting (PLP \u0026 PDP)\r\n   * ========================================================================== */\r\n\r\n  /* ========================== Debug Logger ========================== */\r\n  var TAG = \"[MB Debug]\";\r\n  function dbg() {\r\n    try { console.debug.apply(console, [TAG].concat([].slice.call(arguments))); } catch (e) {}\r\n  }\r\n\r\n  /* ====================== Data Layer / Page Flags =================== */\r\n  var utag_data_safe = window.utag_data || {};\r\n  var utag_page = utag_data_safe.page || {};\r\n  var utag_global = utag_data_safe.global || {};\r\n  var utag_prods = Array.isArray(utag_data_safe.products) ? utag_data_safe.products : [];\r\n\r\n  var PAGE_TYPE = String(utag_page.type || \"\").toLowerCase();\r\n\tvar IS_HOMEPAGE = PAGE_TYPE === \"homepage\";\r\n\tvar IS_PLP = PAGE_TYPE === \"category\";\r\n\tvar IS_PDP = PAGE_TYPE === \"product\";\r\n\tvar IS_BASKET = PAGE_TYPE === \"basket\";\r\n\tvar IS_MOBILE = utag_page.responsive_design_type === \"Mobile View\";\r\n\r\n  /* =============================== State =========================== */\r\n  var MB_INIT_DONE = false;\r\n  var RECHECK_TIMER = null;\r\n  var BASKET_OBSERVER = null;\r\n  var SYNC_DEBOUNCE = null;\r\n  var PRICE_OBSERVED = new WeakSet();\r\n  var KEYDOWN_BOUND = false;\r\n\r\n  /* =============================== Consts ========================== */\r\n  var RECO_CONTAINER_ID = \"popup-recommendations\";\r\n  var RECOMMENDATION_ID = \"69baa78568e692b40d7c836a\";\r\n\r\n  /* ======================= Site / Locale Helpers =================== */\r\n  var COUNTRY = (String(utag_global.sfcc_country || utag_global.country || \"\") || \"\").toUpperCase();\r\n  var SITE_LANG = utag_global.site_language || \"en_GB\";\r\n\r\n  function getLocaleSlug(langStr) {\r\n    if (!langStr) return \"en_GB\";\r\n    return String(langStr).replace(\"-\", \"_\");\r\n  }\r\n\r\n  function getSiteId(ctCountry) {\r\n    var map = {\r\n      UK: \"CTShirts-UK-Site\",\r\n      US: \"CTShirts-US-Site\",\r\n      DE: \"CTShirts-DE-Site\",\r\n      EU: \"CTShirts-EU-Site\",\r\n      FR: \"CTShirts-FR-Site\",\r\n      AU: \"CTShirts-AU-Site\",\r\n      NL: \"CTShirts-NL-Site\",\r\n      CH: \"CTShirts-CH-Site\",\r\n      CA: \"CTShirts-CA-Site\"\r\n    };\r\n    return map[ctCountry] || \"CTShirts-UK-Site\";\r\n  }\r\n  \r\n  function isSurfaceEnabled() {\r\n  if (IS_HOMEPAGE) return !!UI_CONFIG.ENABLE_HOMEPAGE;\r\n  if (IS_PLP) return !!UI_CONFIG.ENABLE_PLP;\r\n  if (IS_PDP) return !!UI_CONFIG.ENABLE_PDP;\r\n  if (IS_BASKET) return !!UI_CONFIG.ENABLE_BASKET;\r\n  return false;\r\n}\r\n\r\nfunction getLang() {\r\n  var lang = String(utag_global.site_language || SITE_LANG || \"\").toUpperCase();\r\n  if (lang.indexOf(\"DE\") \u003e -1) return \"DE\";\r\n  if (lang.indexOf(\"FR\") \u003e -1) return \"FR\";\r\n  return \"EN\";\r\n}\r\n\r\nvar LANG = getLang();\r\n\r\nvar COPY = {\r\n  EN: {\r\n    banner: 'Save Even More - \u003cspan class=\"bold m-sides-xs\"\u003eUp to 50% Off\u003c/span\u003e - \u003cspan class=\"underline m-sides-xs\"\u003eAdd now\u003c/span\u003e',\r\n    now: \"Now\",\r\n    was: \"was\",\r\n    noRecs: \"No recommendations available!\"\r\n  },\r\n  DE: {\r\n    banner: 'Noch mehr sparen - \u003cspan class=\"bold m-sides-xs\"\u003eBis zu 50 % Rabatt\u003c/span\u003e - \u003cspan class=\"underline m-sides-xs\"\u003eJetzt\u003c/span\u003e',\r\n    now: \"Jetzt\",\r\n    was: \"war\",\r\n    noRecs: \"Keine Empfehlungen verfügbar!\"\r\n  },\r\n  FR: {\r\n    banner: 'Économisez encore plus - \u003cspan class=\"bold m-sides-xs\"\u003eJusqu’à -50 %\u003c/span\u003e - \u003cspan class=\"underline m-sides-xs\"\u003eVoir l’offre\u003c/span\u003e',\r\n    now: \"\", // often omitted in FR\r\n    was: \"au lieu de\",\r\n    noRecs: \"Aucune recommandation disponible !\"\r\n  }\r\n};\r\n  \r\n  function getMultibuySlideoutCopy() {\r\n  var lang = String(utag_global.site_language || SITE_LANG || \"\").toUpperCase();\r\n\r\n  if (lang.indexOf(\"DE\") \u003e -1) {\r\n    return {\r\n      heading: \"Bis zu 50 % Rabatt\",\r\n      subheading: \"Sparen Sie mehr mit unseren beliebten Hemden.\"\r\n    };\r\n  }\r\n\r\n  if (lang.indexOf(\"FR\") \u003e -1) {\r\n    return {\r\n      heading: \"Jusqu’à 50 % de réduction\",\r\n      subheading: \"Faites encore plus d’économies avec nos chemises populaires.\"\r\n    };\r\n  }\r\n\r\n  return {\r\n    heading: \"Up to 50% Off\",\r\n    subheading: \"Save more with our popular shirts.\"\r\n  };\r\n}\r\n\r\nvar MB_SLIDEOUT_COPY = getMultibuySlideoutCopy();\r\n\r\n  function buildFrontEndProductUrl(item) {\r\n    if (!item) return \"#\";\r\n\r\n    var pid = item.id || item.item_id;\r\n    if (!pid) return \"#\";\r\n\r\n    var global = window.utag_data \u0026\u0026 window.utag_data.global ? window.utag_data.global : {};\r\n    var country = String(global.sfcc_country || COUNTRY || \"UK\").toLowerCase();\r\n    var siteLanguage = String(global.site_language || SITE_LANG || \"\").trim();\r\n\r\n    var pathParts = (window.location.pathname || \"\").split(\"/\").filter(Boolean);\r\n\r\n    var prefix = \"/\" + encodeURIComponent(country);\r\n\r\n    if (\r\n      pathParts.length \u003e= 2 \u0026\u0026\r\n      pathParts[0].toLowerCase() === country \u0026\u0026\r\n      siteLanguage \u0026\u0026\r\n      pathParts[1].toLowerCase() === siteLanguage.toLowerCase()\r\n    ) {\r\n      prefix += \"/\" + encodeURIComponent(siteLanguage);\r\n    }\r\n\r\n    return window.location.origin + prefix + \"/\" + encodeURIComponent(pid) + \".html?pf=5th_shirt_pop\";\r\n  }\r\n\r\n  var localeSlug = getLocaleSlug(SITE_LANG);\r\n  var siteId = getSiteId(COUNTRY || \"UK\");\r\n\r\n  /* =============================== Utils =========================== */\r\n  function escapeHtml(str) {\r\n    return String(str || \"\")\r\n      .replace(/\u0026/g, \"\u0026amp;\")\r\n      .replace(/\u003c/g, \"\u0026lt;\")\r\n      .replace(/\u003e/g, \"\u0026gt;\")\r\n      .replace(/\"/g, \"\u0026quot;\")\r\n      .replace(/'/g, \"\u0026#039;\");\r\n  }\r\n\r\n  function closest(el, selector) {\r\n    while (el \u0026\u0026 el.nodeType === 1) {\r\n      if (el.matches \u0026\u0026 el.matches(selector)) return el;\r\n      el = el.parentNode;\r\n    }\r\n    return null;\r\n  }\r\n\r\n  function normaliseImageV2(src) {\r\n    if (!src) return \"\";\r\n    var params = \"?sw=860\u0026sh=1080\u0026sm=fit\u0026q=55\";\r\n    var base = String(src).split(\"?\")[0];\r\n    if (/\\/dw\\/image\\/v2\\//.test(base)) return base + params;\r\n    if (/^https?:\\/\\//i.test(base)) {\r\n      try { base = new URL(base).pathname; }\r\n      catch (e) { base = base.replace(/^https?:\\/\\/[^/]+/, \"\"); }\r\n    }\r\n    if (base.indexOf(\"/on/demandware.static/\") === 0 || base.indexOf(\"/demandware.static/\") === 0) {\r\n      return \"https://www.charlestyrwhitt.com/dw/image/v2/AAWJ_PRD\" + base + params;\r\n    }\r\n    return base + params;\r\n  }\r\n\r\n  function cleanProductTitle(raw) {\r\n    var t = String(raw || \"\").trim();\r\n    if (!t) return \"\";\r\n\r\n    t = t.replace(/^(men’s|men's|mens)\\s+/i, \"\").trim();\r\n    t = t.replace(/^(women’s|women's|womens)\\s+/i, \"\").trim();\r\n    t = t.replace(/\\bPants\\b/gi, \"Trousers\");\r\n    t = t.replace(/charles\\s+tyrwhitt/ig, \"\").trim();\r\n\r\n    var sizeIdx = t.toLowerCase().indexOf(\" size\");\r\n    if (sizeIdx !== -1) {\r\n      t = t.slice(0, sizeIdx).trim();\r\n    }\r\n\r\n    t = t\r\n      .replace(/\\bSingle\\s+Cuff\\b/ig, \"\")\r\n      .replace(/\\bPure\\b/ig, \"\")\r\n      .replace(/\\s{2,}/g, \" \")\r\n      .replace(/\\s+[-–—]\\s*$/g, \"\")\r\n      .trim();\r\n\r\n    return t;\r\n  }\r\n  \r\n function injectPagingbarOverride() {\r\n  if (document.getElementById(\"mb-pagingbar-override\")) return;\r\n\r\n  var css =\r\n    \"@media (min-width: 1024px) and (hover: hover), \" +\r\n    \"(min-width: 1024px) and (-ms-high-contrast:active), \" +\r\n    \"(min-width: 1024px) and (-ms-high-contrast:none) {\" +\r\n      \".pagingbar-top {\" +\r\n        \"top: 11rem !important;\" +\r\n      \"}\" +\r\n    \"}\";\r\n\r\n  var style = document.createElement(\"style\");\r\n  style.id = \"mb-pagingbar-override\";\r\n  style.appendChild(document.createTextNode(css));\r\n  document.head.appendChild(style);\r\n}\r\n\r\nfunction removePagingbarOverride() {\r\n  var el = document.getElementById(\"mb-pagingbar-override\");\r\n  if (el \u0026\u0026 el.parentNode) el.parentNode.removeChild(el);\r\n}\r\n\r\n  function formatCollarType(raw) {\r\n    var t = String(raw || \"\").trim();\r\n    if (!t) return \"\";\r\n    return t\r\n      .replace(/[_-]+/g, \" \")\r\n      .replace(/\\s+/g, \" \")\r\n      .replace(/\\b\\w/g, function (m) { return m.toUpperCase(); });\r\n  }\r\n\r\n  function normalizeMoney(val) {\r\n    var v = String(val || \"\").trim();\r\n    if (!v) return \"\";\r\n    return v.replace(/\\s+/g, \"\").replace(/,/g, \"\").replace(/[^\\d.]/g, \"\").trim();\r\n  }\r\n\r\n  function parseMoneyNumber(val) {\r\n    var n = normalizeMoney(val);\r\n    return n ? parseFloat(n) : NaN;\r\n  }\r\n\r\n  function hasRealDiscount(was, now) {\r\n    var wasNum = parseMoneyNumber(was);\r\n    var nowNum = parseMoneyNumber(now);\r\n\r\n    if (!Number.isNaN(wasNum) \u0026\u0026 !Number.isNaN(nowNum)) {\r\n      return wasNum \u003e nowNum;\r\n    }\r\n\r\n    return !!was \u0026\u0026 !!now \u0026\u0026 String(was).trim() !== String(now).trim();\r\n  }\r\n\r\n  function parseMoney(text) {\r\n    if (!text) return null;\r\n    var m = String(text).replace(/\\s+/g, \" \").match(/([£$€])\\s*([\\d]+(?:[.,]\\d{1,2})?)/);\r\n    if (!m) return null;\r\n    var symbol = m[1];\r\n    var displayNum = m[2];\r\n    return { symbol: symbol, display: symbol + displayNum, value: displayNum.replace(\",\", \".\") };\r\n  }\r\n\r\n  function getVisNode(el) {\r\n    return el \u0026\u0026 (el.querySelector('[aria-hidden=\"true\"]') || el);\r\n  }\r\n\r\n  function removeRecoTile(tileEl) {\r\n    try {\r\n      if (tileEl \u0026\u0026 tileEl.parentNode) tileEl.parentNode.removeChild(tileEl);\r\n    } catch (e) {}\r\n  }\r\n\r\n  function watchRecoTileImage(imgEl, tileEl, onRemoved) {\r\n    if (!imgEl || !tileEl) return;\r\n\r\n    var src = (imgEl.getAttribute(\"src\") || \"\").trim();\r\n    if (!src) return;\r\n\r\n    var settled = false;\r\n\r\n    function removeTile() {\r\n      if (settled) return;\r\n      settled = true;\r\n      removeRecoTile(tileEl);\r\n      if (typeof onRemoved === \"function\") onRemoved();\r\n    }\r\n\r\n    function handleLoad() {\r\n      if (settled) return;\r\n\r\n      if (imgEl.naturalWidth \u003e 0 \u0026\u0026 imgEl.naturalHeight \u003e 0) {\r\n        settled = true;\r\n        tileEl.setAttribute(\"data-ct-image-ok\", \"true\");\r\n      } else {\r\n        removeTile();\r\n      }\r\n    }\r\n\r\n    function handleError() {\r\n      removeTile();\r\n    }\r\n\r\n    imgEl.addEventListener(\"load\", handleLoad, { once: true });\r\n    imgEl.addEventListener(\"error\", handleError, { once: true });\r\n\r\n    if (imgEl.complete) {\r\n      if (imgEl.naturalWidth \u003e 0 \u0026\u0026 imgEl.naturalHeight \u003e 0) {\r\n        settled = true;\r\n        tileEl.setAttribute(\"data-ct-image-ok\", \"true\");\r\n      } else {\r\n        removeTile();\r\n      }\r\n    }\r\n  }\r\n\r\n  function bindRecoHoverImageSwap(tileEl, imgEl, primarySrc, hoverSrc) {\r\n    if (!tileEl || !imgEl || !primarySrc || !hoverSrc) return;\r\n    if (IS_MOBILE) return;\r\n    if (tileEl.getAttribute(\"data-ct-hover-swap-bound\") === \"true\") return;\r\n\r\n    tileEl.setAttribute(\"data-ct-hover-swap-bound\", \"true\");\r\n\r\n    var preloaded = false;\r\n    var preloadImg = new Image();\r\n\r\n    function ensurePreloaded() {\r\n      if (preloaded) return;\r\n      preloadImg.src = hoverSrc;\r\n      preloaded = true;\r\n    }\r\n\r\n    function swapToHover() {\r\n      ensurePreloaded();\r\n      imgEl.src = hoverSrc;\r\n    }\r\n\r\n    function swapToPrimary() {\r\n      imgEl.src = primarySrc;\r\n    }\r\n\r\n    tileEl.addEventListener(\"mouseenter\", swapToHover);\r\n    tileEl.addEventListener(\"mouseleave\", swapToPrimary);\r\n    tileEl.addEventListener(\"focusin\", swapToHover);\r\n    tileEl.addEventListener(\"focusout\", swapToPrimary);\r\n  }\r\n\r\n  /* ==================== Rich Reco Tile Endpoint Cache ==================== */\r\n  var CT_RECO_PRODUCT_DATA = (function () {\r\n    var cache = new Map();\r\n    var inflight = new Map();\r\n    var queue = [];\r\n    var active = 0;\r\n\r\n    var MAX_CONCURRENCY = 4;\r\n    var TIMEOUT_MS = 8000;\r\n    var RETRIES = 1;\r\n\r\n    function buildUrl(prodId) {\r\n      return (\r\n        \"/on/demandware.store/Sites-\" +\r\n        siteId +\r\n        \"/\" +\r\n        localeSlug +\r\n        \"/Product-getProductTileData?productids=\" +\r\n        encodeURIComponent(prodId)\r\n      );\r\n    }\r\n\r\n    function ajaxText(url) {\r\n      if (window.jQuery \u0026\u0026 window.jQuery.ajax) {\r\n        return new Promise(function (resolve, reject) {\r\n          var done = false;\r\n          var timer = setTimeout(function () {\r\n            if (done) return;\r\n            done = true;\r\n            reject(new Error(\"timeout\"));\r\n          }, TIMEOUT_MS);\r\n\r\n          window.jQuery\r\n            .ajax({ url: url, method: \"GET\", dataType: \"text\" })\r\n            .done(function (txt) {\r\n              if (done) return;\r\n              done = true;\r\n              clearTimeout(timer);\r\n              resolve(txt);\r\n            })\r\n            .fail(function (xhr, status, err) {\r\n              if (done) return;\r\n              done = true;\r\n              clearTimeout(timer);\r\n              reject(new Error(status || err || \"ajax_fail\"));\r\n            });\r\n        });\r\n      }\r\n\r\n      return fetch(url, { credentials: \"include\" }).then(function (r) {\r\n        return r.text();\r\n      });\r\n    }\r\n\r\n    function fetchOne(prodId, attempt) {\r\n      attempt = attempt || 0;\r\n      var url = buildUrl(prodId);\r\n\r\n      return ajaxText(url)\r\n        .then(function (txt) {\r\n          var json = null;\r\n\r\n          try {\r\n            json = JSON.parse(txt);\r\n          } catch (e) {\r\n            if (attempt \u003c RETRIES) return fetchOne(prodId, attempt + 1);\r\n            return null;\r\n          }\r\n\r\n          if (!Array.isArray(json) || !json.length) return null;\r\n\r\n          var obj = null;\r\n          for (var i = 0; i \u003c json.length; i++) {\r\n            if (json[i] \u0026\u0026 String(json[i].productid).toUpperCase() === String(prodId).toUpperCase()) {\r\n              obj = json[i];\r\n              break;\r\n            }\r\n          }\r\n          if (!obj) obj = json[0];\r\n          if (!obj) return null;\r\n\r\n          return {\r\n            id: String(obj.productid || prodId).toUpperCase(),\r\n            name: String(obj.productname || \"\"),\r\n            collarType: String(obj.collarType || \"\"),\r\n            image0: String(obj.productimage0 || \"\"),\r\n            image1: String(obj.productimage1 || \"\"),\r\n            was: String(obj.wasprice || \"\"),\r\n            now: String(obj.nowprice || \"\"),\r\n            mbuy: String(obj.multibuyPrice || \"\")\r\n          };\r\n        })\r\n        .catch(function () {\r\n          if (attempt \u003c RETRIES) return fetchOne(prodId, attempt + 1);\r\n          return null;\r\n        });\r\n    }\r\n\r\n    function pump() {\r\n      while (active \u003c MAX_CONCURRENCY \u0026\u0026 queue.length) {\r\n        (function () {\r\n          var job = queue.shift();\r\n          active++;\r\n\r\n          fetchOne(job.id)\r\n            .then(function (res) {\r\n              if (res) cache.set(job.id, res);\r\n              job.resolve(res);\r\n            })\r\n            .catch(function () {\r\n              job.resolve(null);\r\n            })\r\n            .finally(function () {\r\n              active--;\r\n              pump();\r\n            });\r\n        })();\r\n      }\r\n    }\r\n\r\n    function get(prodId) {\r\n      if (!prodId) return Promise.resolve(null);\r\n\r\n      var id = String(prodId).toUpperCase();\r\n\r\n      if (cache.has(id)) return Promise.resolve(cache.get(id));\r\n      if (inflight.has(id)) return inflight.get(id);\r\n\r\n      var p = new Promise(function (resolve) {\r\n        queue.push({ id: id, resolve: resolve });\r\n        pump();\r\n      }).finally(function () {\r\n        inflight.delete(id);\r\n      });\r\n\r\n      inflight.set(id, p);\r\n      return p;\r\n    }\r\n\r\n    return { get: get };\r\n  })();\r\n\r\n  function applyEndpointDataToRecoTile(prodId, tileEl, onTileChange) {\r\n    if (!prodId || !tileEl) return Promise.resolve(false);\r\n\r\n    tileEl.setAttribute(\"data-ct-hydrating\", \"true\");\r\n\r\n    return CT_RECO_PRODUCT_DATA.get(prodId).then(function (p) {\r\n      if (!p) {\r\n        removeRecoTile(tileEl);\r\n        if (typeof onTileChange === \"function\") onTileChange();\r\n        return false;\r\n      }\r\n\r\n      var cleanTitle = cleanProductTitle(p.name || prodId);\r\n      var primaryImg = String(p.image0 || \"\").trim();\r\n      var hoverImg = String(p.image1 || \"\").trim();\r\n\r\n      if (!primaryImg) {\r\n        removeRecoTile(tileEl);\r\n        if (typeof onTileChange === \"function\") onTileChange();\r\n        return false;\r\n      }\r\n\r\n      var titleEl = tileEl.querySelector(\"[data-ct-title]\");\r\n      if (titleEl) titleEl.textContent = cleanTitle;\r\n\r\n      var linkEls = tileEl.querySelectorAll(\"a[href]\");\r\n      for (var l = 0; l \u003c linkEls.length; l++) {\r\n        linkEls[l].setAttribute(\"title\", cleanTitle);\r\n      }\r\n\r\n      var collarWrap = tileEl.querySelector(\"[data-ct-collar-wrap]\");\r\n      if (collarWrap) {\r\n        var rawCollar = String(p.collarType || \"\").trim().toLowerCase();\r\n        var excluded = [\"polo\", \"button_neck\", \"button neck\", \"trophy_neck\"];\r\n        var isExcluded = excluded.some(function (val) {\r\n          return rawCollar.indexOf(val) \u003e -1;\r\n        });\r\n\r\n        var collarEl = collarWrap.querySelector(\".product-tile__collar-label\");\r\n\r\n        if (isExcluded) {\r\n          collarWrap.classList.remove(\"ct-reco-has-collar\");\r\n          if (collarEl \u0026\u0026 collarEl.parentNode) collarEl.parentNode.removeChild(collarEl);\r\n        } else {\r\n          var collarText = formatCollarType(p.collarType);\r\n\r\n          if (collarText) {\r\n            if (!collarEl) {\r\n              collarEl = document.createElement(\"div\");\r\n              collarEl.className = \"bg-grey5 grey1 p m-all-z text-center capitalize product-tile__collar-label position-absolute col-100\";\r\n              collarWrap.appendChild(collarEl);\r\n            }\r\n            collarEl.textContent = collarText;\r\n            collarWrap.classList.add(\"ct-reco-has-collar\");\r\n          } else {\r\n            collarWrap.classList.remove(\"ct-reco-has-collar\");\r\n            if (collarEl \u0026\u0026 collarEl.parentNode) collarEl.parentNode.removeChild(collarEl);\r\n          }\r\n        }\r\n      }\r\n\r\n            var pricingWrap = tileEl.querySelector(\"[data-ct-price]\");\r\n      if (pricingWrap) {\r\n        var was = String(p.was || \"\").trim();\r\n        var now = String(p.now || \"\").trim();\r\n        var mbValue = String(p.mbuy || \"\").trim();\r\n\r\n        var nowNum = parseMoneyNumber(now);\r\n        var mbNum = parseMoneyNumber(mbValue);\r\n        var wasNum = parseMoneyNumber(was);\r\n\r\n        // ONLY show multibuy format if multibuy is genuinely cheaper than now\r\n        if (\r\n          mbValue \u0026\u0026\r\n          now \u0026\u0026\r\n          !Number.isNaN(nowNum) \u0026\u0026\r\n          !Number.isNaN(mbNum) \u0026\u0026\r\n          mbNum \u003c nowNum\r\n        ) {\r\n          pricingWrap.innerHTML =\r\n            '\u003cspan class=\"ct-reco-price-was\"\u003e' + escapeHtml(now) + '\u003c/span\u003e' +\r\n            '\u003cspan class=\"ct-reco-price-now red1\"\u003eNow ' + escapeHtml(mbValue) + \"\u003c/span\u003e\";\r\n        }\r\n\r\n        // Standard discount only if was is genuinely higher than now\r\n        else if (\r\n          now \u0026\u0026\r\n          was \u0026\u0026\r\n          !Number.isNaN(wasNum) \u0026\u0026\r\n          !Number.isNaN(nowNum) \u0026\u0026\r\n          wasNum \u003e nowNum\r\n        ) {\r\n          pricingWrap.innerHTML =\r\n            '\u003cspan class=\"ct-reco-price-was\"\u003e' + escapeHtml(was) + '\u003c/span\u003e' +\r\n            '\u003cspan class=\"ct-reco-price-now red1\"\u003eNow ' + escapeHtml(now) + \"\u003c/span\u003e\";\r\n        }\r\n\r\n        // Otherwise just show now\r\n        else if (now) {\r\n          pricingWrap.innerHTML =\r\n            '\u003cspan class=\"ct-reco-price-now\"\u003e' + escapeHtml(now) + \"\u003c/span\u003e\";\r\n        } else {\r\n          pricingWrap.innerHTML = \"\";\r\n        }\r\n      }\r\n\r\n      var mbEl = tileEl.querySelector(\"[data-ct-mb]\");\r\n      if (mbEl) {\r\n        mbEl.remove();\r\n      }\r\n\r\n      var imgEl = tileEl.querySelector(\"img[data-ct-img]\");\r\n      if (!imgEl) {\r\n        removeRecoTile(tileEl);\r\n        if (typeof onTileChange === \"function\") onTileChange();\r\n        return false;\r\n      }\r\n\r\n      imgEl.alt = cleanTitle;\r\n      imgEl.src = primaryImg;\r\n      imgEl.setAttribute(\"data-ct-primary-img\", primaryImg);\r\n\r\n      if (hoverImg) {\r\n        imgEl.setAttribute(\"data-ct-hover-img\", hoverImg);\r\n        bindRecoHoverImageSwap(tileEl, imgEl, primaryImg, hoverImg);\r\n      }\r\n\r\n      watchRecoTileImage(imgEl, tileEl, onTileChange);\r\n\r\n      tileEl.setAttribute(\"data-ct-hydrating\", \"false\");\r\n      tileEl.setAttribute(\"data-ct-endpoint-ready\", \"true\");\r\n\r\n      return true;\r\n    }).catch(function () {\r\n      removeRecoTile(tileEl);\r\n      if (typeof onTileChange === \"function\") onTileChange();\r\n      return false;\r\n    });\r\n  }\r\n\r\n  /* ========================= Threshold Checks ====================== */\r\n  function getMiniQty() {\r\n    var el = document.querySelector(\".minicart__quantity, .header__minicart-count, .js-minicart-quantity\");\r\n    var n = el ? parseInt((el.textContent || \"\").replace(/\\D+/g, \"\"), 10) || 0 : 0;\r\n    return n;\r\n  }\r\n\r\nvar SHIRT_MULTIBUY_THRESHOLD = 4;\r\n\r\nfunction isS101Promo(promo) {\r\n  if (!promo) return false;\r\n\r\n  if (typeof promo === \"string\") {\r\n    return promo.indexOf(\"S101\") \u003e -1;\r\n  }\r\n\r\n  if (Array.isArray(promo)) {\r\n    return promo.some(function (x) {\r\n      return String(x).indexOf(\"S101\") \u003e -1;\r\n    });\r\n  }\r\n\r\n  return false;\r\n}\r\n\r\nfunction getQualifyingMultibuyCount() {\r\n  var bag = Array.isArray(utag_data_safe.bag) ? utag_data_safe.bag : [];\r\n  var count = 0;\r\n\r\n  for (var i = 0; i \u003c bag.length; i++) {\r\n    var item = bag[i] || {};\r\n    var qty = Number(item.quantity) || 0;\r\n\r\n    if (isS101Promo(item.promotion_active)) {\r\n      count += qty;\r\n    }\r\n  }\r\n\r\n  return count;\r\n}\r\n\r\nfunction hasAchievedMultibuy() {\r\n  return getQualifyingMultibuyCount() \u003e= SHIRT_MULTIBUY_THRESHOLD;\r\n}\r\n\r\n  /* ========================== Eligibility Gates ==================== */\r\n  function dlContainsShirts() {\r\n    var cat = String(utag_page.category || utag_page.department || \"\");\r\n    var re = /(shirt|hemd|chemise|camicia|camisa)/i;\r\n    return re.test(cat);\r\n  }\r\nfunction isMultibuyUiActive() {\r\n  return isSurfaceEnabled() \u0026\u0026 hasAchievedMultibuy();\r\n}\r\n\r\nfunction dlProductEligibleS101() {\r\n  var p0 = utag_prods[0] || {};\r\n  return isS101Promo(p0.eligible_promotion);\r\n}\r\n\r\n function priceChangeAllowed() {\r\n  var active = isMultibuyUiActive();\r\n  return active \u0026\u0026 ((IS_PLP \u0026\u0026 dlContainsShirts()) || (IS_PDP \u0026\u0026 dlProductEligibleS101()));\r\n}\r\n\r\n  /* ============================ Styles ============================= */\r\n  function injectStyles() {\r\n    if (document.getElementById(\"mb-slideout-styles\")) return;\r\n\r\n    var css = \"\"\r\n      + \".mb-banner{background-color:#1e6a60;color:#fff;padding:0.6rem 1rem;font-size:1.4rem;font-family:Futura !important;width:100%;position:sticky;top:0;z-index:3;display:flex;align-items:center;justify-content:center;cursor:pointer;background-image:linear-gradient(90deg,#1e6a60 0%,#2d8a7d 50%,#1e6a60 100%);background-size:200% 100%;animation:mbshimmer 4s linear infinite;}\"\r\n      + \".mb-banner svg{width:24px;height:24px;margin-right:8px;flex:0 0 auto;display:block;overflow:visible;}\"\r\n      + \".mb-banner .bold{font-weight:700;}.mb-banner .underline{text-decoration:underline;}\"\r\n      + \"@keyframes mbshimmer{0%{background-position:-200% 0}100%{background-position:200% 0}}\"\r\n      + \"html.mb-no-scroll,body.mb-no-scroll{overflow:hidden;height:100%;}\"\r\n      + \".custom-slideout-overlay{position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(186,186,186,0.75);z-index:9998;display:none;}\"\r\n      + \".custom-slideout-overlay.show{display:block;}\"\r\n      + \".custom-slideout{position:fixed;background:#fff;box-shadow:-2px 0 8px rgba(0,0,0,.2);z-index:9999;display:flex;flex-direction:column;transition:transform .6s cubic-bezier(0.34,1.56,0.64,1);}\"\r\n      + (IS_MOBILE\r\n        ? \".custom-slideout{left:0;right:0;bottom:0;height:95%;transform:translateY(100%);border-top-left-radius:8px;border-top-right-radius:8px;}\"\r\n        : \".custom-slideout{top:0;right:0;height:100%;width:700px;transform:translateX(100%);}@media (max-width:1200px){.custom-slideout{width:40vw;}}@media (max-width:768px){.custom-slideout{width:100%;}}\")\r\n      + (IS_MOBILE ? \".custom-slideout.open{transform:translateY(0);}\" : \".custom-slideout.open{transform:translateX(0);}\")\r\n      + \".custom-slideout-header{background:#fff;height:0px;display:flex;align-items:center;position:relative;padding:0 20px;border-top-left-radius:8px;border-top-right-radius:8px;font-weight:600;}\"\r\n      + \".custom-slideout-header .title{font-size:3.2rem;color:#373737;position:absolute;left:20px;top:18px;}\"\r\n      + \".custom-slideout-close{position:absolute;right:15px;top:15px;width:32px;height:32px;background:transparent url(https://www.charlestyrwhitt.com/on/demandware.static/Sites-CTShirts-UK-Site/-/en_GB/v1754633077563/images/svg-icons/cross.svg) center no-repeat;background-size:18px;border:none;cursor:pointer;}\"\r\n      + \"#\" + RECO_CONTAINER_ID + \"{flex:1;overflow-y:auto;padding:16px;}\"\r\n      + \".reco-row{font-size:0;}\"\r\n      + \".reco-tile{display:inline-block;vertical-align:top;width:33.333%;padding:0 0.2rem 24px;box-sizing:border-box;}\"\r\n      + \"@media (max-width:1200px){.reco-tile{width:50%;}}@media (max-width:768px){.reco-tile{width:50%;}}\"\r\n      + \".savings-pill{display:inline-block;background:#116a60;color:#fff;font-size:13px;margin-top:5px;padding:4px 8px;font-weight:600;border-radius:6px;white-space:nowrap;opacity:0;transform:translateY(-5px);transition:opacity .4s ease,transform .4s ease;}\"\r\n      + \".savings-pill.show{opacity:1;transform:translateY(0);}\"\r\n      + \".reco-tile .product-tile__img-link{display:block;}\"\r\n      + \".reco-tile img{width:100%;display:block;background:#fff;object-fit:cover;}\"\r\n      + \".reco-tile .js-product-tile-name{font-family:Futura,sans-serif;font-size:1.6rem;color:#373737;margin:5px 0 2px;line-height:1.2;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;}\"\r\n      + \".reco-tile .tile__pricing{font-family:Futura,sans-serif;font-size:1.6rem;line-height:1.2;color:#373737;}\"\r\n      + \".reco-tile .product-tile__promo{font-family:Futura,sans-serif;font-size:1.4rem;line-height:1.2;margin-top:4px;}\"\r\n      + \".ct-reco-price-was{text-decoration:line-through;opacity:.7;margin-right:.4rem;color:#8a8a8a;}\"\r\n      + \".ct-reco-price-now{font-weight:600;color:#373737;}\"\r\n      + \".product-tile__collar-label{line-height:normal;font-size:1.2rem;padding:.3rem;border-radius:0 0 .5rem .5rem;z-index:1;bottom:-2.2rem;left:0;}\"\r\n      + \".reco-tile [data-ct-collar-wrap]{position:relative;display:block;}\"\r\n      + \".reco-tile .product-tile__collar-label{position:absolute;width:100%;}\"\r\n      + \".reco-tile [data-ct-collar-wrap].ct-reco-has-collar + .js-tile-info-wrapper\";\r\n\r\n    var style = document.createElement(\"style\");\r\n    style.id = \"mb-slideout-styles\";\r\n    style.appendChild(document.createTextNode(css));\r\n    document.head.appendChild(style);\r\n  }\r\n\r\n  function ensureBanner() {\r\n    if (document.querySelector(\".mb-banner\")) return;\r\n    var banner = document.createElement(\"div\");\r\n    banner.className = \"mb-banner\";\r\n    var svg = '' +\r\n      '\u003csvg width=\"24\" height=\"25\" viewBox=\"0 0 24 25\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\" aria-hidden=\"true\"\u003e' +\r\n      '\u003cg clip-path=\"url(#clip0_3002_3927)\"\u003e' +\r\n      '\u003cpath d=\"M22.3649 17.0517H21.6149C21.7499 11.8467 20.2499 8.54668 19.6949 7.70668C19.3349 7.21168 17.3624 6.60418 16.0799 6.34168L15.8549 6.28918L15.3749 4.54168C14.2937 4.0782 13.123 3.86047 11.9474 3.90418C10.7646 3.86086 9.5867 4.07851 8.49744 4.54168L8.02494 6.27418L7.79994 6.32668C6.50994 6.58918 4.53744 7.19668 4.18494 7.69168C3.70494 8.37418 2.37744 11.8617 2.37744 17.0292H1.62744C1.62744 11.7792 2.96244 8.12668 3.56994 7.27918C4.17744 6.43168 6.56994 5.84668 7.42494 5.65168L7.85994 4.06168L7.97994 3.98668C9.20405 3.37545 10.5663 3.09369 11.9324 3.16918C13.3013 3.08992 14.6669 3.37184 15.8924 3.98668L16.0199 4.06168L16.4549 5.65168C17.3324 5.84668 19.7174 6.44668 20.3024 7.27918C20.8874 8.11168 22.5374 11.6667 22.3649 17.0517Z\" fill=\"white\"/\u003e' +\r\n      '\u003cpath d=\"M15 10.8717L14.6625 10.2117C14.01 8.9517 12.75 7.1667 12 7.1667V6.4167C12.0375 6.4167 15.1875 6.1617 15.3525 4.2717L16.1025 4.3317C15.96 5.9667 14.385 6.6642 13.245 6.9642C13.9438 7.61614 14.5338 8.37575 14.9925 9.2142C15.2588 8.37374 15.4816 7.52011 15.66 6.6567L15.825 5.9067L16.5 6.0417L16.3275 6.7917C16.1206 7.96636 15.7809 9.11371 15.315 10.2117L15 10.8717Z\" fill=\"white\"/\u003e' +\r\n      '\u003cpath d=\"M12.0001 8.54669C12.2776 8.54669 12.5026 8.32171 12.5026 8.04419C12.5026 7.76666 12.2776 7.54169 12.0001 7.54169C11.7225 7.54169 11.4976 7.76666 11.4976 8.04419C11.4976 8.32171 11.7225 8.54669 12.0001 8.54669Z\" fill=\"white\"/\u003e' +\r\n      '\u003cpath d=\"M12.5025 11.5467C12.78 11.5467 13.005 11.3217 13.005 11.0442C13.005 10.7667 12.78 10.5417 12.5025 10.5417C12.225 10.5417 12 10.7667 12 11.0442C12 11.3217 12.225 11.5467 12.5025 11.5467Z\" fill=\"white\"/\u003e' +\r\n      '\u003cpath d=\"M12.5025 14.0442C12.78 14.0442 13.005 13.8192 13.005 13.5417C13.005 13.2642 12.78 13.0392 12.5025 13.0392C12.225 13.0392 12 13.2642 12 13.5417C12 13.8192 12.225 14.0442 12.5025 14.0442Z\" fill=\"white\"/\u003e' +\r\n      '\u003cpath d=\"M12.335 15.0417C12.52 15.0417 12.67 14.8917 12.67 14.7067C12.67 14.5217 12.52 14.3717 12.335 14.3717C12.15 14.3717 12 14.5217 12 14.7067C12 14.8917 12.15 15.0417 12.335 15.0417Z\" fill=\"white\"/\u003e' +\r\n      '\u003cpath d=\"M12.335 16.7117C12.52 16.7117 12.67 16.5617 12.67 16.3767C12.67 16.1917 12.52 16.0417 12.335 16.0417C12.15 16.0417 12 16.1917 12 16.3767C12 16.5617 12.15 16.7117 12.335 16.7117Z\" fill=\"white\"/\u003e' +\r\n      '\u003cpath d=\"M4.62744 19.0092C4.68361 18.0036 4.79628 17.0021 4.96494 16.0092C5.11494 15.0192 5.29494 14.0217 5.49744 13.0092C5.54244 14.0217 5.54994 15.0267 5.53494 16.0092C5.53641 17.0115 5.48132 18.0131 5.36994 19.0092H4.62744Z\" fill=\"white\"/\u003e' +\r\n      '\u003cpath d=\"M18.6299 19.0692C18.5185 18.0731 18.4634 17.0715 18.4649 16.0692C18.4649 15.0642 18.4649 14.0592 18.5024 13.0692C18.7049 14.0592 18.8849 15.0567 19.0349 16.0692C19.2035 17.0621 19.3162 18.0636 19.3724 19.0692H18.6299Z\" fill=\"white\"/\u003e' +\r\n      '\u003cpath d=\"M9.00006 10.8867L8.66256 10.2117C8.19007 9.15245 7.83058 8.04633 7.59006 6.91169L7.37256 6.04169L8.12256 5.84669L8.34756 6.70169C8.55452 7.5342 8.80486 8.35532 9.09756 9.16169C9.5494 8.32282 10.1345 7.56292 10.8301 6.91169C9.68256 6.61919 8.10006 5.92169 7.86756 4.30919L8.61756 4.20419C8.82756 6.16919 12.0001 6.41669 12.0001 6.41669V7.16669C11.1976 7.16669 9.96006 8.94419 9.33756 10.2042L9.00006 10.8867Z\" fill=\"white\"/\u003e' +\r\n      '\u003cpath d=\"M12.0001 9.9192C11.114 9.9061 10.2374 9.73334 9.4126 9.4092L9.6901 8.7117C10.4265 9.00129 11.2089 9.15625 12.0001 9.1692C12.7879 9.14788 13.5665 8.99319 14.3026 8.7117L14.5651 9.4167C13.7434 9.72364 12.8769 9.89341 12.0001 9.9192Z\" fill=\"white\"/\u003e' +\r\n      '\u003cpath d=\"M11.3774 9.4317H10.6274V20.0367H11.3774V9.4317Z\" fill=\"white\"/\u003e' +\r\n      \"\u003c/g\u003e\" +\r\n      '\u003cdefs\u003e\u003cclipPath id=\"clip0_3002_3927\"\u003e\u003crect width=\"24\" height=\"24\" fill=\"white\" transform=\"translate(0 0.041687)\"/\u003e\u003c/clipPath\u003e\u003c/defs\u003e' +\r\n      \"\u003c/svg\u003e\";\r\n    var text = COPY[LANG].banner;\r\n    banner.innerHTML = svg + text;\r\n    (document.querySelector(\"#header\") || document.body).appendChild(banner);\r\n  }\r\n\r\n  function removeBanner() {\r\n    var b = document.querySelector(\".mb-banner\");\r\n    if (b \u0026\u0026 b.parentNode) b.parentNode.removeChild(b);\r\n  }\r\n\r\n\r\n  /* ========================= Slideout / Recs ======================= */\r\n  function renderRecommendationTile(item) {\r\n    var extraClasses = IS_BASKET ? \" \" : \"\";\r\n    var url = buildFrontEndProductUrl(item);\r\n    var pid = item.id || item.item_id || \"\";\r\n\r\n    return (\r\n      '\u003cdiv class=\"reco-tile position-relative plp-grid__container--tile m-bottom-xl\" data-prod-id=\"' + escapeHtml(pid) + '\"\u003e' +\r\n        '\u003cdiv class=\"position-relative product-tile js-product-tile-container js-product-tile' + extraClasses + '\" data-prod-id=\"' + escapeHtml(pid) + '\" data-tagg-processed=\"true\"\u003e' +\r\n          '\u003cdiv class=\"product-tile__img text-center position-relative\" data-ct-collar-wrap\u003e' +\r\n            '\u003ca class=\"thumb-link js-thumb-link js-product-tile-image product-tile__img-link d-block keyboard-focus-outline\" href=\"' + escapeHtml(url) + '\"\u003e' +\r\n              '\u003cpicture class=\"d-block bg-white\" style=\"aspect-ratio:430/538;\"\u003e' +\r\n                '\u003cimg data-ct-img alt=\"\" style=\"aspect-ratio:430/538;\"\u003e' +\r\n              '\u003c/picture\u003e' +\r\n            '\u003c/a\u003e' +\r\n          '\u003c/div\u003e' +\r\n          '\u003cdiv class=\"js-tile-info-wrapper text-left product-tile__info-wrapper\"\u003e' +\r\n            '\u003cdiv class=\"js-tile-info product-tile__info bg-white overflow-hidden position-relative\"\u003e' +\r\n              '\u003cdiv\u003e' +\r\n                '\u003ca class=\"js-thumb-link outline-offset-1 product-tile__name-link h4 h4__regular grey1 d-block js-product-tile-name p-top-s\" href=\"' + escapeHtml(url) + '\"\u003e' +\r\n                  '\u003cspan class=\"js-thumb-name font__secondary\" data-ct-title\u003e\u003c/span\u003e' +\r\n                '\u003c/a\u003e' +\r\n              '\u003c/div\u003e' +\r\n              '\u003cdiv\u003e' +\r\n                '\u003cdiv class=\"h5\"\u003e' +\r\n                  '\u003cdiv class=\"js-tile-pricing tile__pricing text-left grey1 font__secondary m-top-xs normal\" data-ct-price\u003e\u003c/div\u003e' +\r\n                '\u003c/div\u003e' +\r\n                '\u003cp class=\"product-tile__promo h5 capitalize grey2 m-top-xs font__secondary\" data-ct-mb\u003e' +\r\n                  '\u003cspan aria-hidden=\"true\"\u003e\u003c/span\u003e' +\r\n                  '\u003cspan class=\"accessibility-hidden\"\u003e\u003c/span\u003e' +\r\n                '\u003c/p\u003e' +\r\n              '\u003c/div\u003e' +\r\n            '\u003c/div\u003e' +\r\n          '\u003c/div\u003e' +\r\n        '\u003c/div\u003e' +\r\n      '\u003c/div\u003e'\r\n    );\r\n  }\r\n\r\n  function onRecommendationsLoaded(data) {\r\n    try {\r\n      var container = document.getElementById(RECO_CONTAINER_ID);\r\n      if (!container) return;\r\n\r\n      if (Array.isArray(data) \u0026\u0026 data.length) {\r\n        var out = ['\u003cdiv class=\"reco-row\"\u003e'];\r\n        for (var i = 0; i \u003c data.length; i++) out.push(renderRecommendationTile(data[i]));\r\n        out.push(\"\u003c/div\u003e\");\r\n        container.innerHTML = out.join(\"\");\r\n\r\n        var tiles = container.querySelectorAll(\".reco-tile[data-prod-id]\");\r\n\r\n        function refreshEmptyState() {\r\n          var row = container.querySelector(\".reco-row\");\r\n          if (!row) return;\r\n\r\n          var liveTiles = row.querySelectorAll(\".reco-tile[data-prod-id]\");\r\n          if (!liveTiles.length) {\r\n            container.innerHTML = '\u003cdiv class=\"reco-row\"\u003eNo recommendations available!\u003c/div\u003e';\r\n          }\r\n        }\r\n\r\n        Array.prototype.forEach.call(tiles, function (tile) {\r\n          var pid = tile.getAttribute(\"data-prod-id\");\r\n          if (pid) applyEndpointDataToRecoTile(pid, tile, refreshEmptyState);\r\n        });\r\n      } else {\r\n        container.innerHTML = '\u003cdiv class=\"reco-row\"\u003eNo recommendations available!\u003c/div\u003e';\r\n      }\r\n\r\n      if (priceChangeAllowed()) applyPlpFormattingEverywhere();\r\n      else revertPlpFormattingEverywhere();\r\n    } catch (e) {\r\n      console.error(TAG, \"onRecommendationsLoaded error:\", e);\r\n    }\r\n  }\r\n\r\n  function openSlideout() {\r\n    var overlay = document.querySelector(\".custom-slideout-overlay\");\r\n    if (!overlay) {\r\n      overlay = document.createElement(\"div\");\r\n      overlay.className = \"custom-slideout-overlay\";\r\n      document.body.appendChild(overlay);\r\n      overlay.addEventListener(\"click\", closeSlideout);\r\n    }\r\n\r\n    var slideout = document.querySelector(\".custom-slideout\");\r\n    if (!slideout) {\r\n      slideout = document.createElement(\"div\");\r\n      slideout.className = \"custom-slideout\";\r\n     slideout.innerHTML =\r\n  '\u003cdiv class=\"custom-slideout-header\"\u003e' +\r\n    '\u003cbutton class=\"custom-slideout-close\" aria-label=\"Close\"\u003e\u003c/button\u003e' +\r\n  '\u003c/div\u003e' +\r\n\r\n  '\u003cdiv class=\"p-ends-m p-sides-m col-100 text-left overflow-hidden\"\u003e' +\r\n    '\u003cp id=\"ct-for-you-heading\" class=\"m-ends-m col-100 grey1 p-sides-z font__secondary medium\" style=\"display:flex;align-items:center;gap:.6rem;\"\u003e' +\r\n      escapeHtml(MB_SLIDEOUT_COPY.heading) +\r\n    '\u003c/p\u003e' +\r\n\r\n    '\u003cdiv class=\"js-tib-id top-info__banner--text col-100 p-sides-z position-relative\"\u003e' +\r\n      '\u003cp class=\"ct-for-you-grid-copy\"\u003e' + escapeHtml(MB_SLIDEOUT_COPY.subheading) +'\u003c/p\u003e' +\r\n    '\u003c/div\u003e' +\r\n  '\u003c/div\u003e' +\r\n\r\n  '\u003cdiv id=\"' + RECO_CONTAINER_ID + '\"\u003e\u003cdiv class=\"reco-row\"\u003eLoading...\u003c/div\u003e\u003c/div\u003e';\r\n      document.body.appendChild(slideout);\r\n\r\n      slideout.querySelector(\".custom-slideout-close\").addEventListener(\"click\", closeSlideout);\r\n      slideout.addEventListener(\"click\", function (e) {\r\n        if (IS_BASKET \u0026\u0026 closest(e.target, \".product-tile a\")) closeSlideout();\r\n      });\r\n\r\n      try {\r\n        if (window.exponea \u0026\u0026 exponea.getRecommendation) {\r\n          exponea.getRecommendation({\r\n            recommendationId: RECOMMENDATION_ID,\r\n            size: 21,\r\n            fillWithRandom: true,\r\n            catalogAttributesWhitelist: [\r\n              \"title\", \"url\", \"price\",\r\n              \"mbuy_price_uk\", \"mbuy_price_au\", \"mbuy_price_eu\",\r\n              \"thumb_image\", \"image\", \"id\",\r\n              \"orig_price_us\", \"product_name_us\", \"url_us\"\r\n            ],\r\n            callback: onRecommendationsLoaded\r\n          });\r\n        } else {\r\n          throw new Error(\"Exponea unavailable\");\r\n        }\r\n      } catch (e) {\r\n        var container = document.getElementById(RECO_CONTAINER_ID);\r\n        if (container) container.innerHTML = '\u003cdiv class=\"reco-row\"\u003eRecommendations unavailable.\u003c/div\u003e';\r\n        console.error(TAG, \"Slideout recs error:\", e);\r\n      }\r\n    }\r\n\r\n    if (IS_MOBILE) {\r\n      document.documentElement.classList.add(\"mb-no-scroll\");\r\n      document.body.classList.add(\"mb-no-scroll\");\r\n    }\r\n\r\n    slideout.classList.add(\"open\");\r\n    overlay.classList.add(\"show\");\r\n\r\n    if (!KEYDOWN_BOUND) {\r\n      KEYDOWN_BOUND = true;\r\n      document.addEventListener(\"keydown\", function (e) {\r\n        if (e.key === \"Escape\") closeSlideout();\r\n      }, true);\r\n    }\r\n  }\r\n\r\n  function closeSlideout() {\r\n    var slideout = document.querySelector(\".custom-slideout\");\r\n    var overlay = document.querySelector(\".custom-slideout-overlay\");\r\n    if (slideout) slideout.classList.remove(\"open\");\r\n    if (overlay) overlay.classList.remove(\"show\");\r\n    document.documentElement.classList.remove(\"mb-no-scroll\");\r\n    document.body.classList.remove(\"mb-no-scroll\");\r\n  }\r\n\r\n  function triggerPopup() {\r\n  if (!isMultibuyUiActive()) return;\r\n  openSlideout();\r\n}\r\n\r\n  /* ========================= Price Formatting ====================== */\r\n  function ensureWasWrap(container, nowWrap) {\r\n    var wasWrap = container.querySelector(\".js-thumb-was-price\");\r\n    if (wasWrap) return wasWrap;\r\n    wasWrap = document.createElement(\"span\");\r\n    wasWrap.className = \"js-thumb-was-price was-price text-decoration-line-through grey1 position-relative col-100 m-right-xs\";\r\n    wasWrap.innerHTML = '\u003cspan class=\"accessibility-hidden\"\u003ewas \u003c/span\u003e\u003cspan aria-hidden=\"true\"\u003e\u003c/span\u003e';\r\n    nowWrap.parentNode.insertBefore(wasWrap, nowWrap);\r\n    wasWrap.dataset.mbWasCreated = \"1\";\r\n    return wasWrap;\r\n  }\r\n\r\n  function setWasPrice(wasWrap, money) {\r\n    if (!wasWrap || !money) return;\r\n    wasWrap.classList.remove(\"hide\");\r\n    wasWrap.style.fontWeight = \"400\";\r\n    var a11y = wasWrap.querySelector(\".accessibility-hidden\");\r\n    var vis = wasWrap.querySelector('[aria-hidden=\"true\"]') || wasWrap;\r\n    if (a11y) a11y.textContent = \"was \" + money.display;\r\n    vis.textContent = money.display;\r\n  }\r\n\r\n  function setNowPrice(nowWrap, money, makeGreen) {\r\n    if (!nowWrap || !money) return;\r\n    var a11y = nowWrap.querySelector(\".accessibility-hidden\");\r\n    var vis = getVisNode(nowWrap);\r\n\r\n    if (!nowWrap.dataset.mbOrigNow) {\r\n      nowWrap.dataset.mbOrigNow = (vis.textContent || \"\").trim();\r\n      nowWrap.dataset.mbOrigColor = nowWrap.style.color || \"\";\r\n    }\r\n\r\n    var desired = (COPY[LANG].now ? COPY[LANG].now + \" \" : \"\") + money.display\r\n    if ((vis.textContent || \"\").trim() !== desired) {\r\n      if (a11y) a11y.textContent = (COPY[LANG].now ? COPY[LANG].now + \" \" : \"\") + money.display;\r\n      vis.textContent = desired;\r\n    }\r\n    nowWrap.style.color = makeGreen ? \"#1e6a60\" : (nowWrap.dataset.mbOrigColor || \"\");\r\n  }\r\n\r\n  function revertNowPrice(nowWrap) {\r\n    if (!nowWrap) return;\r\n    var vis = getVisNode(nowWrap);\r\n    if (nowWrap.dataset.mbOrigNow) {\r\n      vis.textContent = nowWrap.dataset.mbOrigNow;\r\n      delete nowWrap.dataset.mbOrigNow;\r\n    }\r\n    if (\"mbOrigColor\" in nowWrap.dataset) {\r\n      nowWrap.style.color = nowWrap.dataset.mbOrigColor || \"\";\r\n      delete nowWrap.dataset.mbOrigColor;\r\n    } else {\r\n      nowWrap.style.color = \"\";\r\n    }\r\n    var a11y = nowWrap.querySelector(\".accessibility-hidden\");\r\n    if (a11y \u0026\u0026 vis.textContent) a11y.textContent = \"now \" + vis.textContent;\r\n  }\r\n\r\n  function updateHiddenInputs(scope, wasMoney, nowMoney) {\r\n    var wasInput = scope.querySelector(\"#productWasPrice\");\r\n    var nowInput = scope.querySelector(\"#productNowPrice\");\r\n    if (wasInput \u0026\u0026 wasMoney) wasInput.value = wasMoney.value;\r\n    if (nowInput \u0026\u0026 nowMoney) nowInput.value = nowMoney.value;\r\n  }\r\n\r\n  function processTileEnable(tile) {\r\n    try {\r\n      if (!tile) return;\r\n      var promoEl = tile.querySelector(\".product-tile__promo\");\r\n      var nowWrap = tile.querySelector(\".js-thumb-now-price\");\r\n      if (!promoEl || !nowWrap) return;\r\n\r\n      var mbMoney = parseMoney(promoEl.textContent);\r\n      var visNowNode = tile.querySelector(\".js-thumb-now-price [aria-hidden='true']\") || nowWrap;\r\n      var fullMoney = parseMoney(visNowNode.textContent);\r\n      if (!mbMoney || !fullMoney) return;\r\n\r\n      var visText = (getVisNode(nowWrap).textContent || \"\").trim();\r\n      var visVal = parseMoney(visText);\r\n      if (/^now\\s+/i.test(visText) \u0026\u0026 visVal \u0026\u0026 visVal.display === mbMoney.display) {\r\n        promoEl.style.display = \"none\";\r\n        tile.dataset.mbPlpApplied = \"1\";\r\n        return;\r\n      }\r\n\r\n      var wasWrap = ensureWasWrap(tile, nowWrap);\r\n      if (!tile.dataset.mbHadWas) tile.dataset.mbHadWas = wasWrap.dataset.mbWasCreated === \"1\" ? \"0\" : \"1\";\r\n\r\n      setWasPrice(wasWrap, fullMoney);\r\n      setNowPrice(nowWrap, mbMoney, true);\r\n      promoEl.style.display = \"none\";\r\n      updateHiddenInputs(tile, fullMoney, mbMoney);\r\n\r\n      tile.dataset.mbPlpApplied = \"1\";\r\n    } catch (e) {\r\n      console.error(TAG, \"processTileEnable error:\", e, tile);\r\n    }\r\n  }\r\n\r\n  function processTileDisable(tile) {\r\n    try {\r\n      if (!tile || tile.dataset.mbPlpApplied !== \"1\") return;\r\n\r\n      var promoEl = tile.querySelector(\".product-tile__promo\");\r\n      var nowWrap = tile.querySelector(\".js-thumb-now-price\");\r\n      var wasWrap = tile.querySelector(\".js-thumb-was-price\");\r\n\r\n      revertNowPrice(nowWrap);\r\n\r\n      if (wasWrap) {\r\n        //if (wasWrap.dataset.mbWasCreated === \"1\") wasWrap.remove();\r\n        //else wasWrap.classList.add(\"hide\");\r\n      }\r\n      if (promoEl) promoEl.style.display = \"\";\r\n\r\n      delete tile.dataset.mbPlpApplied;\r\n    } catch (e) {\r\n      console.error(TAG, \"processTileDisable error:\", e, tile);\r\n    }\r\n  }\r\n\r\n  function applyPlpFormattingEverywhere() {\r\n    document.querySelectorAll(\".product-tile.js-product-tile, .js-product-tile-container\").forEach(processTileEnable);\r\n  }\r\n\r\n  function revertPlpFormattingEverywhere() {\r\n    document.querySelectorAll(\".product-tile.js-product-tile, .js-product-tile-container\").forEach(processTileDisable);\r\n  }\r\n\r\n  /* ====================== PDP main / slider pricing ====================== */\r\n  function getMbMoneyFromPDP() {\r\n    var scope = document.querySelector(\".pdp-main__inner-details\");\r\n    if (!scope) {\r\n      return null;\r\n    }\r\n\r\n    var mbNode = scope.querySelector(\".js-multibuy-price\");\r\n    var mb = parseMoney(mbNode ? mbNode.textContent : \"\");\r\n    if (!mb) {\r\n      var fb = Array.from(scope.querySelectorAll(\".grey2, .h5, .font__secondary\"))\r\n        .find(function (el) { return /multibuy/i.test(el.textContent || \"\"); });\r\n      if (fb) mb = parseMoney(fb.textContent);\r\n    }\r\n    return mb;\r\n  }\r\n\r\n  function hidePdpMultibuy(scope) {\r\n    var mbNode = scope.querySelector(\".js-multibuy-price\");\r\n    if (mbNode) {\r\n      var block = mbNode.closest(\".grey2\") || mbNode.parentElement;\r\n      if (block) block.style.display = \"none\";\r\n      return;\r\n    }\r\n    var fallback = Array.from(scope.querySelectorAll(\".grey2, .h5, .font__secondary\"))\r\n      .find(function (el) { return /multibuy/i.test(el.textContent || \"\"); });\r\n    if (fallback) fallback.style.display = \"none\";\r\n  }\r\n\r\n  function applyPdpFormatting() {\r\n    try {\r\n      if (!(IS_PDP \u0026\u0026 dlProductEligibleS101() \u0026\u0026 hasAchievedMultibuy())) return;\r\n\r\n      var scope = document.querySelector(\".pdp-main__inner-details\");\r\n      if (!scope) return;\r\n\r\n      var priceBlock = scope.querySelector(\".price.price__display\") || scope;\r\n      var nowWrap = priceBlock.querySelector(\".js-thumb-now-price\");\r\n      if (!nowWrap) return;\r\n\r\n      if (!nowWrap.dataset.mbOrigNow) {\r\n        var vis = getVisNode(nowWrap);\r\n        nowWrap.dataset.mbOrigNow = (vis.textContent || \"\").trim();\r\n        nowWrap.dataset.mbOrigColor = nowWrap.style.color || \"\";\r\n      }\r\n      var orig = parseMoney(nowWrap.dataset.mbOrigNow || \"\");\r\n      var mbMoney = getMbMoneyFromPDP();\r\n      if (!orig || !mbMoney) return;\r\n\r\n      var wasWrap = ensureWasWrap(priceBlock, nowWrap);\r\n      setWasPrice(wasWrap, orig);\r\n      setNowPrice(nowWrap, mbMoney, true);\r\n      hidePdpMultibuy(scope);\r\n      updateHiddenInputs(priceBlock, orig, mbMoney);\r\n\r\n      var sum = document.querySelector(\"#productNowPriceForSummary\");\r\n      if (sum) sum.value = mbMoney.value;\r\n\r\n      document.querySelectorAll(\".terminal\").forEach(function (el) {\r\n        var vis = getVisNode(el);\r\n        if (!el.dataset.mbOrigTerminal) {\r\n          el.dataset.mbOrigTerminal = (vis.textContent || \"\").trim();\r\n          el.dataset.mbOrigColor = el.style.color || \"\";\r\n        }\r\n        var desired = mbMoney.display;\r\n        if ((vis.textContent || \"\").trim() !== desired) {\r\n          vis.textContent = desired;\r\n        }\r\n        el.style.color = \"#1e6a60\";\r\n      });\r\n    } catch (e) {\r\n      console.error(TAG, \"applyPdpFormatting error:\", e);\r\n    }\r\n  }\r\n\r\n  function revertPdpFormatting() {\r\n    try {\r\n      var scope = document.querySelector(\".pdp-main__inner-details\");\r\n      if (!scope) return;\r\n      var priceBlock = scope.querySelector(\".price.price__display\") || scope;\r\n      var nowWrap = priceBlock.querySelector(\".js-thumb-now-price\");\r\n      var wasWrap = priceBlock.querySelector(\".js-thumb-was-price\");\r\n\r\n      if (nowWrap) revertNowPrice(nowWrap);\r\n      if (wasWrap) {\r\n        //if (wasWrap.dataset.mbWasCreated === \"1\") wasWrap.remove();\r\n        //else wasWrap.classList.add(\"hide\");\r\n      }\r\n\r\n      var mbNode = scope.querySelector(\".js-multibuy-price\");\r\n      if (mbNode) {\r\n        var block = mbNode.closest(\".grey2\") || mbNode.parentElement;\r\n        if (block) block.style.display = \"\";\r\n      }\r\n\r\n      document.querySelectorAll(\".terminal\").forEach(function (el) {\r\n        var vis = getVisNode(el);\r\n        if (el.dataset.mbOrigTerminal) {\r\n          vis.textContent = el.dataset.mbOrigTerminal;\r\n          delete el.dataset.mbOrigTerminal;\r\n        }\r\n        if (\"mbOrigColor\" in el.dataset) {\r\n          el.style.color = el.dataset.mbOrigColor || \"\";\r\n          delete el.dataset.mbOrigColor;\r\n        } else {\r\n          el.style.color = \"\";\r\n        }\r\n      });\r\n    } catch (e) {\r\n      console.error(TAG, \"revertPdpFormatting error:\", e);\r\n    }\r\n  }\r\n\r\n  function updateJsProductPriceNode(el, mbMoney) {\r\n    try {\r\n      var vis = getVisNode(el);\r\n      if (!el.dataset.mbOrigSliderPrice) el.dataset.mbOrigSliderPrice = (vis.textContent || \"\").trim();\r\n      var desired = mbMoney ? mbMoney.display : el.dataset.mbOrigSliderPrice;\r\n      var current = (vis.textContent || \"\").trim();\r\n      if (current === desired) return;\r\n      vis.textContent = desired;\r\n      el.style.color = \"\";\r\n    } catch (e) {\r\n      console.error(TAG, \"updateJsProductPriceNode error:\", e, el);\r\n    }\r\n  }\r\n\r\n  function attachJsProductPriceObserver(el) {\r\n    if (!el || PRICE_OBSERVED.has(el)) return;\r\n    var reentrant = false;\r\n    var obs = new MutationObserver(function () {\r\n      if (reentrant) return;\r\n      reentrant = true;\r\n      try {\r\n        var allowed = priceChangeAllowed();\r\n        var mb = (allowed \u0026\u0026 IS_PDP) ? getMbMoneyFromPDP() : null;\r\n        updateJsProductPriceNode(el, mb);\r\n      } catch (e) {\r\n        console.error(TAG, \"price observer error:\", e);\r\n      } finally {\r\n        setTimeout(function () { reentrant = false; }, 0);\r\n      }\r\n    });\r\n    obs.observe(el, { childList: true, subtree: true, characterData: true });\r\n    PRICE_OBSERVED.add(el);\r\n    dbg(\"Observer attached to .js-product-price\", el);\r\n  }\r\n\r\n  function initJsProductPriceObservers() {\r\n    if (!(IS_PDP \u0026\u0026 dlProductEligibleS101() \u0026\u0026 hasAchievedMultibuy())) return;\r\n    document.querySelectorAll(\".js-product-price\").forEach(function (el) {\r\n      var mb = getMbMoneyFromPDP();\r\n      updateJsProductPriceNode(el, mb);\r\n      attachJsProductPriceObserver(el);\r\n    });\r\n  }\r\n\r\n  function revertSliderPrices() {\r\n    document.querySelectorAll(\".js-product-price\").forEach(function (el) {\r\n      updateJsProductPriceNode(el, null);\r\n    });\r\n  }\r\n\r\n  function revertAllFormatting() {\r\n    revertPlpFormattingEverywhere();\r\n    revertPdpFormatting();\r\n    revertSliderPrices();\r\n  }\r\n\r\n  /* ============================= Sync UI =========================== */\r\n  function teardownMultibuyUI() {\r\n    closeSlideout();\r\n    removeBanner();\r\n    document.documentElement.classList.remove(\"mb-no-scroll\");\r\n    document.body.classList.remove(\"mb-no-scroll\");\r\n    MB_INIT_DONE = false;\r\n  }\r\n\r\n  function syncMultibuyUI() {\r\n  try {\r\n    var uiActive = isMultibuyUiActive();\r\n\r\n    if (uiActive) {\r\n      injectStyles();\r\n      ensureBanner();\r\n      MB_INIT_DONE = true;\r\n\r\n      if (IS_PLP) {\r\n        injectPagingbarOverride();\r\n      } else {\r\n        removePagingbarOverride();\r\n      }\r\n\r\n      // pricing override intentionally disabled\r\n      revertAllFormatting();\r\n    } else {\r\n      teardownMultibuyUI();\r\n      removePagingbarOverride();\r\n      revertAllFormatting();\r\n    }\r\n  } catch (e) {\r\n    console.error(TAG, \"syncMultibuyUI error:\", e);\r\n  }\r\n}\r\n\r\n  function scheduleSync(delay) {\r\n    if (SYNC_DEBOUNCE) clearTimeout(SYNC_DEBOUNCE);\r\n    SYNC_DEBOUNCE = setTimeout(syncMultibuyUI, delay || 150);\r\n  }\r\n\r\n  function observeBasketChanges() {\r\n    if (BASKET_OBSERVER) {\r\n      try { BASKET_OBSERVER.disconnect(); } catch (e) {}\r\n    }\r\n    BASKET_OBSERVER = new MutationObserver(function () {\r\n      if (SYNC_DEBOUNCE) clearTimeout(SYNC_DEBOUNCE);\r\n      SYNC_DEBOUNCE = setTimeout(syncMultibuyUI, 300);\r\n    });\r\n    var target = document.getElementById(\"mini-cart\");\r\n    if (target) BASKET_OBSERVER.observe(target, { childList: true, subtree: true });\r\n  }\r\n\r\n  var DOM_OBS = new MutationObserver(function (muts) {\r\n    var allow = priceChangeAllowed();\r\n    var seenTiles = false, seenPrice = false, seenPdp = false;\r\n    for (var i = 0; i \u003c muts.length; i++) {\r\n      var list = muts[i].addedNodes;\r\n      if (!list) continue;\r\n      for (var j = 0; j \u003c list.length; j++) {\r\n        var n = list[j];\r\n        if (!(n instanceof HTMLElement)) continue;\r\n        if ((n.matches \u0026\u0026 n.matches(\".product-tile.js-product-tile, .js-product-tile-container\")) || (n.querySelector \u0026\u0026 n.querySelector(\".product-tile.js-product-tile, .js-product-tile-container\"))) seenTiles = true;\r\n        if ((n.matches \u0026\u0026 n.matches(\".js-product-price\")) || (n.querySelector \u0026\u0026 n.querySelector(\".js-product-price\"))) seenPrice = true;\r\n        if ((n.matches \u0026\u0026 n.matches(\".pdp-main__inner-details\")) || (n.querySelector \u0026\u0026 n.querySelector(\".pdp-main__inner-details\"))) seenPdp = true;\r\n      }\r\n    }\r\n  });\r\n\r\n  if (document.body) {\r\n    DOM_OBS.observe(document.body, { childList: true, subtree: true });\r\n  } else {\r\n    window.addEventListener(\"DOMContentLoaded\", function () {\r\n      DOM_OBS.observe(document.body, { childList: true, subtree: true });\r\n    });\r\n  }\r\n\r\n  /* =============================== Events ========================== */\r\n  document.addEventListener(\"click\", function (e) {\r\n    if (closest(e.target, \".mb-banner\")) {\r\n      e.preventDefault();\r\n      if (hasAchievedMultibuy()) triggerPopup();\r\n    }\r\n\r\n    var t = e.target;\r\n    if (t \u0026\u0026 t.closest \u0026\u0026 t.closest(\"[name='addToCart'], .js-add-to-basket, .add-to-basket, #add-to-cart\")) {\r\n      setTimeout(function () {\r\n        revertAllFormatting();\r\n      }, 150);\r\n    }\r\n  });\r\n\r\n  /* ================================ Init =========================== */\r\n  (function init() {\r\n    try {\r\n      syncMultibuyUI();\r\n      observeBasketChanges();\r\n      var attempts = 0;\r\n      RECHECK_TIMER = setInterval(function () {\r\n        attempts++;\r\n        syncMultibuyUI();\r\n        if (attempts \u003e 10) {\r\n          clearInterval(RECHECK_TIMER);\r\n          RECHECK_TIMER = null;\r\n        }\r\n      }, 1000);\r\n    } catch (e) {\r\n      console.error(TAG, \"init error:\", e);\r\n    }\r\n  })();\r\n\r\n  setInterval(function () {\r\n    if (document.querySelector(\".pdp-main__inner-details\")) priceChangeAllowed();\r\n  }, 3000);\r\n\r\n})();","trigger":{"include_pages":[{"type":"any"}],"exclude_pages":[{"url":"dwcont","type":"contains"},{"url":"/ch/","type":"contains"}]},"_id":"693332cfbe73ed65a0453cd7"},{"uses_overlay":false,"type":"js","parametrized_definition":"(function () {\n  \"use strict\";\n\n  // ---------- run once per page ----------\n  var RUN_FLAG = \"__BR_SIV_PIXEL_US_ONLY__\";\n  if (window[RUN_FLAG]) return;\n  window[RUN_FLAG] = true;\n\n  var PIXEL_SRC = \"https://cdn.brcdn.com/v1/siv/br-trk-8125-wrapper.js\";\n\n  function hasScript(src) {\n    return !!document.querySelector('script[src=\"' + src + '\"]');\n  }\n\n  function waitForUtag(cb, maxTries) {\n    maxTries--;\n    if (window.utag_data \u0026\u0026 utag_data.global \u0026\u0026 typeof utag_data.global.sfcc_country === \"string\") {\n      cb();\n    } else if (maxTries \u003e 0) {\n      setTimeout(function () { waitForUtag(cb, maxTries); }, 50);\n    }\n  }\n\n  waitForUtag(function () {\n    // ---------- US-only gate ----------\n    if (utag_data.global.sfcc_country !== \"US\") return;\n\n    // ---------- belt \u0026 braces: don't double-insert ----------\n    if (hasScript(PIXEL_SRC)) return;\n\n    var s = document.createElement(\"script\");\n    s.async = true;\n    s.type = \"text/javascript\";\n    s.src = PIXEL_SRC;\n\n    (document.head || document.documentElement).appendChild(s);\n  }, 100);\n})();\n","trigger":{"include_pages":[{"type":"any"}],"exclude_pages":null},"_id":"695f78b9d84be51e1c8bc6ef"},{"uses_overlay":false,"type":"js","parametrized_definition":"(() =\u003e {\r\n  \"use strict\";\r\n\r\n  // Guard: homepage only\r\n  if (\r\n    !window.utag_data ||\r\n    window.utag_data?.page?.name !== \"Homepage\"\r\n  ) {\r\n    return;\r\n  }\r\n\r\n  const SVG_SRC =\r\n    \"https://www.charlestyrwhitt.com/on/demandware.static/-/Library-Sites-CTShirtsSharedLibrary/default/dwf32243ec/merchAssets/content/All-Svg-Icons/tyrhwitt-takeback-Logo.svg\";\r\n\r\n  const LINK_HREF =\r\n    \"https://www.charlestyrwhitt.com/uk/tyrwhitt-takeback-scheme.html\";\r\n\r\n  // Covers \u003cimg src=\"...svg\"\u003e and any odd \u003csvg src=\"...\"\u003e cases\r\n  const icons = document.querySelectorAll(\r\n    `img[src=\"${SVG_SRC}\"], svg[src=\"${SVG_SRC}\"]`\r\n  );\r\n\r\n  icons.forEach((icon) =\u003e {\r\n    // Don’t double-wrap\r\n    if (icon.closest(\"a\")) return;\r\n\r\n    const link = document.createElement(\"a\");\r\n    link.href = LINK_HREF;\r\n    link.setAttribute(\"aria-label\", \"Tyrwhitt Takeback Scheme\");\r\n\r\n    icon.parentNode.insertBefore(link, icon);\r\n    link.appendChild(icon);\r\n  });\r\n})();\r\n","trigger":{"include_pages":[{"url":"home","type":"contains"}],"exclude_pages":null},"_id":"696e9065dc027424c39feb69"},{"uses_overlay":false,"type":"html","parametrized_definition":"\u003cscript\u003e\n(function () {\n  \"use strict\";\n\n  const RUN_FLAG = \"__CT_MENTION_ME_PDP__\";\n  if (window[RUN_FLAG]) return;\n  window[RUN_FLAG] = true;\n\n  // Hard guard: only run on PDP\n  if (!window.utag_data || utag_data.page?.type !== \"product\") return;\n\n  const productId = String(utag_data.products?.[0]?.id || \"\").trim();\n  if (!productId) return;\n\n  const script = document.createElement(\"script\");\n  script.type = \"text/javascript\";\n  script.async = true;\n  script.src =\n    \"https://tag.mention-me.com/api/v2/product/mme5bcd07b\" +\n    \"?situation=product\" +\n    \"\u0026implementation=sharelink\" +\n    \"\u0026locale=en_GB\" +\n    \"\u0026product_id=\" + encodeURIComponent(productId);\n\n  document.head.appendChild(script);\n})();\n\u003c/script\u003e\n","trigger":{"include_pages":[{"type":"any"}],"exclude_pages":null},"_id":"69945a5bbd3fb93768250079"},{"uses_overlay":false,"type":"js","parametrized_definition":"(function () {\n  \"use strict\";\n\n  if (!window.exponea) return;\n  if (!window.webxpClient || typeof window.webxpClient.reset !== \"function\") return;\n  if (window.utag_data?.global?.sfcc_country !== \"US\") return;\n  if (window.utag_data?.bloomreach_tests) return;\n\n  var SPLIT_KEY = \"ct_us_site_split_v1\";            // persistent bucket\n  var ASSIGNED_KEY = \"ct_us_block_assigned_v1\";     // marks Bloomreach update/track completed\n\n  var storage;\n  try {\n    storage = window.localStorage;\n    storage.setItem(\"__t\", \"1\");\n    storage.removeItem(\"__t\");\n  } catch (e) {\n    return;\n  }\n\n  var alreadyAssigned = false;\n  try {\n    alreadyAssigned = storage.getItem(ASSIGNED_KEY) === \"1\";\n  } catch (e) {\n    return;\n  }\n\n  // If already assigned once for this customer/browser, do nothing forever\n  if (alreadyAssigned) return;\n\n  // Get or create persistent split\n  var split = null;\n  try { split = storage.getItem(SPLIT_KEY); } catch (e) {}\n\n  if (split == null || split === \"\") {\n    split = String(Math.floor(Math.random() * 100));\n    try { storage.setItem(SPLIT_KEY, split); } catch (e) {}\n  }\n\n  var splitNum = Number(split);\n\n  // Mark before sending to reduce double-fire risk\n  try { storage.setItem(ASSIGNED_KEY, \"1\"); } catch (e) {}\n\n  try {\n    window.exponea.update({\n      us_site_split: splitNum\n    });\n  } catch (e) {}\n\n  try {\n  \tconsole.log('Assign block', splitNum);\n    window.exponea.track(\"us_block_assign\", {\n      us_site_split: splitNum\n    });\n  } catch (e) {}\n\n  // Re-init experiment once so first page can qualify without refresh\n  setTimeout(function () {\n    try {\n    \tconsole.log('Force assign');\n      window.webxpClient.reset();\n      console.debug(\"[CT] Split assigned once and experiment reset:\", splitNum);\n    } catch (e) {}\n  }, 2000);\n})();","trigger":{"include_pages":[{"type":"any"}],"exclude_pages":null},"_id":"699c661cd6ccf39bc176de34"},{"uses_overlay":false,"type":"js","parametrized_definition":"(function () {\n\tconsole.log('Go');\n  \"use strict\";\n  console.log('Here', !window.exponea,!window.webxpClient || typeof window.webxpClient.reset !== \"function\",  window.utag_data?.global?.sfcc_country !== \"UK\", window.utag_data?.bloomreach_tests);\n\n  if (!window.exponea) return;\n  if (window.utag_data?.global?.sfcc_country !== \"UK\") return;\n  if (window.utag_data?.bloomreach_tests) return;\n  \n  console.log('Here2');\n\n  var SPLIT_KEY = \"ct_uk_site_split_v1\";            // persistent bucket\n  var ASSIGNED_KEY = \"ct_uk_block_assigned_v1\";     // marks Bloomreach update/track completed\n\n  var storage;\n  try {\n    storage = window.localStorage;\n    storage.setItem(\"__t\", \"1\");\n    storage.removeItem(\"__t\");\n  } catch (e) {\n    return;\n  }\n\n  var alreadyAssigned = false;\n  try {\n    alreadyAssigned = storage.getItem(ASSIGNED_KEY) === \"1\";\n  } catch (e) {\n    return;\n  }\n  \n  console.log('Here3', alreadyAssigned);\n\n  // If already assigned once for this customer/browser, do nothing forever\n  if (alreadyAssigned) return;\n\n  // Get or create persistent split\n  var split = null;\n  try { split = storage.getItem(SPLIT_KEY); } catch (e) {}\n\n  if (split == null || split === \"\") {\n    split = String(Math.floor(Math.random() * 100));\n    try { storage.setItem(SPLIT_KEY, split); } catch (e) {}\n  }\n\n  var splitNum = Number(split);\n\n  // Mark before sending to reduce double-fire risk\n  try { storage.setItem(ASSIGNED_KEY, \"1\"); } catch (e) {}\n\n  try {\n    window.exponea.update({\n      uk_site_split: splitNum\n    });\n  } catch (e) {}\n\n  try {\n  \tconsole.log('Assign block');\n    window.exponea.track(\"uk_block_assign\", {\n      uk_site_split: splitNum\n    });\n  } catch (e) {}\n\n  // Re-init experiment once so first page can qualify without refresh\n  setTimeout(function () {\n    try {\n    \tconsole.log('Force reset');\n      window.webxpClient.reset();\n      console.debug(\"[CT] Split assigned once and experiment reset:\", splitNum);\n    } catch (e) {}\n  }, 2000);\n})();","trigger":{"include_pages":[{"type":"any"}],"exclude_pages":null},"_id":"69a96b3c045149338993efcd"},{"uses_overlay":false,"type":"js","parametrized_definition":"(function () {\n  \"use strict\";\n\n  if (!window.exponea) return;\n  if (!window.webxpClient || typeof window.webxpClient.reset !== \"function\") return;\n  if (window.utag_data?.global?.sfcc_country !== \"DE\") return;\n  if (window.utag_data?.bloomreach_tests) return;\n\n  var SPLIT_KEY = \"ct_de_site_split_v1\";            // persistent bucket\n  var ASSIGNED_KEY = \"ct_de_block_assigned_v1\";     // marks Bloomreach update/track completed\n\n  var storage;\n  try {\n    storage = window.localStorage;\n    storage.setItem(\"__t\", \"1\");\n    storage.removeItem(\"__t\");\n  } catch (e) {\n    return;\n  }\n\n  var alreadyAssigned = false;\n  try {\n    alreadyAssigned = storage.getItem(ASSIGNED_KEY) === \"1\";\n  } catch (e) {\n    return;\n  }\n\n  // If already assigned once for this customer/browser, do nothing forever\n  if (alreadyAssigned) return;\n\n  // Get or create persistent split\n  var split = null;\n  try { split = storage.getItem(SPLIT_KEY); } catch (e) {}\n\n  if (split == null || split === \"\") {\n    split = String(Math.floor(Math.random() * 100));\n    try { storage.setItem(SPLIT_KEY, split); } catch (e) {}\n  }\n\n  var splitNum = Number(split);\n\n  // Mark before sending to reduce double-fire risk\n  try { storage.setItem(ASSIGNED_KEY, \"1\"); } catch (e) {}\n\n  try {\n    window.exponea.update({\n      de_site_split: splitNum\n    });\n  } catch (e) {}\n\n  try {\n    window.exponea.track(\"de_block_assign\", {\n      de_site_split: splitNum\n    });\n  } catch (e) {}\n\n  // Re-init experiment once so first page can qualify without refresh\n  setTimeout(function () {\n    try {\n      window.webxpClient.reset();\n      console.debug(\"[CT] Split assigned once and experiment reset:\", splitNum);\n    } catch (e) {}\n  }, 2000);\n})();","trigger":{"include_pages":[{"type":"any"}],"exclude_pages":null},"_id":"69a99d5d9a386d6c7480e5f1"},{"uses_overlay":false,"type":"js","parametrized_definition":"(function () {\n  \"use strict\";\n\n  var RUN_FLAG = \"__CT_EVENT_BANNER__\";\n  var BANNER_ID = \"ct-event-banner\";\n  var STYLE_ID = \"ct-event-banner-style\";\n  var HEADER_SELECTOR = \"#header\";\n\n  var BANNERS = {\n    \"0tbuks1\": {\n      message: \"Happy Birthday! 15% Off + Free Socks\",\n      link: \"https://www.charlestyrwhitt.com/uk/choose-your-free-pair-of-socks/\"\n    },\n    \"0tbcb1\": {\n      message: \"Happy Birthday! Enjoy 15% Off\",\n      link: \"\"\n    },\n    \"ukctan1\": {\n      message: \"Happy Anniversary! Enjoy 10% Off\",\n      link: \"\"\n    },\n\n    \"0tbcg1\": {\n      message: \"Alles Gute zum Geburtstag – genießen Sie 15 % Rabatt!\",\n      link: \"\"\n    },\n    \"dectan1\": {\n      message: \"Zum jahrestag! Feiern sie mit 10 € rabatt\",\n      link: \"\"\n    },\n\n    \"0tbeu1\": {\n      message: \"Happy Birthday! Enjoy 15% off\",\n      link: \"\"\n    },\n    \"euctan1\": {\n      message: \"Happy Anniversary! Enjoy €10 Off\",\n      link: \"\"\n    },\n\n    \"anniv2\": {\n      message: \"Happy Anniversary! Enjoy $15 Off\",\n      link: \"\"\n    },\n\n    \"0tbcs1\": {\n      message: \"Happy Birthday! Enjoy 20% Off\",\n      link: \"\"\n    },\n    \"anniv1\": {\n      message: \"Happy Anniversary! Enjoy $20 Off\",\n      link: \"\"\n    },\n\n    \"0tbxb1\": {\n      message: \"Happy Birthday! Enjoy 15% Off\",\n      link: \"\"\n    },\n    \"xbrctan1\": {\n      message: \"Happy Anniversary! Enjoy 10% Off\",\n      link: \"\"\n    }\n  };\n\n  if (window[RUN_FLAG]) return;\n  window[RUN_FLAG] = true;\n\n  var campaignSite = \"\";\n  try {\n    campaignSite = String(\n      (window.utag_data \u0026\u0026 window.utag_data.global \u0026\u0026 window.utag_data.global.campaign_site) || \"\"\n    ).toLowerCase();\n  } catch (e) {\n    return;\n  }\n\n  var config = BANNERS[campaignSite];\n  if (!config || !config.message) return;\n\n  var hasLink = !!String(config.link || \"\").trim();\n\n  function injectStyles() {\n    if (document.getElementById(STYLE_ID)) return;\n\n    var style = document.createElement(\"style\");\n    style.id = STYLE_ID;\n   style.textContent = `\n  #${BANNER_ID} {\n    width: 100%;\n    background: #373737;\n    color: #fff;\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    gap: 14px;\n    padding: 10px 15px;\n    text-align: center;\n    font-family: Futura, system-ui, sans-serif;\n    position: relative;\n    z-index: 1;\n    border-bottom: 2px solid #936F1F;\n    box-sizing: border-box;\n  }\n\n  #${BANNER_ID}.is-clickable {\n    cursor: pointer;\n  }\n\n  #${BANNER_ID} .ct-banner__inner {\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    gap: 14px;\n    flex-wrap: wrap;\n    width: 100%;\n  }\n\n  #${BANNER_ID} .ct-banner__text {\n    font-size: 1.6rem;\n    font-weight: 500;\n    letter-spacing: .02em;\n    line-height: 1.2;\n  }\n\n  #${BANNER_ID} .ct-banner__cta {\n    display: inline-flex;\n    align-items: center;\n    justify-content: center;\n    height: 20px;\n    padding: 0 10px;\n    background: #fff;\n    color: #373737;\n    border-radius: 5px;\n    font-weight: 700;\n    text-transform: uppercase;\n    white-space: nowrap;\n    text-decoration: none;\n  }\n\n  /* 👇 Only applies when banner exists */\n  @media (min-width: 1024px) and (hover: hover), \n         (min-width: 1024px) and (-ms-high-contrast:active), \n         (min-width: 1024px) and (-ms-high-contrast:none) {\n    .pagingbar-top {\n      top: 9rem;\n    }\n  }\n\n  @media (max-width: 767px) {\n    #${BANNER_ID} {\n      padding: 10px 12px;\n      gap: 8px;\n    }\n\n    #${BANNER_ID} .ct-banner__inner {\n      gap: 8px;\n    }\n\n    #${BANNER_ID} .ct-banner__text {\n      font-size: 1.4rem;\n    }\n  }\n`;\n    document.head.appendChild(style);\n  }\n\n  function buildBannerHtml() {\n    var ctaHtml = hasLink\n      ? `\u003ca class=\"ct-banner__cta\" href=\"${config.link}\"\u003eClaim\u003c/a\u003e`\n      : \"\";\n\n    return `\n      \u003cdiv class=\"ct-banner__inner\"\u003e\n        \u003cdiv class=\"ct-banner__text\"\u003e${config.message}\u003c/div\u003e\n        ${ctaHtml}\n      \u003c/div\u003e\n    `;\n  }\n\n  function injectBanner() {\n    var header = document.querySelector(HEADER_SELECTOR);\n    if (!header) return false;\n    if (document.getElementById(BANNER_ID)) return true;\n\n    injectStyles();\n\n    var banner = document.createElement(\"div\");\n    banner.id = BANNER_ID;\n    if (hasLink) banner.className = \"is-clickable\";\n    banner.innerHTML = buildBannerHtml();\n\n    if (hasLink) {\n      banner.addEventListener(\"click\", function (e) {\n        if (e.target.closest(\"a\")) return;\n        window.location.href = config.link;\n      });\n    }\n\n    header.insertBefore(banner, header.firstChild);\n    return true;\n  }\n\n  if (injectBanner()) return;\n\n  var observer = new MutationObserver(function () {\n    if (injectBanner()) observer.disconnect();\n  });\n\n  observer.observe(document.documentElement, {\n    childList: true,\n    subtree: true\n  });\n})();","trigger":{"include_pages":[{"type":"any"}],"exclude_pages":null},"_id":"69e729617dbfa5f106e8d456"},{"uses_overlay":false,"type":"js","parametrized_definition":"(function () {\r\n  'use strict';\r\n\r\n  var LOG = '[ss26-cta]';\r\n  var PHRASES = ['SHIRTY', 'NEUESHEMD', 'ETE175', 'SHIRTS175', 'SAVETWENTY', 'NL175', 'CH245'];\r\n  var TILE_ID = 'ss26-plptile-shirt-up-event';\r\n  var HREF_MARKER = 'up-event-ss26_shirts'; // locale-independent, identifies the shirts CTA\r\n\r\n  function pageTypeIsCategory() {\r\n    var type = window.utag_data \u0026\u0026 window.utag_data.page \u0026\u0026 window.utag_data.page.type;\r\n    var ok = type === 'category';\r\n    console.log(LOG, 'page.type =', type, '| isCategory =', ok);\r\n    return ok;\r\n  }\r\n\r\n  function phrasePresent() {\r\n    var text = ((document.body \u0026\u0026 document.body.textContent) || '').toUpperCase();\r\n    var found = PHRASES.filter(function (p) { return text.indexOf(p) !== -1; });\r\n    console.log(LOG, 'phrases matched =', found);\r\n    return found.length \u003e 0;\r\n  }\r\n\r\n  function removeCtas() {\r\n    // querySelectorAll catches duplicate IDs. getElementById only returns the first.\r\n    var tiles = document.querySelectorAll('[id=\"' + TILE_ID + '\"]');\r\n    console.log(LOG, 'tiles with id =', tiles.length);\r\n\r\n    var anchors = [];\r\n    for (var t = 0; t \u003c tiles.length; t++) {\r\n      var found = tiles[t].querySelectorAll('a');\r\n      for (var a = 0; a \u003c found.length; a++) anchors.push(found[a]);\r\n    }\r\n    console.log(LOG, 'anchors found across tiles =', anchors.length);\r\n\r\n    var removed = 0;\r\n    for (var i = 0; i \u003c anchors.length; i++) {\r\n      var href = anchors[i].getAttribute('href') || '';\r\n      console.log(LOG, 'anchor[' + i + '] href =', href);\r\n      if (href.indexOf(HREF_MARKER) !== -1) {\r\n        anchors[i].remove();\r\n        removed++;\r\n        console.log(LOG, 'CTA removed (' + removed + ')');\r\n      }\r\n    }\r\n    console.log(LOG, 'total CTAs removed =', removed);\r\n  }\r\n\r\n  function run() {\r\n    console.log(LOG, 'script running | readyState =', document.readyState);\r\n\r\n    if (!pageTypeIsCategory()) {\r\n      console.log(LOG, 'not a category page, exiting');\r\n      return;\r\n    }\r\n    if (!phrasePresent()) {\r\n      console.log(LOG, 'no phrase present, exiting');\r\n      return;\r\n    }\r\n\r\n    removeCtas();\r\n  }\r\n\r\n  if (document.readyState === 'loading') {\r\n    document.addEventListener('DOMContentLoaded', run);\r\n  } else {\r\n    run();\r\n  }\r\n})();","trigger":{"include_pages":[{"type":"any"}],"exclude_pages":null},"_id":"6a22adf082bc5dff4c48c722"},{"uses_overlay":false,"type":"js","parametrized_definition":"\n(() =\u003e {\n  \"use strict\";\n\n  const RUN_FLAG = \"__CT_FR_PROMOTION_TO_SOLDES_SCHEDULED_V7__\";\n  if (window[RUN_FLAG]) return;\n  window[RUN_FLAG] = true;\n\n  try {\n    if (!window.utag_data || !window.utag_data.global) {\n      console.log(\"[CT FR Soldes] No utag_data.global, exiting\");\n      return;\n    }\n\n    const CONFIG = {\n      DEBUG: false,\n\n      SCHEDULING: {\n        ENABLE: true,\n        NOW_OFFSET_MS: 0,\n        USE_LOCAL_TIME_BY_REGION: false,\n\n        PREVIEW: {\n          ENABLE: true,\n          TITLE_REGEX:\n            /[()（）\\[\\]]\\s*(?:\\d{4}-\\d{2}-\\d{2}|\\d{1,2}[.\\-\\/]\\d{1,2}[.\\-\\/]\\d{4})\\s+\\d{1,2}[:hH]\\d{2}(?:\\s*(?:[ap]\\s*\\.?\\s*m\\.?))?(?:\\s*[A-Za-zÀ-ÿ]{2,5})?\\s*[\\])）]?/iu,\n          ASSUME_UTC: true,\n          FORMAT_MAP: {\n            FR: \"DMY\",\n            DEFAULT: \"DMY\"\n          }\n        },\n\n        BY_CAMPAIGNSITE: {},\n\n        BY_REGION: {\n          FR: [\n            {\n              start: \"2026-06-24T00:00:00Z\",\n              end: \"2026-07-28T23:59:59Z\"\n            }\n          ]\n        },\n\n        GLOBAL: []\n      }\n    };\n\n    const sfccCountry = String(window.utag_data?.global?.sfcc_country || \"\").toUpperCase();\n    const campaignSite = String(window.utag_data?.global?.campaign_site || \"\").toLowerCase();\n    const siteLang = String(window.utag_data?.global?.site_language || \"\").trim().toLowerCase();\n    const REGION = sfccCountry === \"FR\" ? \"FR\" : \"\";\n\n    function log() {\n      if (!CONFIG.DEBUG) return;\n      //console.log.apply(console, [\"[CT FR Soldes]\"].concat([].slice.call(arguments)));\n    }\n\n    if (!REGION) {\n      log(\"Not FR\", { sfccCountry });\n      return;\n    }\n\n    function hasTz(iso) {\n      return /Z|[+\\-]\\d{2}:\\d{2}$/.test(String(iso || \"\"));\n    }\n\n    function parseUtcOrNull(iso) {\n      if (!iso) return null;\n      const s = hasTz(iso) ? iso : iso + \"Z\";\n      const t = Date.parse(s);\n      return Number.isFinite(t) ? t : null;\n    }\n\n    function isNowWithinWindow(nowMs, win) {\n      const start = parseUtcOrNull(win.start) ?? Number.NEGATIVE_INFINITY;\n      const end = parseUtcOrNull(win.end) ?? Number.POSITIVE_INFINITY;\n      return nowMs \u003e= start \u0026\u0026 nowMs \u003c end;\n    }\n\n    function anyWindowActive(nowMs, arr) {\n      if (!Array.isArray(arr) || arr.length === 0) return false;\n      return arr.some(win =\u003e isNowWithinWindow(nowMs, win));\n    }\n\n    function resolveDesiredFormatForPreview() {\n      const langPrefix = String(siteLang || \"\").toLowerCase().split(\"_\")[0];\n      const map = CONFIG.SCHEDULING?.PREVIEW?.FORMAT_MAP || {};\n      return map[`${REGION}:${langPrefix}`] || map[REGION] || map.DEFAULT || \"DMY\";\n    }\n\n    function readPreviewNowMsFromTitle() {\n      try {\n        const cfgPrev = CONFIG?.SCHEDULING?.PREVIEW;\n        if (!cfgPrev || cfgPrev.ENABLE === false) return null;\n\n        const title = String(document?.title || \"\")\n          .replace(/[\\u00A0\\u202F\\u2007\\u2009\\u200A\\u2002-\\u2006]/g, \" \")\n          .trim();\n\n        if (!title) return null;\n        if (cfgPrev.TITLE_REGEX \u0026\u0026 !cfgPrev.TITLE_REGEX.test(title)) return null;\n\n        const reYMD =\n          /[()（）\\[\\]]\\s*(\\d{4})-(\\d{2})-(\\d{2})\\s+(\\d{1,2}):(\\d{2})\\s*[\\])）]?/;\n\n        const reDMYorMDY =\n          /[()（）\\[\\]]\\s*(\\d{1,2})[.\\-\\/](\\d{1,2})[.\\-\\/](\\d{4})\\s+(\\d{1,2})[:hH](\\d{2})(?:\\s*(?:([ap])\\s*\\.?\\s*m\\.?))?(?:\\s*([A-Za-zÀ-ÿ]{2,5}))?\\s*[\\])）]?/iu;\n\n        let utcMs = null;\n        const mYMD = title.match(reYMD);\n\n        if (mYMD) {\n          utcMs = Date.UTC(+mYMD[1], +mYMD[2] - 1, +mYMD[3], +mYMD[4], +mYMD[5], 0, 0);\n        } else {\n          const m = title.match(reDMYorMDY);\n          if (!m) return null;\n\n          let n1 = +m[1];\n          let n2 = +m[2];\n          const yyyy = +m[3];\n          let hh = +m[4];\n          const min = +m[5];\n          const ampmRaw = (m[6] || \"\").toLowerCase();\n\n          let inferredDMY = null;\n          if (n1 \u003e 12 \u0026\u0026 n2 \u003c= 12) inferredDMY = true;\n          else if (n2 \u003e 12 \u0026\u0026 n1 \u003c= 12) inferredDMY = false;\n\n          const configured = resolveDesiredFormatForPreview();\n          const useDMY = inferredDMY === null ? configured !== \"MDY\" : inferredDMY;\n\n          const day = useDMY ? n1 : n2;\n          const month = useDMY ? n2 : n1;\n\n          if (ampmRaw) {\n            const isPM = ampmRaw.startsWith(\"p\");\n            if (hh === 12) hh = isPM ? 12 : 0;\n            else if (isPM) hh += 12;\n          }\n\n          utcMs = Date.UTC(yyyy, month - 1, day, hh, min, 0, 0);\n        }\n\n        if (!Number.isFinite(utcMs)) return null;\n\n        log(\"Preview date detected\", {\n          title,\n          previewUtc: new Date(utcMs).toISOString()\n        });\n\n        return utcMs;\n      } catch (e) {\n        console.warn(\"[CT FR Soldes] Preview time parse error\", e);\n        return null;\n      }\n    }\n\n    function getNowMsForSchedule() {\n      const preview = readPreviewNowMsFromTitle();\n      if (preview != null) return preview;\n      return Date.now() + (CONFIG.SCHEDULING?.NOW_OFFSET_MS || 0);\n    }\n\n    function isScheduleActive(region, cs) {\n      if (!CONFIG.SCHEDULING?.ENABLE) return true;\n\n      const nowMs = getNowMsForSchedule();\n\n      const byCS = CONFIG.SCHEDULING.BY_CAMPAIGNSITE?.[String(cs || \"\").toLowerCase()];\n      if (byCS \u0026\u0026 byCS.length) return anyWindowActive(nowMs, byCS);\n\n      const byReg = CONFIG.SCHEDULING.BY_REGION?.[region];\n\n      log(\"Schedule check\", {\n        region,\n        campaignSite: cs,\n        nowUtc: new Date(nowMs).toISOString(),\n        byRegion: byReg,\n        title: document.title\n      });\n\n      if (byReg \u0026\u0026 byReg.length) return anyWindowActive(nowMs, byReg);\n\n      const globalWins = CONFIG.SCHEDULING.GLOBAL;\n      if (Array.isArray(globalWins) \u0026\u0026 globalWins.length) return anyWindowActive(nowMs, globalWins);\n\n      return false;\n    }\n\n    function replacePromotionInElement(el) {\n      if (!el || !/promotion/i.test(el.innerHTML)) return 0;\n\n      const before = el.innerHTML;\n      el.innerHTML = el.innerHTML.replace(/promotion/gi, \"Soldes\");\n\n      return before !== el.innerHTML ? 1 : 0;\n    }\n\n    function updatePromotionText() {\n      let count = 0;\n\n      document.querySelectorAll(\".top-info__title\").forEach(el =\u003e {\n        count += replacePromotionInElement(el);\n      });\n\n      document.querySelectorAll(\".slick-track .slick-slide .internal-links-carousel--item\").forEach(el =\u003e {\n        count += replacePromotionInElement(el);\n      });\n\n      document.querySelectorAll('a[href*=\"/fr/reductions/\"]').forEach(el =\u003e {\n        count += replacePromotionInElement(el);\n      });\n\n      document.querySelectorAll('a[href*=\"/fr/fin-de-serie/\"]').forEach(el =\u003e {\n        count += replacePromotionInElement(el);\n      });\n\n      document.querySelectorAll('a[href*=\"/fr/findeserie/\"]').forEach(el =\u003e {\n        count += replacePromotionInElement(el);\n      });\n\n      document.querySelectorAll(\".navigation__gallery a, .nav-non-touch-device a, .nav-touch-device a\").forEach(el =\u003e {\n        if (/promotion/i.test(el.textContent)) {\n          count += replacePromotionInElement(el);\n        }\n      });\n\n      log(\"Text replacement complete\", {\n        count,\n        reductionsLinksFound: document.querySelectorAll('a[href*=\"/fr/reductions/\"]').length,\n        finDeSerieLinksFound: document.querySelectorAll('a[href*=\"/fr/fin-de-serie/\"]').length,\n        finDeSerieNoDashLinksFound: document.querySelectorAll('a[href*=\"/fr/findeserie/\"]').length\n      });\n\n      return count;\n    }\n\n    function run() {\n      log(\"Run triggered\");\n\n      const scheduleOk = isScheduleActive(REGION, campaignSite);\n\n      log(\"Gate checks\", {\n        REGION,\n        sfccCountry,\n        campaignSite,\n        scheduleOk,\n        url: location.href\n      });\n\n      if (!scheduleOk) {\n        log(\"Conditions not met\");\n        return;\n      }\n\n      updatePromotionText();\n      log(\"Complete\");\n    }\n\n    function retryUntilNavFound(maxAttempts = 20, delay = 250) {\n      let attempts = 0;\n\n      function attempt() {\n        attempts++;\n\n        const found =\n          document.querySelectorAll('a[href*=\"/fr/reductions/\"]').length ||\n          document.querySelectorAll('a[href*=\"/fr/fin-de-serie/\"]').length ||\n          document.querySelectorAll('a[href*=\"/fr/findeserie/\"]').length ||\n          document.querySelectorAll(\".navigation__gallery a\").length;\n\n        log(\"Nav retry check\", {\n          attempts,\n          found\n        });\n\n        run();\n\n        if (!found \u0026\u0026 attempts \u003c maxAttempts) {\n          setTimeout(attempt, delay);\n        }\n      }\n\n      attempt();\n    }\n\n    function bindNavTriggers() {\n      const navTriggers = document.querySelectorAll(\n        \"header, .navigation, .js-navigation, .nav-non-touch-device, .nav-touch-device, .navigation__gallery\"\n      );\n\n      navTriggers.forEach(el =\u003e {\n        if (el.hasAttribute(\"data-ct-fr-soldes-bound\")) return;\n\n        el.setAttribute(\"data-ct-fr-soldes-bound\", \"1\");\n\n        el.addEventListener(\"mouseenter\", () =\u003e retryUntilNavFound(), { passive: true });\n        el.addEventListener(\"mouseover\", () =\u003e retryUntilNavFound(), { passive: true });\n        el.addEventListener(\"focusin\", () =\u003e retryUntilNavFound(), { passive: true });\n        el.addEventListener(\"click\", () =\u003e retryUntilNavFound(), { passive: true });\n      });\n\n      log(\"Nav triggers bound\", { count: navTriggers.length });\n    }\n\n    run();\n    retryUntilNavFound();\n\n    setTimeout(run, 500);\n    setTimeout(run, 1500);\n    setTimeout(run, 3000);\n\n    bindNavTriggers();\n\n    setTimeout(bindNavTriggers, 500);\n    setTimeout(bindNavTriggers, 1500);\n    setTimeout(bindNavTriggers, 3000);\n\n    window.CTFrSoldesText = {\n      refresh: run,\n      retryUntilNavFound,\n      bindNavTriggers\n    };\n  } catch (e) {\n    console.warn(\"[CT FR Soldes] Error\", e);\n  }\n})();","trigger":{"include_pages":[{"type":"any"}],"exclude_pages":null},"_id":"6a394b13035508623b2dfae7"},{"uses_overlay":false,"type":"js","parametrized_definition":"exponea.update({\n  UX_Research_List: true\n});","trigger":{"include_pages":[{"url":"research-signup.html","type":"contains"}],"exclude_pages":null},"_id":"6a3bed80307b1106eef09cd7"},{"uses_overlay":false,"type":"js","parametrized_definition":"(function () {\n  // Page guard: only run on the research confirmation page\n  if (window.location.pathname.indexOf('research-confirmed') === -1) {\n    return;\n  }\n\n  var fragment = window.location.hash.replace('#', '').toLowerCase().trim();\n\n  if (!fragment) {\n    return;\n  }\n\n  // Fire-once guard, keyed per fragment, so a reload does not double-count\n  var flagKey = 'research_reward_fired_' + fragment;\n  if (sessionStorage.getItem(flagKey)) {\n    return;\n  }\n\n  switch (fragment) {\n    case 'amazon':\n      exponea.track('research_reward_amazon', {\n        page: 'research-confirmed'\n      });\n      sessionStorage.setItem(flagKey, '1');\n      break;\n\n    case 'ctvoucher':\n      exponea.track('research_reward_ctvoucher', {\n        page: 'research-confirmed'\n      });\n      sessionStorage.setItem(flagKey, '1');\n      break;\n\n    default:\n      break;\n  }\n})();","trigger":{"include_pages":[{"url":"research-confirmed.html","type":"contains"}],"exclude_pages":null},"_id":"6a3bef272681b8019dd771a7"},{"uses_overlay":false,"type":"js","parametrized_definition":"(function () {\n  if (window.__csBrDvarSent) return;          // fire once per page load\n\n  var INTERVAL = 200;\n  var MAX_TRIES = 50;                          // 10s ceiling\n  var tries = 0;\n\n  function send(tests) {\n    window._uxa = window._uxa || [];\n    tests.forEach(function (entry) {\n      if (typeof entry !== 'string') return;\n      var i = entry.lastIndexOf(':');          // variant is after the LAST colon\n      if (i === -1) return;                     // (test names contain colons too)\n      var key = entry.slice(0, i).trim();       // \"CT477: Easy Sleeve Lengths\"\n      var value = entry.slice(i + 1).trim();    // \"D\"\n      if (!key || !value) return;\n      window._uxa.push(['trackDynamicVariable', { key: key, value: value }]);\n    });\n    window.__csBrDvarSent = true;\n  }\n\n  function check() {\n    var t = window.utag_data \u0026\u0026 window.utag_data.bloomreach_tests;\n    if (Array.isArray(t) \u0026\u0026 t.length) { send(t); return; }\n    if (++tries \u003c MAX_TRIES) setTimeout(check, INTERVAL);\n  }\n\n  check();\n})();","trigger":{"include_pages":[{"type":"any"}],"exclude_pages":null},"_id":"6a45082ab74d455f0e26acb6"},{"uses_overlay":false,"type":"js","parametrized_definition":"(() =\u003e {\n  \"use strict\";\n\n  const RUN_FLAG = \"__CT_CA_CH_FR_PROMOTION_TO_SOLDES_SCHEDULED_V1__\";\n  if (window[RUN_FLAG]) return;\n  window[RUN_FLAG] = true;\n\n  try {\n    if (!window.utag_data || !window.utag_data.global) {\n      //console.log(\"[CT CA/CH Soldes] No utag_data.global, exiting\");\n      return;\n    }\n\n    const CONFIG = {\n      DEBUG: false,\n\n      SCHEDULING: {\n        ENABLE: true,\n        NOW_OFFSET_MS: 0,\n\n        PREVIEW: {\n          ENABLE: true,\n          TITLE_REGEX:\n            /[()（）\\[\\]]\\s*(?:\\d{4}-\\d{2}-\\d{2}|\\d{1,2}[.\\-\\/]\\d{1,2}[.\\-\\/]\\d{4})\\s+\\d{1,2}[:hH]\\d{2}(?:\\s*(?:[ap]\\s*\\.?\\s*m\\.?))?(?:\\s*[A-Za-zÀ-ÿ]{2,5})?\\s*[\\])）]?/iu,\n          ASSUME_UTC: true,\n          FORMAT_MAP: {\n            CA: \"DMY\",\n            CH: \"DMY\",\n            DEFAULT: \"DMY\"\n          }\n        },\n\n        BY_CAMPAIGNSITE: {},\n\n        BY_REGION: {\n          CA: [\n            {\n              start: \"2026-07-06T02:00:00Z\",\n              end: \"2026-07-27T02:00:00Z\"\n            }\n          ],\n          CH: [\n            {\n              start: \"2026-07-06T00:00:00Z\",\n              end: \"2026-07-26T23:59:59Z\"\n            }\n          ]\n        },\n\n        GLOBAL: []\n      }\n    };\n\n    const sfccCountry = String(window.utag_data?.global?.sfcc_country || \"\").toUpperCase();\n    const campaignSite = String(window.utag_data?.global?.campaign_site || \"\").toLowerCase();\n    const siteLang = String(window.utag_data?.global?.site_language || \"\").trim().toLowerCase();\n\n    // Only target French-language visitors for CA and CH\n    const REGION =\n      (sfccCountry === \"CA\" \u0026\u0026 siteLang.startsWith(\"fr\")) ? \"CA\" :\n      (sfccCountry === \"CH\" \u0026\u0026 siteLang.startsWith(\"fr\")) ? \"CH\" : \"\";\n\n    function log() {\n      if (!CONFIG.DEBUG) return;\n      //console.log.apply(console, [\"[CT CA/CH Soldes]\"].concat([].slice.call(arguments)));\n    }\n\n    if (!REGION) {\n      log(\"Not CA-FR or CH-FR\", { sfccCountry, siteLang });\n      return;\n    }\n\n    function hasTz(iso) {\n      return /Z|[+\\-]\\d{2}:\\d{2}$/.test(String(iso || \"\"));\n    }\n\n    function parseUtcOrNull(iso) {\n      if (!iso) return null;\n      const s = hasTz(iso) ? iso : iso + \"Z\";\n      const t = Date.parse(s);\n      return Number.isFinite(t) ? t : null;\n    }\n\n    function isNowWithinWindow(nowMs, win) {\n      const start = parseUtcOrNull(win.start) ?? Number.NEGATIVE_INFINITY;\n      const end = parseUtcOrNull(win.end) ?? Number.POSITIVE_INFINITY;\n      return nowMs \u003e= start \u0026\u0026 nowMs \u003c end;\n    }\n\n    function anyWindowActive(nowMs, arr) {\n      if (!Array.isArray(arr) || arr.length === 0) return false;\n      return arr.some(win =\u003e isNowWithinWindow(nowMs, win));\n    }\n\n    function resolveDesiredFormatForPreview() {\n      const langPrefix = String(siteLang || \"\").toLowerCase().split(\"_\")[0];\n      const map = CONFIG.SCHEDULING?.PREVIEW?.FORMAT_MAP || {};\n      return map[`${REGION}:${langPrefix}`] || map[REGION] || map.DEFAULT || \"DMY\";\n    }\n\n    function readPreviewNowMsFromTitle() {\n      try {\n        const cfgPrev = CONFIG?.SCHEDULING?.PREVIEW;\n        if (!cfgPrev || cfgPrev.ENABLE === false) return null;\n\n        const title = String(document?.title || \"\")\n          .replace(/[\\u00A0\\u202F\\u2007\\u2009\\u200A\\u2002-\\u2006]/g, \" \")\n          .trim();\n\n        if (!title) return null;\n        if (cfgPrev.TITLE_REGEX \u0026\u0026 !cfgPrev.TITLE_REGEX.test(title)) return null;\n\n        const reYMD =\n          /[()（）\\[\\]]\\s*(\\d{4})-(\\d{2})-(\\d{2})\\s+(\\d{1,2}):(\\d{2})\\s*[\\])）]?/;\n\n        const reDMYorMDY =\n          /[()（）\\[\\]]\\s*(\\d{1,2})[.\\-\\/](\\d{1,2})[.\\-\\/](\\d{4})\\s+(\\d{1,2})[:hH](\\d{2})(?:\\s*(?:([ap])\\s*\\.?\\s*m\\.?))?(?:\\s*([A-Za-zÀ-ÿ]{2,5}))?\\s*[\\])）]?/iu;\n\n        let utcMs = null;\n        const mYMD = title.match(reYMD);\n\n        if (mYMD) {\n          utcMs = Date.UTC(+mYMD[1], +mYMD[2] - 1, +mYMD[3], +mYMD[4], +mYMD[5], 0, 0);\n        } else {\n          const m = title.match(reDMYorMDY);\n          if (!m) return null;\n\n          let n1 = +m[1];\n          let n2 = +m[2];\n          const yyyy = +m[3];\n          let hh = +m[4];\n          const min = +m[5];\n          const ampmRaw = (m[6] || \"\").toLowerCase();\n\n          let inferredDMY = null;\n          if (n1 \u003e 12 \u0026\u0026 n2 \u003c= 12) inferredDMY = true;\n          else if (n2 \u003e 12 \u0026\u0026 n1 \u003c= 12) inferredDMY = false;\n\n          const configured = resolveDesiredFormatForPreview();\n          const useDMY = inferredDMY === null ? configured !== \"MDY\" : inferredDMY;\n\n          const day = useDMY ? n1 : n2;\n          const month = useDMY ? n2 : n1;\n\n          if (ampmRaw) {\n            const isPM = ampmRaw.startsWith(\"p\");\n            if (hh === 12) hh = isPM ? 12 : 0;\n            else if (isPM) hh += 12;\n          }\n\n          utcMs = Date.UTC(yyyy, month - 1, day, hh, min, 0, 0);\n        }\n\n        if (!Number.isFinite(utcMs)) return null;\n\n        log(\"Preview date detected\", {\n          title,\n          previewUtc: new Date(utcMs).toISOString()\n        });\n\n        return utcMs;\n      } catch (e) {\n        // console.warn(\"[CT CA/CH Soldes] Preview time parse error\", e);\n        return null;\n      }\n    }\n\n    function getNowMsForSchedule() {\n      const preview = readPreviewNowMsFromTitle();\n      if (preview != null) return preview;\n      return Date.now() + (CONFIG.SCHEDULING?.NOW_OFFSET_MS || 0);\n    }\n\n    function isScheduleActive(region, cs) {\n      if (!CONFIG.SCHEDULING?.ENABLE) return true;\n\n      const nowMs = getNowMsForSchedule();\n\n      const byCS = CONFIG.SCHEDULING.BY_CAMPAIGNSITE?.[String(cs || \"\").toLowerCase()];\n      if (byCS \u0026\u0026 byCS.length) return anyWindowActive(nowMs, byCS);\n\n      const byReg = CONFIG.SCHEDULING.BY_REGION?.[region];\n\n      log(\"Schedule check\", {\n        region,\n        campaignSite: cs,\n        nowUtc: new Date(nowMs).toISOString(),\n        byRegion: byReg,\n        title: document.title\n      });\n\n      if (byReg \u0026\u0026 byReg.length) return anyWindowActive(nowMs, byReg);\n\n      const globalWins = CONFIG.SCHEDULING.GLOBAL;\n      if (Array.isArray(globalWins) \u0026\u0026 globalWins.length) return anyWindowActive(nowMs, globalWins);\n\n      return false;\n    }\n\n    // function replacePromotionInElement(el) {\n    //   if (!el || !/promotion/i.test(el.innerHTML)) return 0;\n\n    //   const before = el.innerHTML;\n    //   el.innerHTML = el.innerHTML.replace(/promotion?/gi, \"Soldes\");\n\n    //   return before !== el.innerHTML ? 1 : 0;\n    // }\n    function replacePromotionInElement(el) {\n\t  if (!el || !/promotions?/i.test(el.innerHTML)) return 0;\n\t\n\t  const before = el.innerHTML;\n\t  el.innerHTML = el.innerHTML.replace(/promotions?/gi, \"Soldes\");\n\t\n\t  return before !== el.innerHTML ? 1 : 0;\n\t}\n\n    function updatePromotionText() {\n      let count = 0;\n\n      document.querySelectorAll(\".top-info__title\").forEach(el =\u003e {\n        count += replacePromotionInElement(el);\n      });\n\n      document.querySelectorAll(\".slick-track .slick-slide .internal-links-carousel--item\").forEach(el =\u003e {\n        count += replacePromotionInElement(el);\n      });\n\n      // CH URL patterns: /ch/fr_CH/reductions/ etc.\n      document.querySelectorAll('a[href*=\"/ch/fr_CH/reductions/\"]').forEach(el =\u003e {\n        count += replacePromotionInElement(el);\n      });\n      document.querySelectorAll('a[href*=\"/ch/fr_CH/fin-de-serie/\"]').forEach(el =\u003e {\n        count += replacePromotionInElement(el);\n      });\n      document.querySelectorAll('a[href*=\"/ch/fr_CH/findeserie/\"]').forEach(el =\u003e {\n        count += replacePromotionInElement(el);\n      });\n\n      // CA URL patterns: /ca/fr CA/reductions/ etc. — use partial match safe for both encoded and raw space\n      document.querySelectorAll('a[href*=\"/ca/fr\"]').forEach(el =\u003e {\n        if (/\\/(reductions|fin-de-serie|findeserie)\\//i.test(el.href)) {\n          count += replacePromotionInElement(el);\n        }\n      });\n\n      // Nav links (touch + non-touch + gallery) — catches anything missed above\n      document.querySelectorAll(\".navigation__gallery a, .nav-non-touch-device a, .nav-touch-device a\").forEach(el =\u003e {\n        if (/promotion/i.test(el.textContent)) {\n          count += replacePromotionInElement(el);\n        }\n      });\n\n      log(\"Text replacement complete\", { count });\n\n      return count;\n    }\n\n    function run() {\n      log(\"Run triggered\");\n\n      const scheduleOk = isScheduleActive(REGION, campaignSite);\n\n      log(\"Gate checks\", {\n        REGION,\n        sfccCountry,\n        siteLang,\n        campaignSite,\n        scheduleOk,\n        url: location.href\n      });\n\n      if (!scheduleOk) {\n        log(\"Conditions not met\");\n        return;\n      }\n\n      updatePromotionText();\n      log(\"Complete\");\n    }\n\n    function retryUntilNavFound(maxAttempts = 20, delay = 250) {\n      let attempts = 0;\n\n      function attempt() {\n        attempts++;\n\n        const found =\n          document.querySelectorAll('a[href*=\"/ch/fr_CH/reductions/\"]').length ||\n          document.querySelectorAll('a[href*=\"/ch/fr_CH/fin-de-serie/\"]').length ||\n          document.querySelectorAll('a[href*=\"/ca/fr\"]').length ||\n          document.querySelectorAll(\".navigation__gallery a\").length;\n\n        log(\"Nav retry check\", { attempts, found });\n\n        run();\n\n        if (!found \u0026\u0026 attempts \u003c maxAttempts) {\n          setTimeout(attempt, delay);\n        }\n      }\n\n      attempt();\n    }\n\n    function bindNavTriggers() {\n      const navTriggers = document.querySelectorAll(\n        \"header, .navigation, .js-navigation, .nav-non-touch-device, .nav-touch-device, .navigation__gallery\"\n      );\n\n      navTriggers.forEach(el =\u003e {\n        if (el.hasAttribute(\"data-ct-ca-ch-soldes-bound\")) return;\n\n        el.setAttribute(\"data-ct-ca-ch-soldes-bound\", \"1\");\n\n        el.addEventListener(\"mouseenter\", () =\u003e retryUntilNavFound(), { passive: true });\n        el.addEventListener(\"mouseover\", () =\u003e retryUntilNavFound(), { passive: true });\n        el.addEventListener(\"focusin\", () =\u003e retryUntilNavFound(), { passive: true });\n        el.addEventListener(\"click\", () =\u003e retryUntilNavFound(), { passive: true });\n      });\n\n      log(\"Nav triggers bound\", { count: navTriggers.length });\n    }\n\n    run();\n    retryUntilNavFound();\n\n    setTimeout(run, 500);\n    setTimeout(run, 1500);\n    setTimeout(run, 3000);\n\n    bindNavTriggers();\n\n    setTimeout(bindNavTriggers, 500);\n    setTimeout(bindNavTriggers, 1500);\n    setTimeout(bindNavTriggers, 3000);\n\n    window.CTCaChSoldesText = {\n      refresh: run,\n      retryUntilNavFound,\n      bindNavTriggers\n    };\n  } catch (e) {\n    // console.warn(\"[CT CA/CH Soldes] Error\", e);\n  }\n})();","trigger":{"include_pages":[{"type":"any"}],"exclude_pages":null},"_id":"6a47d03f5ac1f968f5547102"},{"uses_overlay":false,"type":"js","parametrized_definition":"\n(function () {\n  var PDP_SELECTOR = 'p.price-diff';\n  var REVEAL_TIMEOUT_MS = 1500; // safety net if fetch is slow/fails\n\n  // Hide the element immediately (before we know the outcome) so the\n  // original \"Save £xx today\" text never flashes before we either\n  // swap in the promo copy or decide to leave it as-is. Uses opacity,\n  // not display:none, so layout/height doesn't shift when revealed.\n  var style = document.createElement('style');\n  style.textContent =\n    PDP_SELECTOR + ':not([data-price-diff-ready]) { opacity: 0; } ' +\n    PDP_SELECTOR + '[data-price-diff-ready] { opacity: 1; transition: opacity 0.15s ease; }';\n  document.head.appendChild(style);\n\n  function revealAll() {\n    document.querySelectorAll(PDP_SELECTOR).forEach(function (el) {\n      if (!el.dataset.priceDiffReady) el.dataset.priceDiffReady = 'true';\n    });\n  }\n\n  // Safety net: never leave the element invisible indefinitely,\n  // even if the homepage fetch hangs or errors unexpectedly.\n  setTimeout(revealAll, REVEAL_TIMEOUT_MS);\n\n  var HP_TITLE_CLASS_RE = /text-info-title-\\d+--title/;\n\n  // Finds the homepage URL by reading the site's own \"go to homepage\"\n  // link (logo, header, rel=\"home\", etc.) rather than guessing a\n  // locale prefix pattern. This works for ANY locale/language because\n  // it uses whatever link the site itself already points home with —\n  // no need to enumerate /fr/, /de/, /es/, etc.\n  function getHomepageUrl() {\n    var selectors = [\n      'a[rel=\"home\"]',\n      'a.logo[href]',\n      '.header-logo a[href]',\n      '.logo a[href]',\n      'header a[aria-label*=\"home\" i]',\n      'header a[href=\"/\"]',\n      'a[href][class*=\"logo\" i]'\n    ];\n\n    for (var i = 0; i \u003c selectors.length; i++) {\n      var el = document.querySelector(selectors[i]);\n      if (el \u0026\u0026 el.href) {\n        // console.debug('[price-diff patch] homepage link matched via selector:', selectors[i], '-\u003e', el.href);\n        return el.href;\n      }\n    }\n\n    // console.debug('[price-diff patch] no homepage link found, falling back to origin root');\n    return window.location.origin + '/';\n  }\n\n  var HP_URL = getHomepageUrl();\n\n  var cachedPromoHTML = null; // e.g. \"+ Extra 10% Off Use Code: \u003cstrong\u003eSALE10\u003c/strong\u003e\"\n  var fetchInFlight = null;\n  var initialCheckDone = false;\n\n  function extractPromoFromHomepageDoc(doc) {\n    // Scope to the hero container first, so we don't accidentally\n    // pick up unrelated promo/editorial blocks elsewhere on the\n    // homepage that happen to use the same title component class.\n    var heroRoot =\n      doc.querySelector('.experience-textInfoCtaWrapper') ||\n      doc.querySelector('.experience-region.experience-textInfoCtaWrapper') ||\n      doc; // fallback: whole doc, if hero wrapper class isn't found\n\n    if (heroRoot === doc) {\n      //console.debug('[price-diff patch] hero wrapper not found, searching full document (may pick up unrelated copy)');\n    }\n\n    var candidates = Array.prototype.filter.call(\n      heroRoot.querySelectorAll('p, h1, h2'),\n      function (el) {\n        return Array.prototype.some.call(el.classList, function (cls) {\n          return HP_TITLE_CLASS_RE.test(cls);\n        });\n      }\n    );\n\n    console.debug(\n      '[price-diff patch] candidates found:',\n      candidates.map(function (el) { return el.textContent.trim(); })\n    );\n\n    // The \"extra X% off\" line consistently starts with a \"+\" in every\n    // locale we've seen (e.g. \"+ Extra 10% Off\", \"+ 10 % Supplémentaires\").\n    // That's more reliable than matching \"%\", which the \"up to X% off\"\n    // line also contains.\n    var extraOffEl = candidates.find(function (el) {\n      return el.textContent.trim().indexOf('+') === 0;\n    });\n\n    // Fallback if no locale-specific \"+\" prefix is used\n    if (!extraOffEl) {\n      extraOffEl = candidates.find(function (el) {\n        var hasPdRed = Array.prototype.some.call(el.classList, function (cls) {\n          return cls === 'pd-red';\n        });\n        return hasPdRed;\n      });\n    }\n\n    // The \"code\" line: don't rely on \u003cstrong\u003e (not always present).\n    // Instead, detect it by shape — an uppercase/alphanumeric token\n    // that looks like a promo code, usually the last token on the line.\n    function extractCodeToken(text) {\n      var afterColon = text.match(/:\\s*([A-Za-z0-9]{3,20})\\s*$/);\n      if (afterColon) return afterColon[1];\n\n      var tokens = text.trim().split(/\\s+/);\n      var last = tokens[tokens.length - 1];\n      if (/^[A-Za-z0-9]{3,20}$/.test(last) \u0026\u0026 /\\d/.test(last)) return last;\n      return null;\n    }\n\n    var useCodeEl = null;\n    var codeToken = null;\n    for (var i = 0; i \u003c candidates.length; i++) {\n      if (candidates[i] === extraOffEl) continue;\n      var token = extractCodeToken(candidates[i].textContent);\n      if (token) {\n        useCodeEl = candidates[i];\n        codeToken = token;\n        break;\n      }\n    }\n\n    console.debug(\n      '[price-diff patch] extraOffEl:', extraOffEl ? extraOffEl.textContent.trim() : null,\n      '| useCodeEl:', useCodeEl ? useCodeEl.textContent.trim() : null,\n      '| codeToken:', codeToken\n    );\n\n    // Explicit guard: if the homepage doesn't currently show both an\n    // \"extra X% off\" line AND a matching code, treat this as \"no\n    // active sale\" and make NO changes to the PDP element. This is\n    // what keeps the PDP safe across timezones — e.g. if the US/CA\n    // sale ends later than the UK's, each market's script simply\n    // checks its own live homepage and skips silently once that\n    // market's promo copy is no longer there.\n    var saleIsActive = !!(extraOffEl \u0026\u0026 useCodeEl \u0026\u0026 codeToken);\n\n    if (!saleIsActive) {\n      console.debug('[price-diff patch] No active sale detected on homepage — leaving PDP copy unchanged');\n      return null;\n    }\n\n    var extraOffText = extraOffEl.textContent.trim();\n    var codeLineText = useCodeEl.textContent.trim();\n    // Keep whatever label precedes the code (\"Code :\", \"Código:\", etc.)\n    // fully dynamic — just re-wrap the detected code token in \u003cstrong\u003e.\n    // Normalize whitespace and guarantee exactly one space before the\n    // code, regardless of how the source spaces \"Code :\" vs \"Code:\".\n    var labelText = codeLineText.replace(codeToken, '').replace(/\\s+/g, ' ').trim();\n    var codeLineHTML = (labelText ? labelText + '\\u00A0' : '') + '\u003cstrong\u003e' + codeToken + '\u003c/strong\u003e';\n\n    return extraOffText + ' ' + codeLineHTML;\n  }\n\n  function fetchPromoCopy() {\n    if (cachedPromoHTML) return Promise.resolve(cachedPromoHTML);\n    if (fetchInFlight) return fetchInFlight;\n\n    // console.debug('[price-diff patch] fetching homepage URL:', HP_URL);\n\n    fetchInFlight = fetch(HP_URL, { credentials: 'same-origin' })\n      .then(function (res) {\n        if (!res.ok) throw new Error('Homepage fetch failed: ' + res.status);\n        return res.text();\n      })\n      .then(function (html) {\n        var doc = new DOMParser().parseFromString(html, 'text/html');\n        var promo = extractPromoFromHomepageDoc(doc);\n        if (!promo) throw new Error('Promo copy not found on homepage');\n        cachedPromoHTML = promo;\n        return promo;\n      })\n      .catch(function (err) {\n        console.warn('[price-diff patch]', err.message);\n        return null; // fail silently on PDP, leave original copy untouched\n      });\n\n    return fetchInFlight;\n  }\n\n  function applyPromoCopy(promoHTML) {\n    initialCheckDone = true;\n    if (!promoHTML) {\n      console.debug('[price-diff patch] No promo copy to apply — PDP element left as-is');\n      revealAll(); // no sale: reveal original copy right away, don't wait for timeout\n      return;\n    }\n    document.querySelectorAll(PDP_SELECTOR).forEach(function (el) {\n      if (el.dataset.priceDiffPatched === 'true') return;\n      el.innerHTML = promoHTML;\n      el.dataset.priceDiffPatched = 'true';\n      el.dataset.priceDiffReady = 'true';\n    });\n  }\n\n  function init() {\n    // Only bother fetching if the target element actually exists on this page\n    if (!document.querySelector(PDP_SELECTOR)) return;\n    fetchPromoCopy().then(applyPromoCopy);\n  }\n\n  init();\n\n  // Re-apply (from cache, no re-fetch) if the PDP block re-renders,\n  // e.g. on color/size variant switch\n  var observer = new MutationObserver(function (mutations) {\n    var relevant = mutations.some(function (m) {\n      return m.type === 'childList' || m.type === 'characterData';\n    });\n    if (!relevant) return;\n    if (cachedPromoHTML) {\n      applyPromoCopy(cachedPromoHTML);\n    } else if (initialCheckDone) {\n      // No sale was found on the initial check — a variant re-render\n      // just brought back the original copy, so reveal it immediately\n      // rather than waiting for the fallback timeout.\n      revealAll();\n    }\n  });\n\n  observer.observe(document.body, {\n    childList: true,\n    subtree: true,\n    characterData: true\n  });\n})();","trigger":{"include_pages":[{"type":"any"}],"exclude_pages":null},"_id":"6a5e0752ff7322063f6622e9"},{"uses_overlay":false,"type":"js","parametrized_definition":"(function () {\n  // console.log('%c[CTA-HIDE] Script started', 'color: orange; font-weight: bold;');\n\n  var HIDE_ON_CATEGORIES = [\n    'clearance',\n    'sale-top-picks',\n    'clr_shirts',\n    'clr_shirts-formal-shirts',\n    'clr_shirts-casual-shirts',\n    'clr_polo_shirts',\n    'clr_suits',\n    'clr_trousers',\n    'clr_knitwear',\n    'clr_blazers',\n    'clr_outerwear',\n    'clr_shoes',\n    'clr_accessories',\n    'outlet-suit-jackets',\n    'outlet-suit-trousers',\n    'outlet-waistcoats',\n    'clr_ties'\n  ];\n\n  function getPageCategory() {\n    // console.log('[CTA-HIDE] Checking window.utag_data...', window.utag_data);\n\n    if (!window.utag_data) {\n      // console.warn('[CTA-HIDE] ❌ utag_data does not exist yet on window');\n      return null;\n    }\n\n    // console.log('[CTA-HIDE] utag_data.page:', window.utag_data.page);\n\n    if (!window.utag_data.page) {\n      // console.warn('[CTA-HIDE] ❌ utag_data.page is missing');\n      return null;\n    }\n\n    var pageType = window.utag_data.page.type;\n    // console.log('[CTA-HIDE] page.type found:', JSON.stringify(pageType));\n\n    if (pageType !== 'category') {\n      // console.log('[CTA-HIDE] ℹ️ Not a category page (type=\"' + pageType + '\") — skipping entirely.');\n      return null;\n    }\n\n    var category = window.utag_data.page.category;\n    // console.log('[CTA-HIDE] Raw category value found:', JSON.stringify(category));\n\n    if (!category) {\n      // console.warn('[CTA-HIDE] ❌ category is empty/undefined');\n      return null;\n    }\n\n    return String(category).toLowerCase().trim();\n  }\n\n  function hideCtaIfNeeded() {\n    // console.log('%c[CTA-HIDE] Running hideCtaIfNeeded()', 'color: cyan;');\n\n    var category = getPageCategory();\n    if (!category) {\n      // console.warn('[CTA-HIDE] Stopping — no category available');\n      return;\n    }\n\n    // console.log('[CTA-HIDE] Normalized category:', category);\n    // console.log('[CTA-HIDE] Comparing against list:', HIDE_ON_CATEGORIES);\n\n    var matchedValue = HIDE_ON_CATEGORIES.find(function (val) {\n      return val.toLowerCase() === category;\n    });\n\n    if (!matchedValue) {\n      // console.log('[CTA-HIDE] ℹ️ Category \"' + category + '\" is NOT in the hide list. CTA stays visible.');\n      return;\n    }\n\n    // console.log('[CTA-HIDE] ✅ Match found:', matchedValue, '— attempting to hide CTA');\n\n    var selectors = [\n      '.experience-component.experience-assets-textInfoCta',\n      '[class*=\"text-info-cta-\"][class*=\"--cta\"]'\n    ];\n\n    var allFound = [];\n    selectors.forEach(function (sel) {\n      var nodes = document.querySelectorAll(sel);\n      // console.log('[CTA-HIDE] Selector \"' + sel + '\" found', nodes.length, 'element(s)');\n      nodes.forEach(function (node) { allFound.push(node); });\n    });\n\n    if (allFound.length === 0) {\n      // console.error('[CTA-HIDE] ❌ No elements found at all. Check selectors against actual page markup.');\n      return;\n    }\n\n    var uniqueEls = Array.from(new Set(allFound));\n    // console.log('[CTA-HIDE] Hiding', uniqueEls.length, 'unique element(s)');\n\n    uniqueEls.forEach(function (el, i) {\n      // console.log('[CTA-HIDE] Hiding element #' + i, el, '— outerHTML snippet:', el.outerHTML.slice(0, 150));\n      el.style.setProperty('display', 'none', 'important');\n    });\n\n    // console.log('%c[CTA-HIDE] ✅ Done', 'color: lime; font-weight: bold;');\n  }\n\n  // console.log('[CTA-HIDE] document.readyState:', document.readyState);\n\n  if (document.readyState === 'loading') {\n    // console.log('[CTA-HIDE] DOM still loading — waiting for DOMContentLoaded');\n    document.addEventListener('DOMContentLoaded', hideCtaIfNeeded);\n  } else {\n    // console.log('[CTA-HIDE] DOM already ready — running immediately');\n    hideCtaIfNeeded();\n  }\n\n  document.addEventListener('utag_data_ready', function () {\n    // console.log('[CTA-HIDE] utag_data_ready event fired — re-running');\n    hideCtaIfNeeded();\n  });\n\n  var attempts = 0;\n  var poll = setInterval(function () {\n    attempts++;\n    if (window.utag_data \u0026\u0026 window.utag_data.page) {\n      // console.log('[CTA-HIDE] Poll detected utag_data.page after', attempts, 'attempts — re-running');\n      clearInterval(poll);\n      hideCtaIfNeeded();\n    } else if (attempts \u003e 20) {\n      // console.warn('[CTA-HIDE] Poll gave up after 20 attempts — utag_data.page never appeared');\n      clearInterval(poll);\n    }\n  }, 500);\n})();","trigger":{"include_pages":[{"type":"any"}],"exclude_pages":null},"_id":"6a5e4c05d5e004890b2ea80a"},{"uses_overlay":false,"type":"js","parametrized_definition":"/* ------------------------------------------------------------------\n * CT · Collar label \"New\" flag\n *\n * Scope gates (all read from utag_data, fail closed):\n *   Market · global.sfcc_country in UK, US\n *   Page   · page.type equals \"category\"  (runs PLP tile scan)\n *            OR products[0].id in TARGET_IDS  (runs PDP scan)\n *\n * Injects a coloured, localised \"New\" prefix into the collar attribute\n * label for a fixed list of button-down product IDs.\n * ------------------------------------------------------------------ */\n(function () {\n  'use strict';\n\n  /* ================================================== config */\n\n  var COLOUR = '#936F1F';\n  var DEBUG = false;\n\n  var TARGET_IDS = [\n    'SCB0005WHT', 'SCB0008WHT', 'SCB0002WHT',\n    'SCB0005SKY', 'SCB0008SKY', 'SCB0002SKY',\n    'SCB0007RYL', 'SCB0010RYL', 'SCB0004RYL',\n    'SCB0006CFW', 'SCB0009CFW', 'SCB0003CFW',\n    'SCB0010CFW', 'SCB0007CFW', 'SCB0004CFW'\n  ];\n\n  var ALLOWED_COUNTRIES = ['UK', 'US'];\n  var CATEGORY_PAGE_TYPES = ['category'];\n\n  /* Copy retained for all locales, but UK and US both resolve to EN\n     under the current market gate. */\n  var COPY = {\n    en: 'New',\n    fr: 'Nouveau',\n    de: 'Neu',\n    it: 'Nuovo',\n    es: 'Nuevo'\n  };\n\n  /* Order matters for the substring fallback; 'en' is checked last. */\n  var LANG_ORDER = ['fr', 'de', 'it', 'es', 'en'];\n  var DEFAULT_LANG = 'en';\n\n  var CONFIG = {\n    separator: ' \\u00B7 ',        // middle dot\n    includeTileInfoLabel: false   // second collar label inside the tile info block\n  };\n\n  var SEL = {\n    plpTile: '.product-tile[data-prod-id], .js-product-tile[data-prod-id], .js-product-tile-container[data-prod-id]',\n    plpLabel: '.product-tile__collar-label',\n    plpInfoLabel: '.pdp-main__collar-label.product-dot-collar-type',\n    pdpLabel: '.pdp-main__collar-label.js-collar-type-label'\n  };\n\n  var FLAG_ATTR = 'data-ct-new-collar';\n  var LANG_ATTR = 'data-ct-new-collar-lang';\n  var FLAG_CLASS = 'ct-new-collar-flag';\n\n  /* ================================================== helpers */\n\n  function log() {\n    if (!DEBUG || !window.console) return;\n    try {\n      console.log.apply(console, ['[ct-new-collar]'].concat([].slice.call(arguments)));\n    } catch (e) { /* noop */ }\n  }\n\n  function inList(value, list) {\n    if (!value) return false;\n    var v = String(value).trim().toUpperCase();\n    for (var i = 0; i \u003c list.length; i++) {\n      if (v === String(list[i]).trim().toUpperCase()) return true;\n    }\n    return false;\n  }\n\n  var idSet = Object.create(null);\n  for (var i = 0; i \u003c TARGET_IDS.length; i++) {\n    idSet[String(TARGET_IDS[i]).trim().toUpperCase()] = true;\n  }\n\n  function isTarget(id) {\n    if (!id) return false;\n    return idSet[String(id).trim().toUpperCase()] === true;\n  }\n\n  /* ================================================== data layer reads */\n\n  function utag() {\n    try {\n      return window.utag_data || null;\n    } catch (e) {\n      return null;\n    }\n  }\n\n  function sfccCountry() {\n    var d = utag();\n    if (d \u0026\u0026 d.global \u0026\u0026 d.global.sfcc_country) return String(d.global.sfcc_country);\n    return '';\n  }\n\n  function pageType() {\n    var d = utag();\n    if (d \u0026\u0026 d.page \u0026\u0026 d.page.type) return String(d.page.type);\n    return '';\n  }\n\n  /* utag_data.products[0].id, tolerating a bare string entry. */\n  function firstProductId() {\n    var d = utag();\n    if (!d) return '';\n    var list = d.products;\n    if (Object.prototype.toString.call(list) !== '[object Array]' || !list.length) return '';\n    var first = list[0];\n    if (typeof first === 'string') return first;\n    if (first \u0026\u0026 typeof first === 'object' \u0026\u0026 first.id) return String(first.id);\n    return '';\n  }\n\n  /* Fails closed: an unpopulated data layer means no injection. Retry\n     scans pick it up once Tealium has run. */\n  function countryAllowed() {\n    return inList(sfccCountry(), ALLOWED_COUNTRIES);\n  }\n\n  function isCategoryPage() {\n    return inList(pageType(), CATEGORY_PAGE_TYPES);\n  }\n\n  function isTargetProductPage() {\n    return isTarget(firstProductId());\n  }\n\n  /* ================================================== language */\n\n  function rawSiteLanguage() {\n    var d = utag();\n    if (d \u0026\u0026 d.global \u0026\u0026 d.global.site_language) return String(d.global.site_language);\n    return '';\n  }\n\n  /* Returns a supported two-letter code, or null when not resolvable. */\n  function resolveLang() {\n    var raw = rawSiteLanguage();\n    if (!raw) {\n      // Fallback only: document language attribute.\n      raw = (document.documentElement \u0026\u0026 document.documentElement.lang) || '';\n    }\n    if (!raw) return null;\n\n    var norm = raw.toLowerCase().replace(/[^a-z]+/g, '_');\n\n    // 1. Leading token match, e.g. \"en\", \"en_GB\", \"en-US\".\n    var lead = norm.split('_')[0];\n    for (var i = 0; i \u003c LANG_ORDER.length; i++) {\n      if (lead === LANG_ORDER[i]) return LANG_ORDER[i];\n    }\n\n    // 2. Substring fallback, e.g. \"site_en_gb\", \"english\".\n    for (var j = 0; j \u003c LANG_ORDER.length; j++) {\n      if (norm.indexOf(LANG_ORDER[j]) !== -1) return LANG_ORDER[j];\n    }\n\n    return null;\n  }\n\n  var currentLang = null;\n\n  function activeLang() {\n    var resolved = resolveLang();\n    if (resolved \u0026\u0026 resolved !== currentLang) {\n      currentLang = resolved;\n      log('language resolved as', currentLang, 'from', rawSiteLanguage());\n    }\n    return currentLang || DEFAULT_LANG;\n  }\n\n  function copyFor(lang) {\n    return COPY[lang] || COPY[DEFAULT_LANG];\n  }\n\n  /* ================================================== injection */\n\n  function injectCollar(el, lang) {\n    if (!el) return;\n    if (el.getAttribute(FLAG_ATTR) === '1') return;\n    if (el.querySelector \u0026\u0026 el.querySelector('.' + FLAG_CLASS)) {\n      el.setAttribute(FLAG_ATTR, '1');\n      el.setAttribute(LANG_ATTR, lang);\n      return;\n    }\n\n    var badge = document.createElement('span');\n    badge.className = FLAG_CLASS;\n    badge.textContent = copyFor(lang);\n    badge.style.color = COLOUR;\n    badge.style.fontWeight = '700';\n    badge.style.textTransform = 'uppercase';\n\n    el.insertBefore(document.createTextNode(CONFIG.separator), el.firstChild);\n    el.insertBefore(badge, el.firstChild);\n    el.setAttribute(FLAG_ATTR, '1');\n    el.setAttribute(LANG_ATTR, lang);\n\n    log('injected', lang, el);\n  }\n\n  /* Rewrite any badge injected before the language resolved. */\n  function reconcileLang(lang) {\n    var stale = document.querySelectorAll(\n      '[' + LANG_ATTR + ']:not([' + LANG_ATTR + '=\"' + lang + '\"])'\n    );\n    for (var i = 0; i \u003c stale.length; i++) {\n      var badge = stale[i].querySelector('.' + FLAG_CLASS);\n      if (badge) badge.textContent = copyFor(lang);\n      stale[i].setAttribute(LANG_ATTR, lang);\n    }\n    if (stale.length) log('relabelled', stale.length, 'badge(s) to', lang);\n  }\n\n  /* ================================================== scanning */\n\n  function scanPlp(root, lang) {\n    var tiles = root.querySelectorAll(SEL.plpTile);\n    for (var i = 0; i \u003c tiles.length; i++) {\n      var tile = tiles[i];\n      if (!isTarget(tile.getAttribute('data-prod-id'))) continue;\n\n      var labels = tile.querySelectorAll(SEL.plpLabel);\n      for (var j = 0; j \u003c labels.length; j++) injectCollar(labels[j], lang);\n\n      if (CONFIG.includeTileInfoLabel) {\n        var infoLabels = tile.querySelectorAll(SEL.plpInfoLabel);\n        for (var k = 0; k \u003c infoLabels.length; k++) injectCollar(infoLabels[k], lang);\n      }\n    }\n  }\n\n  function scanPdp(root, lang) {\n    var labels = root.querySelectorAll(SEL.pdpLabel);\n    for (var i = 0; i \u003c labels.length; i++) injectCollar(labels[i], lang);\n  }\n\n  function scan() {\n    try {\n      if (!countryAllowed()) {\n        log('skipped, country', sfccCountry() || '(unset)');\n        return;\n      }\n\n      var category = isCategoryPage();\n      var productPage = isTargetProductPage();\n\n      if (!category \u0026\u0026 !productPage) {\n        log('skipped, page.type', pageType() || '(unset)', 'products[0].id', firstProductId() || '(unset)');\n        return;\n      }\n\n      var lang = activeLang();\n      reconcileLang(lang);\n\n      if (category) scanPlp(document, lang);\n      if (productPage) scanPdp(document, lang);\n    } catch (e) {\n      log('scan error', e);\n    }\n  }\n\n  /* ================================================== lifecycle */\n\n  var queued = false;\n  function queueScan() {\n    if (queued) return;\n    queued = true;\n    var run = function () {\n      queued = false;\n      scan();\n    };\n    if (window.requestAnimationFrame) {\n      window.requestAnimationFrame(run);\n    } else {\n      setTimeout(run, 16);\n    }\n  }\n\n  function observe() {\n    if (!window.MutationObserver || !document.body) return;\n    var observer = new MutationObserver(function (mutations) {\n      for (var i = 0; i \u003c mutations.length; i++) {\n        if (mutations[i].addedNodes \u0026\u0026 mutations[i].addedNodes.length) {\n          queueScan();\n          return;\n        }\n      }\n    });\n    observer.observe(document.body, { childList: true, subtree: true });\n  }\n\n  function init() {\n    scan();\n    observe();\n    // Catch late data layer population and deferred tile renders.\n    setTimeout(scan, 500);\n    setTimeout(scan, 1500);\n    setTimeout(scan, 3000);\n  }\n\n  if (document.readyState === 'loading') {\n    document.addEventListener('DOMContentLoaded', init);\n  } else {\n    init();\n  }\n})();","trigger":{"include_pages":[{"type":"any"}],"exclude_pages":null},"_id":"6a74b7d89dd226c6f07b9b65"}],"vars":{"data":[{"id":"6862a355ce623f4f19e39fc9","name":"Global Tracker Object","variable":{"type":"custom_function","custom_function":{"body":"const globalTrackerObj = {\n    shirts: {\n        en_GB: {\n            Copy: 'Shirts \u0026 Polos',\n            NumberOfProductsToActivateMb: 4,\n            AcqNumberOfProductsToActivateMb: 3,\n            PlpLink: 'https://www.charlestyrwhitt.com/uk/mens-shirts/',\n            MbPrice: '£33',\n        },\n        en_US: {\n            Copy: 'Shirts \u0026 Polos',\n            NumberOfProductsToActivateMb: 4,\n            AcqNumberOfProductsToActivateMb: 3,\n            PlpLink: 'https://www.charlestyrwhitt.com/us/mens-shirts/',\n            MbPrice: '$49.75',\n        },\n        en_CA: {\n            Copy: 'Shirts \u0026 Polos',\n            NumberOfProductsToActivateMb: 4,\n            AcqNumberOfProductsToActivateMb: 3,\n            PlpLink: 'https://www.charlestyrwhitt.com/ca/en_CA/mens-shirts/',\n            MbPrice: 'C$99.75',\n        },\n        en_CH: {\n            Copy: 'Shirts \u0026 Polos',\n            NumberOfProductsToActivateMb: 4,\n            AcqNumberOfProductsToActivateMb: 3,\n            PlpLink: 'https://www.charlestyrwhitt.com/ch/en_CH/mens-shirts/',\n            MbPrice: 'CHF 62,25',\n        },\n        en_IE: {\n            Copy: 'Shirts \u0026 Polos',\n            NumberOfProductsToActivateMb: 4,\n            AcqNumberOfProductsToActivateMb: 3,\n            PlpLink: 'https://www.charlestyrwhitt.com/eu/mens-shirts/',\n            MbPrice: '49.75 €',\n        },\n        nl_NL: {\n            Copy: 'Shirts \u0026 Polos',\n            NumberOfProductsToActivateMb: 4,\n            AcqNumberOfProductsToActivateMb: 3,\n            PlpLink: 'https://www.charlestyrwhitt.com/nl/en_NL/mens-shirts/',\n            MbPrice: '49.75 €',\n        },\n        fr_CH: {\n            Copy: 'Chemises ou Polos',\n            NumberOfProductsToActivateMb: 4,\n            AcqNumberOfProductsToActivateMb: 3,\n            PlpLink: 'https://www.charlestyrwhitt.com/ch/fr_CH/mens-shirts/',\n            MbPrice: 'CHF 62,25',\n        },\n        de_CH: {\n            Copy: 'Hemden \u0026 Polos',\n            NumberOfProductsToActivateMb: 4,\n            AcqNumberOfProductsToActivateMb: 3,\n            PlpLink: 'https://www.charlestyrwhitt.com/ch/de_CH/mens-shirts/',\n            MbPrice: 'CHF 62,25',\n        },\n        fr_CA: {\n            Copy: 'Chemises ou Polos',\n            NumberOfProductsToActivateMb: 4,\n            AcqNumberOfProductsToActivateMb: 3,\n            PlpLink: 'https://www.charlestyrwhitt.com/ca/fr_CA/mens-shirts/',\n            MbPrice: 'C$99.75',\n        },\n        de_DE: {\n            Copy: 'Hemden \u0026 Polos',\n            NumberOfProductsToActivateMb: 4,\n            AcqNumberOfProductsToActivateMb: 3,\n            PlpLink: 'https://www.charlestyrwhitt.com/de/herren-hemden/',\n            MbPrice: '49.75 €',\n        },\n        fr_FR: {\n            Copy: 'Chemises ou Polos',\n            NumberOfProductsToActivateMb: 4,\n            AcqNumberOfProductsToActivateMb: 3,\n            PlpLink: 'https://www.charlestyrwhitt.com/fr/chemises-homme/',\n            MbPrice: '49.75 €',\n        },\n        en_AU: {\n            Copy: 'Shirts \u0026 Polos',\n            NumberOfProductsToActivateMb: 4,\n            AcqNumberOfProductsToActivateMb: 3,\n            PlpLink: 'https://www.charlestyrwhitt.com/au/mens-shirts/',\n            MbPrice: '$74.75',\n        },\n        en: {\n            Copy: 'Shirts \u0026 Polos',\n            NumberOfProductsToActivateMb: 4,\n            PlpLink: '/intl/mens-shirts/',\n            mbSavings: ['10% off', '15% off', '20% off'],\n        },\n        Icon: '/on/demandware.static/-/Library-Sites-CTShirtsSharedLibrary/default/mb-tracker/shirt-icon-default.svg',\n    },\n\n    trousers: {\n        en_GB: {\n            Copy: 'Trousers \u0026 Shorts',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/uk/mens-trousers/',\n            MbPrice: '£39.95',\n        },\n        en_CH: {\n            Copy: 'Trousers \u0026 Shorts',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/ch/en_CH/mens-trousers/',\n            MbPrice: 'CHF 64,00',\n        },\n        en_US: {\n            Copy: 'Pants \u0026 Shorts',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/us/mens-pants/',\n            MbPrice: '$59.00',\n        },\n        en_CA: {\n            Copy: 'Pants \u0026 Shorts',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/ca/en_CA/mens-pants/',\n            MbPrice: 'C$169.00',\n        },\n        en_IE: {\n            Copy: 'Trousers \u0026 Shorts',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/eu/mens-trousers/',\n            MbPrice: '€49.95',\n        },\n        nl_NL: {\n            Copy: 'Trousers \u0026 Shorts',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/nl/en_NL/mens-trousers/',\n            MbPrice: '€49.95',\n        },\n        fr_CH: {\n            Copy: 'Pantalons et Shorts',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/ch/fr_CH/mens-trousers/',\n            MbPrice: 'CHF 64,00',\n        },\n        de_CH: {\n            Copy: 'Hosen \u0026 Shorts',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/ch/de_CH/mens-trousers/',\n            MbPrice: 'CHF 64,00',\n        },\n        fr_CA: {\n            Copy: 'Pantalons et Shorts',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/ca/fr_CA/mens-trousers/',\n            MbPrice: 'C$169.00',\n        },\n        de_DE: {\n            Copy: 'Hosen \u0026 Shorts',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/de/herren-hosen/',\n            MbPrice: '€49.95',\n        },\n        fr_FR: {\n            Copy: 'Pantalons et Shorts',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/fr/pantalons-homme/',\n            MbPrice: '€49.95',\n        },\n        en_AU: {\n            Copy: 'Pants \u0026 Shorts',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/au/mens-pants/',\n            MbPrice: '$59.00',\n        },\n        en: {\n            Copy: 'Trousers \u0026 Shorts',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: '/intl/mens-trousers/',\n            mbSavings: ['20% off'],\n        },\n        Icon: '/on/demandware.static/-/Library-Sites-CTShirtsSharedLibrary/default/mb-tracker/pants-icon-default.svg',\n    },\n\n\n    knitwear: {\n        en_GB: {\n            Copy: 'Jumpers \u0026 Cardigans',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/uk/mens-knitwear/',\n            MbPrice: '£59.95',\n        },\n        en_CH: {\n            Copy: 'Jumpers \u0026 Cardigans',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/ch/en_CH/mens-knitwear/',\n            MbPrice: 'CHF 104,00',\n        },\n        en_US: {\n            Copy: 'Sweaters \u0026 Cardigans',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/us/mens-sweaters/',\n            MbPrice: '$79.00',\n        },\n        en_CA: {\n            Copy: 'Sweaters \u0026 Cardigans',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/ca/en_CA/mens-sweaters/',\n            MbPrice: 'C$149.00',\n        },\n        en_IE: {\n            Copy: 'Jumpers \u0026 Cardigans',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/eu/mens-knitwear/',\n            MbPrice: '€79.95',\n        },\n        nl_NL: {\n            Copy: 'Jumpers \u0026 Cardigans',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/nl/en_NL/mens-knitwear/',\n            MbPrice: '€79.95',\n        },\n        fr_CH: {\n            Copy: 'Pulls et Cardigans',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/ch/fr_CH/mens-knitwear/',\n            MbPrice: 'CHF 104,00',\n        },\n        de_CH: {\n            Copy: 'Pullover \u0026 Strickjacken',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/ch/de_CH/mens-knitwear/',\n            MbPrice: 'CHF 104,00',\n        },\n        fr_CA: {\n            Copy: 'Pulls et Cardigans',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/ca/fr_CA/mens-knitwear/',\n            MbPrice: 'C$149.00',\n        },\n        de_DE: {\n            Copy: 'Pullover \u0026 Strickjacken',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/de/herren-strickwaren/',\n            MbPrice: '€79.95',\n        },\n        fr_FR: {\n            Copy: 'Pulls et Cardigans',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/fr/mailles-homme/',\n            MbPrice: '€79.95',\n        },\n        en_AU: {\n            Copy: 'Jumpers \u0026 Cardigans',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/au/mens-knitwear/',\n            MbPrice: '$79.00',\n        },\n        en: {\n            Copy: 'Jumpers \u0026 Cardigans',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: '/intl/mens-knitwear/',\n            mbSavings: ['20% off'],\n        },\n        Icon: '/on/demandware.static/-/Library-Sites-CTShirtsSharedLibrary/default/mb-tracker/knitwear-icon-default.svg',\n    },\n\n\n    ties: {\n        NumberOfProductsToActivateMb: 2,\n        en_GB: {\n            Copy: 'Ties',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/uk/mens-ties/',\n            MbPrice: '£29.95',\n        },\n        en_US: {\n            Copy: 'Ties',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/us/mens-ties/',\n            MbPrice: '$34.00',\n        },\n        en_CH: {\n            Copy: 'Ties',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/ch/en_CH/mens-ties/',\n            MbPrice: 'CHF 44,00',\n        },\n        en_CA: {\n            Copy: 'Ties',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/ca/en_CA/mens-ties/',\n            MbPrice: 'C$64.00',\n        },\n        en_IE: {\n            Copy: 'Ties',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/eu/mens-ties/',\n            MbPrice: '€29.95',\n        },\n        nl_NL: {\n            Copy: 'Ties',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/nl/en_NL/mens-ties/',\n            MbPrice: '€29.95',\n        },\n        fr_CH: {\n            Copy: 'Cravates',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/ch/fr_CH/mens-ties/',\n            MbPrice: 'CHF 44,00',\n        },\n        de_CH: {\n            Copy: 'Krawatten',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/ch/de_CH/mens-ties/',\n            MbPrice: 'CHF 44,00',\n        },\n        fr_CA: {\n            Copy: 'Cravates',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/ca/fr_CA/mens-ties/',\n            MbPrice: 'C$64.00',\n        },\n        de_DE: {\n            Copy: 'Krawatten',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/de/herren-krawatten/',\n            MbPrice: '€29.95',\n        },\n        fr_FR: {\n            Copy: 'Cravates',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/fr/accessoires-homme/cravate/',\n            MbPrice: '€29.95',\n        },\n        en_AU: {\n            Copy: 'Ties',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/au/mens-ties/',\n            MbPrice: '$45.00',\n        },\n        en: {\n            Copy: 'Ties',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: '/intl/mens-ties/',\n            mbSavings: ['15% off'],\n        },\n        Icon: '/on/demandware.static/-/Library-Sites-CTShirtsSharedLibrary/default/mb-tracker/ties-icon-default.svg',\n    },\n\n\n    belts: {\n        en_GB: {\n            Copy: 'Belts \u0026 Braces',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/uk/mens-accessories/belts/',\n            MbPrice: '£32.45',\n        },\n        en_CH: {\n            Copy: 'Belts \u0026 Braces',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/ch/en_CH/mens-accessories/belts/',\n            MbPrice: 'CHF 79,00',\n        },\n        en_US: {\n            Copy: 'Belts \u0026 Suspenders',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/us/mens-accessories/belts/',\n            MbPrice: '$40.00',\n        },\n        en_CA: {\n            Copy: 'Belts \u0026 Suspenders',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/ca/en_CA/mens-accessories/belts/',\n            MbPrice: 'C$64.00',\n        },\n        en_IE: {\n            Copy: 'Belts \u0026 Braces',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/eu/mens-accessories/belts/',\n            MbPrice: '€32.45',\n        },\n        nl_NL: {\n            Copy: 'Belts \u0026 Braces',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/nl/en_NL/mens-accessories/belts/',\n            MbPrice: '€32.45',\n        },\n        fr_CH: {\n            Copy: 'Ceintures et Bretelles',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/ch/fr_CH/mens-accessories/belts/',\n            MbPrice: 'CHF 79,00',\n        },\n        de_CH: {\n            Copy: 'Gürtel \u0026 Hosenträger',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/ch/de_CH/mens-accessories/belts/',\n            MbPrice: 'CHF 79,00',\n        },\n        fr_CA: {\n            Copy: 'Ceintures et Bretelles',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/ca/fr_CA/mens-accessories/belts/',\n            MbPrice: 'C$64.00',\n        },\n        de_DE: {\n            Copy: 'Gürtel \u0026 Hosenträger',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/de/herren-accessoires/guertel/',\n            MbPrice: '€32.45',\n        },\n        fr_FR: {\n            Copy: 'Ceintures et Bretelles',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/fr/accessoires-homme/ceintures-bretelles/',\n            MbPrice: '€32.45',\n        },\n        en_AU: {\n            Copy: 'Belts \u0026 Braces',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/au/mens-accessories/belts/',\n            MbPrice: '$40.00',\n        },\n        en: {\n            Copy: 'Belts \u0026 Braces',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: '/intl/mens-accessories/belts/',\n            mbSavings: ['20% off'],\n        },\n        Icon: '/on/demandware.static/-/Library-Sites-CTShirtsSharedLibrary/default/mb-tracker/belt-icon-default.svg',\n    },\n\n\n    pocketsquares: {\n        en_GB: {\n            Copy: 'Pocket Squares',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/uk/mens-accessories/pocket-squares/',\n            MbPrice: '£19.95',\n        },\n        en_CH: {\n            Copy: 'Pocket Squares',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/ch/en_CH/mens-accessories/pocket-squares/',\n            MbPrice: 'CHF 16,95',\n        },\n        en_US: {\n            Copy: 'Pocket Squares',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/us/mens-accessories/pocket-squares/',\n            MbPrice: '$22.50',\n        },\n        en_CA: {\n            Copy: 'Pocket Squares',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/ca/en_CA/mens-accessories/pocket-squares/',\n            MbPrice: 'C$39.00',\n        },\n        en_IE: {\n            Copy: 'Pocket Squares',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/eu/mens-accessories/pocket-squares/',\n            MbPrice: '€24.95',\n        },\n        nl_NL: {\n            Copy: 'Pocket Squares',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/nl/en_NL/mens-accessories/pocket-squares/',\n            MbPrice: '€24.95',\n        },\n        fr_CH: {\n            Copy: 'Pochettes de Costume',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/ch/fr_CH/mens-accessories/pocket-squares/',\n            MbPrice: 'CHF 16,95',\n        },\n        de_CH: {\n            Copy: 'Einstecktücher',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/ch/de_CH/mens-accessories/pocket-squares/',\n            MbPrice: 'CHF 16,95',\n        },\n        fr_CA: {\n            Copy: 'Pochettes de Costume',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/ca/fr_CA/mens-accessories/pocket-squares/',\n            MbPrice: 'C$39.00',\n        },\n        de_DE: {\n            Copy: 'Einstecktücher',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/de/herren-accessoires/einstecktuecher/',\n            MbPrice: '€24.95',\n        },\n        fr_FR: {\n            Copy: 'Pochettes de Costume',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/fr/accessoires-homme/pochettes-costume/',\n            MbPrice: '€24.95',\n        },\n        en_AU: {\n            Copy: 'Pocket Squares',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/au/mens-accessories/pocket-squares/',\n            MbPrice: '$27.50',\n        },\n        en: {\n            Copy: 'Pocket Squares',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: '/intl/mens-accessories/pocket-squares/',\n            mbSavings: ['15% off'],\n        },\n        Icon: '/on/demandware.static/-/Library-Sites-CTShirtsSharedLibrary/default/mb-tracker/pocketsquare-icon-default.svg',\n\n    },\n\n    socks: {\n        en_GB: {\n            Copy: 'Socks',\n            NumberOfProductsToActivateMb: 3,\n            PlpLink: 'https://www.charlestyrwhitt.com/uk/mens-accessories/socks/',\n            MbPrice: '£9.50',\n        },\n        en_CH: {\n            Copy: 'Socks',\n            NumberOfProductsToActivateMb: 3,\n            PlpLink: 'https://www.charlestyrwhitt.com/ch/en_CH/mens-accessories/socks/',\n            MbPrice: 'CHF 20,00',\n        },\n        en_US: {\n            Copy: 'Socks',\n            NumberOfProductsToActivateMb: 3,\n            PlpLink: 'https://www.charlestyrwhitt.com/us/mens-accessories/socks/',\n            MbPrice: '$13.00',\n        },\n        en_CA: {\n            Copy: 'Socks',\n            NumberOfProductsToActivateMb: 3,\n            PlpLink: 'https://www.charlestyrwhitt.com/ca/en_CA/mens-accessories/socks/',\n            MbPrice: 'C$22.00',\n        },\n        en_IE: {\n            Copy: 'Socks',\n            NumberOfProductsToActivateMb: 3,\n            PlpLink: 'https://www.charlestyrwhitt.com/eu/mens-accessories/socks/',\n            MbPrice: '€12.50',\n        },\n        nl_NL: {\n            Copy: 'Socks',\n            NumberOfProductsToActivateMb: 3,\n            PlpLink: 'https://www.charlestyrwhitt.com/nl/en_NL/mens-accessories/socks/',\n            MbPrice: '€12.50',\n        },\n        fr_CH: {\n            Copy: 'Chaussettes',\n            NumberOfProductsToActivateMb: 3,\n            PlpLink: 'https://www.charlestyrwhitt.com/ch/fr_CH/mens-accessories/socks/',\n            MbPrice: 'CHF 20,00',\n        },\n        de_CH: {\n            Copy: 'Socken',\n            NumberOfProductsToActivateMb: 3,\n            PlpLink: 'https://www.charlestyrwhitt.com/ch/de_CH/mens-accessories/socks/',\n            MbPrice: 'CHF 20,00',\n        },\n        fr_CA: {\n            Copy: 'Chaussettes',\n            NumberOfProductsToActivateMb: 3,\n            PlpLink: 'https://www.charlestyrwhitt.com/ca/fr_CA/mens-accessories/socks/',\n            MbPrice: 'C$22.00',\n        },\n        de_DE: {\n            Copy: 'Socken',\n            NumberOfProductsToActivateMb: 3,\n            PlpLink: 'https://www.charlestyrwhitt.com/de/herren-accessoires/socken/',\n            MbPrice: '€12.50',\n        },\n        fr_FR: {\n            Copy: 'Chaussettes',\n            NumberOfProductsToActivateMb: 3,\n            PlpLink: 'https://www.charlestyrwhitt.com/fr/accessoires-homme/chaussettes/',\n            MbPrice: '€12.50',\n        },\n        en_AU: {\n            Copy: 'Socks',\n            NumberOfProductsToActivateMb: 3,\n            PlpLink: 'https://www.charlestyrwhitt.com/au/mens-accessories/socks/',\n            MbPrice: '$17.00',\n        },\n        en: {\n            Copy: 'Socks',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: '/intl/mens-accessories/socks/',\n            mbSavings: ['10% off'],\n        },\n        Icon: '/on/demandware.static/-/Library-Sites-CTShirtsSharedLibrary/default/mb-tracker/socks-icon-default.svg'\n    },\n\n    underwear: {\n        en_GB: {\n            Copy: 'Underwear',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/uk/mens-underwear/',\n            MbPrice: '£19.95',\n        },\n        en_CH: {\n            Copy: 'Underwear',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/ch/en_CH/mens-accessories/boxer-shorts/',\n            MbPrice: 'CHF 40,00',\n        },\n        en_US: {\n            Copy: 'Underwear',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/us/mens-accessories/boxer-shorts/',\n            MbPrice: '$39.00',\n        },\n        en_CA: {\n            Copy: 'Underwear',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/ca/en_CA/mens-accessories/boxer-shorts/',\n            MbPrice: 'C$64.00',\n        },\n        en_IE: {\n            Copy: 'Underwear',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/eu/mens-accessories/boxer-shorts/',\n            MbPrice: '€24.95',\n        },\n        nl_NL: {\n            Copy: 'Underwear',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/nl/en_NL/mens-accessories/boxer-shorts/',\n            MbPrice: '€24.95',\n        },\n        fr_CH: {\n            Copy: 'Sous-vêtements',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/ch/fr_CH/mens-accessories/boxer-shorts/',\n            MbPrice: 'CHF 40,00',\n        },\n        de_CH: {\n            Copy: 'Unterwäsche',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/ch/de_CH/mens-accessories/boxer-shorts/',\n            MbPrice: 'CHF 40,00',\n        },\n        fr_CA: {\n            Copy: 'Sous-vêtements',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/ca/fr_CA/mens-accessories/boxer-shorts/',\n            MbPrice: 'C$64.00',\n        },\n        de_DE: {\n            Copy: 'Unterwäsche',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/de/herren-accessoires/boxer-shorts/',\n            MbPrice: '€24.95',\n        },\n        fr_FR: {\n            Copy: 'Sous-vêtements',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/fr/accessoires-homme/boxers/',\n            MbPrice: '€24.95',\n        },\n        en_AU: {\n            Copy: 'Underwear',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/au/mens-accessories/boxer-shorts/',\n            MbPrice: '$39.00',\n        },\n        en: {\n            Copy: 'Underwear',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: '/intl/mens-accessories/boxer-shorts/',\n            mbSavings: ['15% off'],\n        },\n        Icon: '/on/demandware.static/-/Library-Sites-CTShirtsSharedLibrary/default/mb-tracker/underwear-icon-default.svg',\n    },\n\n    cufflinks: {\n        NumberOfProductsToActivateMb: 2,\n        en_GB: {\n            Copy: 'Cufflinks',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/uk/mens-accessories/cufflinks/',\n            MbPrice: '£22.45',\n        },\n        en_CH: {\n            Copy: 'Cufflinks',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/ch/en_CH/mens-accessories/cufflinks/',\n            MbPrice: 'CHF 39,00',\n        },\n        en_US: {\n            Copy: 'Cufflinks',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/us/mens-accessories/cufflinks/',\n            MbPrice: '$39.00',\n        },\n        en_CA: {\n            Copy: 'Cufflinks',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/ca/en_CA/mens-accessories/cufflinks/',\n            MbPrice: 'C$74.00',\n        },\n        en_IE: {\n            Copy: 'Cufflinks',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/eu/mens-accessories/cufflinks/',\n            MbPrice: '€32.45',\n        },\n        nl_NL: {\n            Copy: 'Cufflinks',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/nl/en_NL/mens-accessories/cufflinks/',\n            MbPrice: '€32.45',\n        },\n        fr_CH: {\n            Copy: 'Boutons de manchette',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/ch/fr_CH/mens-accessories/cufflinks/',\n            MbPrice: 'CHF 39,00',\n        },\n        de_CH: {\n            Copy: 'Manschettenknöpfe',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/ch/de_CH/mens-accessories/cufflinks/',\n            MbPrice: 'CHF 39,00',\n        },\n        fr_CA: {\n            Copy: 'Boutons de manchette',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/ca/fr_CA/mens-accessories/cufflinks/',\n            MbPrice: 'C$74.00',\n        },\n        de_DE: {\n            Copy: 'Manschettenknöpfe',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/de/herren-accessoires/manschettenknoepfe/',\n            MbPrice: '€32.95',\n        },\n        fr_FR: {\n            Copy: 'Boutons de manchette',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/fr/accessoires-homme/boutons-manchette/',\n            MbPrice: '€32.95',\n        },\n        en_AU: {\n            Copy: 'Cufflinks',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/au/mens-accessories/cufflinks/',\n            MbPrice: '$79.00',\n        },\n        Icon: '/on/demandware.static/-/Library-Sites-CTShirtsSharedLibrary/default/mb-tracker/cufflinks-icon-default.svg',\n    },\n    tshirts: {\n        NumberOfProductsToActivateMb: 2,\n\n        en_GB: {\n            Copy: 'T-Shirts',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/uk/mens-shirts/t-shirts/',\n            MbPrice: '£24.95',\n        },\n        en_US: {\n            Copy: 'T-Shirts',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/us/mens-shirts/t-shirts/',\n            MbPrice: '$39',\n        },\n        en_CA: {\n            Copy: 'T-Shirts',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/ca/en_CA/mens-shirts/t-shirts/',\n            MbPrice: 'C$64',\n        },\n        en_CH: {\n            Copy: 'T-Shirts',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/ch/en_CH/mens-shirts/t-shirts/',\n            MbPrice: 'CHF 44',\n        },\n        en_IE: {\n            Copy: 'T-Shirts',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/eu/mens-shirts/t-shirts/',\n            MbPrice: '34,95 €',\n        },\n        nl_NL: {\n            Copy: 'T-Shirts',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/nl/en_NL/mens-shirts/t-shirts/',\n            MbPrice: '€34,95',\n        },\n        fr_CH: {\n            Copy: 'T-Shirts',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/ch/fr_CH/mens-shirts/t-shirts/',\n            MbPrice: 'CHF 44',\n        },\n        de_CH: {\n            Copy: 'T-Shirts',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/ch/de_CH/mens-shirts/t-shirts',\n            MbPrice: 'CHF 44',\n        },\n        fr_CA: {\n            Copy: 'T-Shirts',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/ca/fr_CA/mens-shirts/t-shirts/',\n            MbPrice: 'C$64',\n        },\n        de_DE: {\n            Copy: 'T-Shirts',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/de/herren-hemden/t-shirts',\n            MbPrice: '€34,95',\n        },\n        fr_FR: {\n            Copy: 'T-Shirts',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/fr/chemises-homme/t-shirts/',\n            MbPrice: '€34,95',\n        },\n        en_AU: {\n            Copy: 'T-Shirts',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/au/mens-shirts/t-shirts/',\n            MbPrice: '$39',\n        },\n        Icon: '/on/demandware.static/-/Library-Sites-CTShirtsSharedLibrary/default/mb-tracker/t-shirt-icon-default.svg'\n    },\n\n    // SH101 shoes multibuy.\n    // Shoes is the first category with a countable noun, so it carries both\n    // Copy (plural) and CopySingular. Categories without CopySingular fall back\n    // to Copy, so nothing else changes. German uses the invariant \"Paar\" after\n    // a numeral, so both forms are identical there.\n    // MbPrice values are placeholders pending the confirmed promotion prices.\n    shoes: {\n        NumberOfProductsToActivateMb: 2,\n\n        en_GB: {\n            Copy: 'pairs of Shoes',\n            CopySingular: 'pair of Shoes',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/uk/mens-shoes/',\n            MbPrice: '£TBC',\n        },\n        en_US: {\n            Copy: 'pairs of Shoes',\n            CopySingular: 'pair of Shoes',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/us/mens-shoes/',\n            MbPrice: '$TBC',\n        },\n        en_CA: {\n            Copy: 'pairs of Shoes',\n            CopySingular: 'pair of Shoes',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/ca/en_CA/mens-shoes/',\n            MbPrice: 'C$TBC',\n        },\n        en_CH: {\n            Copy: 'pairs of Shoes',\n            CopySingular: 'pair of Shoes',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/ch/en_CH/mens-shoes/',\n            MbPrice: 'CHF TBC',\n        },\n        en_IE: {\n            Copy: 'pairs of Shoes',\n            CopySingular: 'pair of Shoes',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/eu/mens-shoes/',\n            MbPrice: '€TBC',\n        },\n        nl_NL: {\n            Copy: 'pairs of Shoes',\n            CopySingular: 'pair of Shoes',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/nl/en_NL/mens-shoes/',\n            MbPrice: '€TBC',\n        },\n        fr_CH: {\n            Copy: 'paires de Chaussures',\n            CopySingular: 'paire de Chaussures',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/ch/fr_CH/mens-shoes/',\n            MbPrice: 'CHF TBC',\n        },\n        de_CH: {\n            Copy: 'Paar Schuhe',\n            CopySingular: 'Paar Schuhe',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/ch/de_CH/mens-shoes/',\n            MbPrice: 'CHF TBC',\n        },\n        fr_CA: {\n            Copy: 'paires de Chaussures',\n            CopySingular: 'paire de Chaussures',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/ca/fr_CA/mens-shoes/',\n            MbPrice: 'C$TBC',\n        },\n        de_DE: {\n            Copy: 'Paar Schuhe',\n            CopySingular: 'Paar Schuhe',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/de/herren-schuhe/',\n            MbPrice: '€TBC',\n        },\n        fr_FR: {\n            Copy: 'paires de Chaussures',\n            CopySingular: 'paire de Chaussures',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/fr/chaussures-homme/',\n            MbPrice: '€TBC',\n        },\n        en_AU: {\n            Copy: 'pairs of Shoes',\n            CopySingular: 'pair of Shoes',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: 'https://www.charlestyrwhitt.com/au/mens-shoes/',\n            MbPrice: '$TBC',\n        },\n        // XBR only. Delete this block if shoes is not part of the international\n        // multibuy, the tracker then suppresses itself on XBR.\n        en: {\n            Copy: 'pairs of Shoes',\n            CopySingular: 'pair of Shoes',\n            NumberOfProductsToActivateMb: 2,\n            PlpLink: '/intl/mens-shoes/',\n            mbSavings: ['TBC% off'],\n        },\n        Icon: 'https://brxcdn.com/uk1-app-storage/d868c674-e566-11ef-bb40-924d6b029175/media/original/82de7fee-8bf2-11f1-829b-a654aefd9d0c'\n    }\n}\n\nwindow.globalTrackerObj = globalTrackerObj;\nreturn true;"}}},{"id":"686bda9631a9bc8251208077","name":"BR Site Language","variable":{"type":"global_variable","global_variable":{"name":"utag_data.global.site_language"}}},{"id":"6870cfc582729abfafd29d0c","name":"BR Country Site","variable":{"type":"global_variable","global_variable":{"name":"utag_data.global.sfcc_country"}}},{"id":"6870cfc682729abfafd29d10","name":"BR Device View","variable":{"type":"global_variable","global_variable":{"name":"utag_data.page.responsive_design_type"}}},{"id":"687777bbd6d560fc90693882","name":"BR Page Type","variable":{"type":"global_variable","global_variable":{"name":"utag_data.page.type"}}},{"id":"687777bbd6d560fc90693886","name":"BR Campaign Site","variable":{"type":"global_variable","global_variable":{"name":"utag_data.global.campaign_site"}}},{"id":"687e48e9e79652fed545563f","name":"Product ID","variable":{"type":"global_variable","global_variable":{"name":"utag_data.products[0].id"}}},{"id":"687f5904f7fcebf3eaf07fef","name":"Products Array","variable":{"type":"global_variable","global_variable":{"name":"utag_data.products"}}},{"id":"687f9ebffac7bd3683754786","name":"Bag","variable":{"type":"global_variable","global_variable":{"name":"utag_data.bag"}}},{"id":"687f9ebffac7bd368375478a","name":"Bag_IDs","variable":{"type":"custom_function","custom_function":{"body":"if (utag_data.bag){\n\tvar ids=[];\n\tfor(let i=0;i\u003cutag_data.bag.length;i++){\n\t\tids.push(utag_data.bag[i].id);\n\t}\n\twindow.bagIds=ids;\n} \nreturn ids;"}}},{"id":"689254c63d8b6aa8df033691","name":"BR Page Type","variable":{"type":"global_variable","global_variable":{"name":"utag_data.page.type"}}},{"id":"689468c1181a7ca4ed37e2c4","name":"BR Page Category","variable":{"type":"global_variable","global_variable":{"name":"utag_data.page.category"}}},{"id":"689498bd181a7ca4ed37ef90","name":"BR Product ID (PDP Only)","variable":{"type":"global_variable","global_variable":{"name":"utag_data.products[0].id"}}},{"id":"68a88a1b00c874c8b139e49a","name":"Recommendations Social Proof Array (Top Sellers 22/8/25)","variable":{"type":"custom_function","custom_function":{"body":"[\r\n  \"CSB0255SKY\",\"CSB0255WHT\",\"CSH0013AFB\",\"CSH0015AQA\",\"CSH0015COB\",\"CSH0015LLC\",\"CSH0015MCA\",\r\n  \"CSH0015NAV\",\"CSH0015OAT\",\"CSH0015OCE\",\"CSH0015OLV\",\"CSH0015WHT\",\"CSR0906BWT\",\"CSR2089OAT\",\r\n  \"CSR2111MCA\",\"CSR2111SKY\",\"FOA0004IDG\",\"FOA0004LLC\",\"FOA0004SKY\",\"FOA0004WHT\",\"FOA0009CFW\",\r\n  \"FOA0009SKY\",\"FOA0009WHT\",\"FOB0188WHT\",\"FOB0636COB\",\"FOB0785WHT\",\"FON0216WHT\",\"FON0219WHT\",\r\n  \"FON0409SKY\",\"FON0409WHT\",\"FON0410RYL\",\"FON0410SKY\",\"FON0412WSK\",\"FON0413RYL\",\"FON0540SKY\",\r\n  \"FON0540WHT\",\"FON0671WHT\",\"FON0677WHT\",\"FON0740SKY\",\"FON2613SKY\",\"FON2628CFW\",\"FON2631SKY\",\r\n  \"FON2647DPK\",\"FON2648GRN\",\"FON2648LLC\",\"FOR2362WHT\",\"FOR2406SKY\",\"JEP0317NAV\",\"JEP0317WHT\",\r\n  \"TRC0270NAV\",\"CLX0027NON\",\"CLX0028NON\",\"CSH0018NAV\",\"CSR0806WHT\",\"CSR0905WHT\",\"CSR0968WHT\",\r\n  \"CSR2052OLV\",\"CSR2056COB\",\"CSR2056NAV\",\"CSR2056WHT\",\"CSR2114OLV\",\"FOA0005OCE\",\"FOA0009LLC\",\r\n  \"FOA0009PNK\",\"FOA0009SLV\",\"FOB0188SKY\",\"FOB0765DEN\",\"FOB0806TPE\",\"FOB0815IDG\",\"FOB0824RYL\",\r\n  \"FON0219BLU\",\"FON0409NAV\"\r\n]\r\n"}}},{"id":"68c91ba91c00bfc935319bd9","name":"Page Name","variable":{"type":"global_variable","global_variable":{"name":"utag_data.page.name"}}},{"id":"68fb434029827191de90a56e","name":"Page Type","variable":{"type":"global_variable","global_variable":{"name":"utag_data.page.type"}}},{"id":"68fb434029827191de90a572","name":"Country Site","variable":{"type":"global_variable","global_variable":{"name":"utag_data.global.sfcc_country"}}},{"id":"69b7e0c02a7591e216cdb2da","name":"BR Site Language","variable":{"type":"global_variable","global_variable":{"name":"utag_data.global.site_language"}}},{"id":"69b7e0c12a7591e216cdb2de","name":"BR Country Site","variable":{"type":"global_variable","global_variable":{"name":"utag_data.global.sfcc_country"}}},{"id":"69b7e0c12a7591e216cdb2e2","name":"BR Page Type","variable":{"type":"global_variable","global_variable":{"name":"utag_data.page.type"}}},{"id":"69b7e0c12a7591e216cdb2e6","name":"Product ID","variable":{"type":"global_variable","global_variable":{"name":"utag_data.products[0].id"}}},{"id":"69b7e0c12a7591e216cdb2ea","name":"Products Array","variable":{"type":"global_variable","global_variable":{"name":"utag_data.products"}}},{"id":"6a7998e5bcb5563a5f8bb30a","name":"PLP Column Layout","variable":{"type":"custom_function","custom_function":{"body":"return (window.CT_PLP_COLS === '1'\n  || document.documentElement.getAttribute('data-ct-plp-cols') === '1'\n  || !!document.querySelector('.plp-grid__container--1-col-mobile')) ? '1' : '2';"}}}]}}