1<!DOCTYPE html> 2<!--[if lte IE 8]> <html lang="pl" class="lt-ie8"> <![endif]--> 3<!--[if IE 9]> <html lang="pl" class="lt-ie8 lt-ie9"> <![endif]--> 4<!--[if gt IE 9]><!--> <html data-pwa="1" lang="pl"> <!--<![endif]--> 5<head data-features="WyJwcm9kdWN0X2J1bmRsZXMiLCJ3ZWJkYXYiLCJzYWFzX2JpbGxpbmciLCJyZWRpcmVjdHNfY29uZmlnIiwicmVkaXJlY3RzX2RvbWFpbnMiLCJyZWRpcmVjdHNfb2JqZWN0cyIsInJlZGlyZWN0c19yb3V0ZXIiLCJyZWRpcmVjdHNfYXBpIiwiYWxsZWdyb19kb3dubG9hZF9vcmRlcnMiLCJhbGxlZ3JvX2ltcG9ydF9hdWN0aW9ucyIsImFsbGVncm9fYXV0b19pbXBvcnRfYXVjdGlvbnMiLCJhbGxlZ3JvX3VwZGF0ZV9hdWN0aW9ucyIsInB3YSIsImFsbGVncm9fc2VuZF9zaGlwcGluZ19udW1iZXIiLCJzZW9fZ2Z4Iiwic2hvd19wcmVtaXVtX2ZlYXR1cmVzIiwicmVjb21tZW5kYXRpb25zX3RyYWNraW5nIiwicmVjb21tZW5kYXRpb25zX3N0YXRzX2FuYWx5emVyIiwib2JqZWN0c19zdGF0c19hbmFseXplciIsInJlY29tbWVuZGF0aW9uc19tb2RlbF9maXQiLCJyZWNvbW1lbmRhdGlvbnNfYWRtaW4iLCJiZWxsX21lc3NhZ2VzIiwiaW5wb3N0X21hcCIsIm5icF9jdXJyZW5jaWVzIiwicGF5bWVudF9ncGF5IiwicGFjemtvbWF0eV9kaXNhYmxlIiwiYWxsZWdyb19kb3dubG9hZF9vcmRlcnNfc3VyY2hhcmdlcyIsImFsbGVncm9fb3JkZXJfYW5kX3RyYW5zYWN0aW9uX3VpZF9maWx0ZXJzIiwiYWxsZWdyb19kb3dubG9hZF9vcmRlcnNfYWRkaXRpb25hbF9zZXJ2aWNlcyIsImFsbGVncm9fdXBkYXRlX3F1YW50aXR5X211bHRpYWN0aW9uIiwiYWxsZWdyb191cGRhdGVfcHJpY2VfbXVsdGlhY3Rpb24iLCJ0d29fZmFjdG9yIiwidHdvX2ZhY3Rvcl9zbXMiLCJhbGxlZ3JvX3RlbXBsYXRlX2V4dGVuZGVkIiwicHJvZHVjdF9kdXBsaWNhdGVfbmV3X29wdGlvbnMiLCJ3ZWJwdXNoX2FkbWluIiwiZGVmYXVsdF9maWx0ZXJfcHJvZmlsZXMiLCJmaWxlX21hbmFnZW1lbnQiLCJpbnBvc3RfcHd3IiwicmVjYXB0Y2hhX2FkbWluIiwidHJhZmZpY19hbmFseXplciIsInNlYXJjaF9hZG1pbiIsInNlYXJjaF9jbGllbnQiLCJzZWFyY2hfaW5kZXhlciIsImF1cm9yYV9yZWZhY3RvcmluZyIsImFsbGVncm9fc3RhdHVzX21hcCIsImd0dV9jb2RlIiwibmV3X2RhdGVwaWNrZXIiLCJ2YXRfZXUiLCJuZXdfYWxsZWdyb190ZW1wbGF0ZV9jcmVhdG9yIiwiYWxsZWdyb19hc3NpZ25fdGF4X3ZhbHVlX211bHRpYWN0aW9uIiwiYWxsZWdyb19hdWN0aW9uc190YXhfdmFsdWVfZmlsdGVycyIsImFsbGVncm9fY3JlYXRvcl90YXhfc2VsZWN0aW9uX2xpc3QiLCJhbGxlZ3JvX2RldGVjdF9hbGxlZ3JvX3Byb2R1Y3RfbXVsdGlhY3Rpb24iLCJhbGxlZ3JvX2Fzc2lnbl9hbGxlZ3JvX3Byb2R1Y3RfbXVsdGlhY3Rpb24iLCJhbGxlZ3JvX2F1Y3Rpb25zX2hhc19hbGxlZ3JvX3Byb2R1Y3RfZmlsdGVycyIsImFsbGVncm9fcHJvZHVjdHNfaGFzX2FsbGVncm9fcHJvZHVjdF9maWx0ZXJzIiwiY2xlYW5fdXBfbWFpbF9sb2dzIiwibmV3X29yZGVyX25vdGVzIiwibmV3X2dhbGxlcnkiLCJ0cmFmZmljX25ld19yZXBvcnRzIiwicGVyZm9ybWFuY2VfcmVwb3J0cyIsImN1c3RvbWVyX3ByaXZhY3kiLCJpbWdfc2l6ZV9lZGl0YWJsZSIsImRpZ2l0YWxfbGlua3MiLCJjb2xsZWN0aW9ucyIsImdmeF9tZXRhZGF0YSIsInByb2dyZXNzaXZlX2Rpc2NvdW50cyIsInN0b2NrMF9zeW5jIiwic3RvY2swIiwiZmFjZWJvb2tfYnVzaW5lc3NfZXh0ZW5zaW9uIiwiZmFjZWJvb2tfY2FwaSIsInJlY29tbWVuZGF0aW9uc19jb21wdXRlX3N1bXNfb3B0aW1pemF0aW9uIiwicmVjb21tZW5kYXRpb25zX3N1bXNfb3B0aW1pemF0aW9uIiwid2FyZWhvdXNlc19sb2dzIiwid2FyZWhvdXNlcyIsImdvb2dsZV9hbmFseXRpY3NfdjQiLCJwcm9kdWN0X2R1cGxpY2F0ZV9jb2xsZWN0aW9ucyIsInJlc3RhcGlfd2l0aG91dF9sb2NrcyIsImRpc2FibGVfY2xpZW50X3Nlc3Npb25fdWFfcmV2YWxpZGF0ZSIsImNvbmRpdGlvbl9vbl9wcm9tb2NvZGVzbGlzdCIsInBob25lX3ZhbGlkYXRpb24iLCJ1cmxfcmVwYWlyX3N0cmluZ19kaXNhYmxlIiwicHJvZHVjdHNfb3JkZXIiLCJhbGxlZ3JvX2VycGJveCIsIm1haW5fcGFnZV9jb2xsZWN0aW9uIiwicmVicmFuZGluZ19hcGlsbyIsInNob3Blcl9zaGlwbWVudHMiLCJjYW1wYWdpbnNfdGlrdG9rIiwicHJvbW90aW9uc19wcm9kdWN0c19tYW51YWxfb3JkZXIiLCJuZXdfcHJvZHVjdHNfbWFudWFsX29yZGVyIiwiZnJvbnRza2luX2NvbmZpZ3VyYXRvciIsInBheW1lbnRfYXBwbGVfcGF5IiwiYnlfZGF0ZV9hZGRfc29ydF90eXBlcyIsInBheW1lbnRfZmluYW5jaW5nX2JydXR0byIsImNyZWF0ZV9tYWlsX21lc3NhZ2VfaWQiLCJzaG9wZXJfY2FtcGFpZ25zX25ld19kYXRhX3NvdXJjZSIsInNob3Blcl9jYW1wYWlnbnNfcmVwb3J0cyIsImFsbGVncm9fcHJvbW9fb3B0aW9ucyIsImFsbGVncm9fcHJvZHVjdGl6YXRpb24iLCJjb250cm9sX2NhdGVnb3J5X3JlZmFjdG9yIiwiYWxsZWdyb19wcm9ncmVzc192YWxpZGF0aW9uX2Vycm9yIiwiYWxsZWdyb19sb2NrX3Byb2Nlc3MiLCJwcm9kdWN0X2NhcmRfYWRkaXRpb25hbF93YXJlaG91c2VzX3NoaXBwaW5nX3RpbWUiLCJjbGllbnRfZmlsdGVyX2NsZWFuX2FzY2lpIiwiYmFza2V0X2FkZHJlc3NfcGx1Z2lucyIsInBvY3p0YV9wb2xza2FfaW5zdXJhbmNlIiwic2hvcGVyX2NhbXBhaWduc19vcmRlcl9lbWFpbCIsInNoaXBtZW50X2NyZWF0ZV9pbnZlcnRfc2hvcGVyc2hpcG1lbnQiLCJwYXJjZWxzX2NyZWF0ZV9vcmRlcl9pZF9ub3RlcyIsImFwcHN0b3JlX2FwaWxvX211bHRpX2NoYW5uZWwiLCJwYWxsZXRfcGFja2FnZSIsInNoaXBtZW50X2NyZWF0ZV9pbnZlcnRfYXBhY3prYSIsInNoaXBtZW50X2NyZWF0ZV9pbnZlcnRfcGFjemtvbWF0eSIsInNwX2lucG9zdF9wb2ludF90b19kb29yIiwic2hpcG1lbnRfY3JlYXRlX2ludmVydF9hbGxlZ3JvIiwic2hpcG1lbnRfY3JlYXRlX2ludmVydF9pbnBvc3QiLCJncGF5X2NsZWFuX3Bob25lX251bWJlciIsImNvdW50X3Byb2R1Y3RzX2luX29wdGlvbl92YWx1ZXNfZmlsdGVyX2F0X29uY2UiLCJvcHRpbWl6ZWRfcGxhY2Vfb3JkZXJfdHJhbnNhY3Rpb24iLCJkaXNhYmxlX3ByaWNlX2ZpbHRlcl9yYW5nZXMiLCJjYW1wYWdpbnNfd3BhZHMiLCJwYXJjZWxzX3ByaW50X2RvY3VtZW50c19uZXdfZmlsZW5hbWUiLCJvbW5pYnVzX2JhY2tlbmQiLCJvbW5pYnVzX2JhY2tlbmRfdjIiLCJvbW5pYnVzX2Zyb250ZW5kIiwic2l0ZW1hcF9hZGRpdGlvbmFsX29wdGlvbnMiLCJwYXltZW50X25ld19zZXJ2aWNlX2V4aXN0cyIsImd0YWdfZW1pdF9ldmVudCIsInBheV9wYWxfZXhwcmVzc19jaGVja291dF9yZXBhaXIiLCJwYXltZW50X25ld19vbmxpbmVwYXltZW50X2Zvcm1fdXBkYXRlIiwiY2FjaGVfdGFnc19vcHRpbWl6ZXIiLCJzZXNzaW9uX3N0YXJ0c19pbl9yZWFkX29ubHlfbW9kZSIsInN0b2NrX29wdGltaXphdGlvbiIsInBheW1lbnRfYm1fcGhvdG9fdmVyaWZpY2F0aW9uIiwicGF5bWVudF9yZWZ1bmRfcHJvY2Vzc19qb2IiLCJvbmxpbmVwYXltZW50X2Rpc2FibGVfYWNjb3VudF9udW1iZXJfdHlwZSIsImFwcHN0b3JlX3JldHVybnMiLCJwYXltZW50X2V4dGVuZF9zeW5jcyIsInJldmVyc2VfcGF5bWVudF9uYW1lX2Rpc3BsYXkiLCJyZXBlYXRpbmdfcGF5cG9fd
5HJhbnNhY3Rpb25zIiwicGF5bWVudF9uZXdfZm9ybV9iYWNrZW5kIiwiYXBwc3RvcmVfYXBpbG8iLCJjYW1wYWdpbnNfbXNhZHMiLCJpbXBvcnRfZ2Z4X2Zyb21fdXJsX21vdmVfb3V0X29mX3RyYW5zYWN0aW9uIiwic3RvY2tfZnJvbnRfY2FjaGVfa2V5IiwidXBkYXRlX2dhdGV3YXlfaWQiLCJvbmxpbmVwYXltZW50X3Bob25lX3ZhbGlkIiwiYXBwc3RvcmVfc2hvcGVyX2Nvbm5lY3QiLCJyb3V0ZXJfdXJsX2FkZF9xdWVyeV9wYXJhbXMiLCJmbWNfc3RhcnRpbmdfY291bnRlcl92YWx1ZSIsIm5ld19jb2xsZWN0aW9uX2xheW91dCIsImxveWFsdHlfbWFpbF9wZXJfdXNlciIsIm9ubGluZXBheW1lbnRfcmVmdW5kc19kYl90cmFuc2FjdGlvbiIsImZtY19sb2NhbF9jb3VudGVyIiwicGF5bWVudF9ub25fYWNjb3VudGVkX2FjdGl2aXR5X3NldHRpbmdzIiwicGF5bWVudF9maW5hbmNpbmdfbmV3X2Rlc2NyaXB0aW9uIiwiZnJvbnRfYXBpX3JlZ2lzdGVyX2ZpeCIsImZlYXR1cmVfZmxhZ3NfYWNrIiwid2Zpcm1hX2FwaV9hdXRoIiwiZG9tYWluX21hbmFnZXJfc3luY19kb21haW5zX3JlZmFjdG9yIiwicGFydG5lcl9nb29nbGVfYW5hbHl0aWNzX3Y0IiwiZ29vZ2xlX2FuYWx5dGljc192NF9jYW1wYWlnbiIsInNob3Blcl9jYW1wYWlnbnNfYnV5X2NhbXBhaWduIiwib21uaWJ1c19wcmljZXMiLCJzaG9wZXJfY2FtcGFpZ25zX2dvb2dsZV9nbWNfbmV3X3JlcXVlc3RfaGFzaCIsImFwaV9vcmRlcnNfY3JlYXRlX2N1cnJlbmN5X3JhdGUiLCJuZXdfZmlsdGVyc19jb25maWciLCJkeW5hbWljX29wdGlvbnNfZm9yX25ld19hY2NvdW50cyIsIm9ubGluZXBheW1lbnRfemlwY29kZV92YWxpZCIsImdwYXlfZXNjYXBlX21lcmNoYW50X2RhdGEiLCJkaXNhYmxlX2RvdHBheSIsInByb21vdGlvbl90aW1lIiwiY29uZmlnX2dvb2dsZV9yZW1hcmtldGluZyIsInBheW1lbnRzX2JtX3RvX2F1dG9wYXkiLCJhcGlfb3JkZXJfb3JpZ2luX3NwZWNpYWxfc2NvcGUiLCJwYXlwb19iYW5uZXIiLCJhcGlfc3BlY2lhbF9zY29wZXMiLCJwcm9tb19jb2Rlc19kYl90aW1lX2VuYWJsZWQiLCJhbGxlZ3JvX21pZ3JhdG9yIiwib3JkZXJfcGlja3VwX3BvaW50X2RiX2RlZGljYXRlZF9zYXZlIiwib3JkZXJzX3Byb3BlcnRpZXNfYWxsZWdyb19zbWFydCIsInBheW1lbnRfcDI0X3JlZmVycmFsX2xpbmsiLCJvcmRlcl9waWNrdXBfcG9pbnRfZGJfZGVkaWNhdGVkX3JlYWQiLCJibV9vdmVyd3JpdGVfYW1sX2RhdGEiLCJwYXltZW50X2NyZWF0ZV9zaW5nbGVfdHJhbnNhY3Rpb25zIiwicHJvbW9jb2RlX3RpbWUiLCJwYXltZW50X2RvY3VtZW50X251bWJlciIsImtsYXJuYV9keW5hbWljX2Jhbm5lciIsImRpc2FibGVfcHJvY2Vzc19iYXNrZXRfcXVldWUiLCJwYXltZW50c19ibV90b19hdXRvcGF5X2xpbmtzIiwic3RvcmVmcm9udF91cGRhdGUiLCJhbGxlZ3JvX2ludGVncmF0aW9uX2xpbWl0ZWQiLCJzdG9yZWZyb250X3NraW5zdG9yZV91cGRhdGVzIiwic2hvcGVyX2NhbXBhaWduc19vcmRlcl9jcmVhdGVkIiwic2hvcGVyX2NhbXBhaWduc19vcmRlcl9hcGlfdXRtIiwib3JkZXJfcGF5bWVudF9tYWlscyIsIm9yZGVyX3BpY2t1cF9wb2ludF9jb21wYXRpYmlsaXR5Iiwib3JkZXJfcGlja3VwX3BvaW50X2luX2NvcmUiLCJzcGVjaWFsX29mZmVyc19zdG9ja3NfdjAiLCJjdXN0b21lcl9wcml2YWN5X3YyIiwibWljcm9zb2Z0X2FkcyIsInNob3Blcl9jYW1wYWlnbnNfYXBwc3RvcmVfbGlua3MiLCJjb29raWVfc2V0dGluZ3NfbGluayIsInBheW1lbnRfb25saW5lcGF5bWVudF9hZGRfZnVuZHMiLCJwcm9kdWN0X29wdGlvbl9jb2xvcl9zdHJ1Y3RfYWdncmVnYXRlX2RhdGEiLCJ1c2Vfb2JqZWN0X3N0b3JhZ2VfZm9yX3RodW1icyIsInBheW1lbnRfa2xhcm5hX2Zsb2F0X3Byb2R1Y3RfcXVhbnRpdHkiLCJwYXltZW50X3BheXVfcGVuZGluZ190cmFuc2FjdGlvbnNfc3luY2hyb25pemF0aW9uIiwic2hvcGVyUDI0X3BheW1lbnRzIiwicGF5bWVudF9hcHBsZV9wYXlfaW5fc2V0dGluZ3MiLCJzZWFyY2hfYWRtaW5fZXhjZXJwdF9zdXBwb3J0IiwibmV3X2NhcmRzX3ZpZXciLCJzdmVfZWRpdG9ycy1icmVhZGNydW1icyIsIm1haWxfb3RwIiwic3ZlX2dyaWQtbGFiZWxzLXYyIiwiZ29vZ2xlXzJmYV9xcl9jb2RlX2dlbmVyYXRlX2xvY2FsbHkiLCJwYXltZW50c19kZWZhdWx0X3BheXBvX3Byb3ZpZGVyIiwic2hvcGVyX2NhbXBhaWduc19tZW51X2dvb2dsZV9kaXNhYmxlZCIsInN0b3JlZnJvbnRfc29jaWFsX2xvZ2luIiwic3RvcmVmcm9udF9zb2NpYWxfbG9naW5fZ29vZ2xlIiwic3RvcmVmcm9udF9zb2NpYWxfbG9naW5fZmFjZWJvb2siLCJzaG9wZXJfY2FtcGFpZ25zX2dvb2dsZV9hcHAiLCJzdmVfbmV3LWNvbG9yLXBpY2tlciIsInN2ZV9pbWFnZS1lZGl0b3IiLCJmaWx0ZXJzX3JlZmFjdG9yIiwicDI0X3BheW1lbnRfZ3BheSIsInAyNF9wYXltZW50X2FwcGxlX3BheSIsImZpbmFuY2luZ19uZXdfb2ZmZXIiLCJyZXR1cm5fcXVhbnRpdHlfdG9fc3RvY2tfYWZ0ZXJfY2FuY2VsZWRfb3JkZXIiLCJzaG9wZXJfY2FtcGFpZ25zX2Rpc2FibGVfc2hvcGVyX3RyYWZmaWMiLCJwYXltZW50X3AyNF9ncGF5X2FzeW5jIiwic2hvcGVyX2NhbXBhaWduc19tZW51X2ZhY2Vib29rX2Rpc2FibGVkIiwic2hvcGVyX2NhbXBhaWduc19mYWNlYm9va19hcHAiLCJzaG9wZXJfY2FtcGFpZ25zX21lbnVfY2FtcGFpZ25zX2Rpc2FibGVkIiwic3ZlX3ByZWRlZmluZWQtY29sdW1ucyIsInN0b3JlZnJvbnRfbWFjcm9zIiwic3RvcmVmcm9udF9tYWNyb3NfYWRkIiwic3RvcmVmcm9udF9tYWNyb3NfZWRpdCIsImltYWdlX2VkaXRvciIsInN0b3JlZnJvbnRfbGFuZ3VhZ2VzIiwic3RvcmVmcm9udCIsInN0b3JlZnJvbnRfYmVsbF9tZXNzYWdlIiwic3RvcmVmcm9udF9tYWNyb3NfZGVsZXRlIiwibGltaXRfcHJvZHVjdF9pbWFnZXNfY291bnRfYXBpIiwiaW5wb3N0X3BheSIsInBheW1lbnRfcDI0X2Rpc2NsYWltZXIiLCJnYV9jYW1wYWlnbl9tb3ZlX2Zyb21fcGx1Z2lucyIsInNraW5zdG9yZV9za2luX2NvcHkiLCJhcHBzdG9yZV9saW5rc19tYWtlX2ludGVybmFsbHkiLCJzdmVfZHVwbGljYXRpb25zIiwiZmFjZWJvb2tfYnVzaW5lc3NfZXh0ZW5zaW9uX3NpbXBsZV9nYW1tYSIsImlucG9zdF9wYXlfY29kIiwibWV0YWZpZWxkc19iaW5kIiwic3ZlX3JlcGVhdGVyIiwic3ZlX3N0cnVjdHVyZS1kcmFnYW5kZHJvcCIsInN0b3JlZnJvbnRfYmFza2V0X2xpc3QiLCJzcGVjaWFsX29mZmVyc19zdG9ja3NfdjEiLCJzcGVjaWFsX29mZmVyc19kZWZhdWx0X3N0b2NrX2ZpeF9nYW1tYSIsInNwZWNpYWxfb2ZmZXJzX3BlcmNlbn
5RhZ2UiLCJzcGVjaWFsX29mZmVyc19tYW51YWxfcHJvbW8iLCJzdG9yZWZyb250X2pzX25ldyIsInN0b3JlZnJvbnRfanNfbmV3X3NhdmUiLCJzdmVfaG90LWtleXMiLCJzaG9waWxvX25ld19tZW51Iiwic2hvcGlsb19oaWRlX29sZF9tZW51IiwicGVyZm9ybWFuY2VfbG9hZF9yZXBvcnRzIiwidHJhZmZpY19sb2FkX2FnZ3JlZ2F0b3IiLCJtZXRhZmllbGRzX2Nhbl9hc3NpZ25fdG9fYXBwIiwiZ3Bzcl9wcm9kdWN0X2luZm9ybWF0aW9uIiwiZ3Bzcl9wcm9kdWN0X2luZm9ybWF0aW9uX3htbCIsInN0b3JlZnJvbnRfZ3BzciIsInN0b3JlZnJvbnRfZW5hYmxlX3R1cmJvX3ByZWZldGNoIiwicGF5bWVudHNfYXV0b3BheV92YWxpZGF0ZV9kb2N1bWVudF9udW1iZXIiLCJzdG9yZWZyb250X2Z1bGxfcmVnaXN0cmF0aW9uIiwiZ2FsbGVyeV9saXN0Iiwic3RvcmVmcm9udF9iYXNrZXRfaGlkZV9jb3N0X3Blcl9jb3VudHJ5IiwicHJvZHVjdF9vcHRpb25fc2VsZWN0X3N0cnVjdF9hZ2dyZWdhdGVfZGF0YSIsInRhc2tfbWFpbF9zZW5kX2J5X21hbmFnZXIiLCJwYXltZW50X2N1c3RvbV9uYW1lX2xpbWl0Iiwic3RvcmVmcm9udF9tYWNyb3NfaGlzdG9yeV9zYXZlIiwic3RvcmVmcm9udF9tYWNyb3NfaGlzdG9yeSIsInN0b3JlZnJvbnRfbWFjcm9zX2Nhbl9hY2Nlc3Nfb3JpZ2luYWwiLCJzdG9yZWZyb250X2Z1bGxfcmVnaXN0cmF0aW9uX2ZvcmNlIiwicGF5bWVudHNfc3RyaXBlIiwiZXh0ZXJuYWxfaW50ZWdyYXRpb25zX2FwaV90b2tlbnNfZ2FtbWEiLCJhcGlfdG9rZW5zX2FkbWluX21hbmFnZV9nYW1tYSIsInNvYXBfYXBpX2F1dGhlbnRpY2F0ZV9ieV90b2tlbl9nYW1tYSIsInBheW1lbnRzX3AyNF9pbnN0YWxsbWVudHNfaHViIiwiYXV0b19uYnBfdXBkYXRlc19nYW1tYSIsInhtbF9jYW1wYWlnbnNfa29qb3R5IiwiaW5wb3N0X3BheV92Ml91bnNldCIsInBheW1lbnRzX3BheW1lbnRfY2hhbm5lbHNfbmFtZSIsImlucG9zdF9wYXlfcmVmdW5kcyIsInNwZl92YWxpZGF0aW9uX2dhbW1hIiwicGF5bWVudHNfcDI0X2luc3RhbGxtZW50c19odWJfMF9vZmZlciIsImlucG9zdF9wYXlfdjIiLCJzdG9ja19hZGRpdGlvbmFsX2NvZGVzX2lwYSIsImh0dHBzX3JlZGlyZWN0XzMwOCIsImlucG9zdF9wYXlfZ2FsbGVyeSIsInNob3Blcl9zaGlwbWVudHNfcGhvbmVfcHJlZml4X2tvam90eSIsInBheW1lbnRzX2lucG9zdF9wYXlfc2F2ZWRfa2V5IiwibWV0YWZpZWxkc19oaWRlX3Njb3BlIiwiZmlsdGVyX29wdGlvbnNfYXZhaWxhYmlsaXR5Iiwic3RvcmVmcm9udF9uZXdfc2NoZW1hX3ZhbGlkYXRpb24iLCJhcHBzdG9yZV9hcHBsaWNhdGlvbl9yZWRpcmVjdCIsInN2ZV9jb2x1bW4tc3BsaXQiLCJmaWxlX3JvdGF0ZV9rb2pvdHkiLCJkYl90YWJsZV9jb21wYXJlX251bWVyaWNfZGF0YV90eXBlcyIsInByb2R1Y3RfZWRpdF9kYXRlX2dhbW1hIiwiZXh0ZXJuYWxfc3lzdGVtX25vdGlmaWNhdGlvbiIsIm5icF90YWJsZV9iX3VwZGF0ZXNfa29qb3R5IiwicHJvZHVjdF9pbWFnZV93Y2FnX2tvam90eSIsImlubGluZV9lZGl0X3RleHRhcmVhX2tvam90eSIsInRyaWFsX21haWxfc2VuZGluZ19ibG9ja2VkX2tvam90eSIsInBheW1lbnRfc3RyaXBlX3ZlcmlmaWNhdGlvbnMiLCJzd2lmdF9wcm9kdWN0X2dmeF9ub19jaGVjayIsImJpZ2RhdGFfaW5kZXhfcHJvZHVjdHMiLCJiaWdkYXRhX2luZGV4X3Byb2R1Y3RzX3ZhcmlhbnRzIiwiYmlnZGF0YV9pbmRleF9wYXJjZWxzIiwiYmlnZGF0YV9pbmRleF9vcmRlcnMiLCJiaWdkYXRhX2luZGV4X29yZGVyc19wcm9kdWN0cyIsImJpZ2RhdGFfaW5kZXhfb3JkZXJzX3RyYW5zYWN0aW9ucyIsInN0Zl9kZWZhdWx0X3NvcnRfZml4IiwiZmlsdGVyX3Byb2R1Y3RfYXR0cmlidXRlc192YWx1ZXNfaXBhIiwiYXBwc3RvcmVfbmV3X3VybF9nZW5lcmF0aW9uX2lwYSIsImdwc3JfcHJvZHVjdF9pbmZvcm1hdGlvbl9wb3N0X2RlcGxveSIsImNhY2hlX3RodW1ibmFpbHNfa29qb3R5Iiwid2ViaG9va3NfZm9yX2V4dGVybmFsX3BheW1lbnRzX2lwYSIsImlucG9zdF9wYXlfZGVidWciLCJzdG9yZWZyb250X2NvcHlfc2tpbl9pbl9iYWNrZ3JvdW5kIiwic3RvcmVmcm9udF9maWx0ZXJzX2NoZWNrc3VtIiwiZmlsdGVyX29wdGlvbnNfYXZhaWxhYmlsaXR5X2ZpeF9ub25fc3RvY2siLCJwYXltZW50X3BheXBhbGVjX25ld19idXR0b24iLCJhcmlhX2xpdmVfcndkIiwic3RvcmVmcm9udF9tb2R1bGVzX2NvbnRleHRzIiwiaW5wb3N0X25ld19nZW93aWRnZXRfa29qb3R5IiwibWluaW11bV9jYXJ0X3ZhbHVlX2Zvcl9zaGlwbWVudHNfbWluX2Nvc3QiLCJzdmVfd2VzdCIsInN2ZV96b29tIiwic3ZlX2RyYWctd2hvbGUtZ3JpZC1lbGVtZW50Iiwic3ZlX2dyaWQtZWxlbWVudHMtY2xpY2stYW5kLWVkaXQiLCJkZXZfc3ZlX25ldy1mb3Jtcy1ncmlkIiwiZGV2X3N0b3JlZnJvbnRfcmVtb3ZlX21hY3JvIiwicGF5bWVudHNfcDI0X3RvcF91cF9iYWxhbmNlIiwiZGV2X2Jhc2tldF9pZCIsImRldl9maWx0ZXJfb3B0aW9uc19zdG9ja19maXgiLCJmaWx0ZXJzX2Rpc2FibGVfZnV6enlfc2VhcmNoIiwiYXBwbGljYXRpb25zX3Nzb19sb2dpbiIsImNvcmVfY3VycmVuY3lfbWVtb3J5X2NhY2hlIiwiY29yZV9lbnRpdHlfcm93X2NhY2hlIiwiY29yZV9za2lwX2FkbWluX2xvZ3NfZm9yX3VzZXJvbmxpbmUiLCJkZXZfc3ZlX3ByZXZpZXctbW9kZSIsImRldl9zdmVfaW1hZ2UtYmFja2dyb3VuZCIsImRldl9iYWNrZ3JvdW5kX2ltYWdlIiwiYmlnZGF0YV9pbmRleF9zZWFyY2hfaGlzdG9yeSIsImJpZ2RhdGFfaW5kZXhfc2Vzc2lvbnMiLCJkZXZfcmVmZXJlcl9ob3N0X2FuYWx5emVyIiwibWVyY2hhbnRfdHJhY2tpbmciLCJwYXltZW50c19hcF92ZXJpZmljYXRpb25fdHJhbnNmZXIiLCJkZXZfc3lzdGVtX2ljb25zIiwiZGV2X3N0b3JlZnJvbnRfc2ltcGxlX2Jhc2tldF9hZGRyZXNzIiwiZGV2X3N2ZV93ZXN0LWJ5LWRlZmF1bHQiLCJkZXZfcHJvbW9jb2RlX2Nhc2VfaW5zZW5zaXRpdmUiLCJkZXZfd2ViaG9va3NfeWVhcmx5X2luZGV4aW5nX2VsYXN0aWMiLCJpbWFnZXNfY2FjaGVfbmFtZV9yZXZlcnNhbCIsImRldl9pbWFnZXNfdXBsb2Fkc190b19jb2xsZWN0aW9uc19hbmRfY2F0ZWdvcmllcyIsImRldl92aXN1YWxfc3ViY2F0ZWdvcmllcyIsImRldl9kaXNjb3VudHNfZml4IiwiZGV2X2Nzc19jbGFzc19vbl9mb3JtX2Vycm9ycyIsImRldl9iYXNrZXRfdXNlX2RvbWFpbl9sb2NhbGUiLCJkZXZfc2tpbnN0b3JlX2ltYWdlX3ZhbGlkYXRvciIsImRldl9zdmVfbmV3LWZvcm1zLW1vZHVsZXMiLCJkZXZfc3ZlX25ldy1mb3Jtcy1zZXR0aW5ncyIsImRldl9zdmVfcmVzaXphYmxlLXNpZGViYXIiLCJkZXZfc3ZlX3dlc3Qtb25seSIsInNob3Blcl9zc29faW50ZWdyYXRpb24iLCJwYXltZW50c19maW5hbmNpbmdfZGlzYWJsZV9lcmJlbyIsImRldl9wYXltZW50X3Zpc2liaWxpdHlfYW1vdW50X2lwYSIsInBheW1lbnRzX2V4dGVybmFsX2lmcmFtZV9pcGEiLCJkZXZfc2VhcmNoX2hpc3RvcnlfaW5kZXhpbmdfZWxhc3RpYyIsInN0b3JlZnJvbnRfYWRtaW5fcHJldmlld19pbmFjdGl2ZV9wcm9kdWN0cyIsImRldl9yZWNvbW1lbmRhdGlvbl9ub2ZvbGxvdyIsImRldl9zdG9yZWZyb250X3BhbmVsX2N1cnJlbmN5IiwiZGV2X2ZpbHRlcl9vcHRpb25zX3RvX3N0b2NrX29ubHkiLCJkZXZfbm90X2NsZWFuX21hcF90cmVlIiwiZGV2X3N0Zl80NDc3IiwiZGV2X3BheXBhbGVjX2J1dHRvbl92aXNpYmlsaXR5Iiwic2hvcGVyX3Nzb19zZW5kX2NoZWNrb3V0X2RhdGEiLCJzdG9yZWZyb250X3NvY2lhbF9sb2dpbl9zaG9wZXJfc3NvIiwicndkX3NvY2lhbF9sb2dpbl9zaG9wZXJfc3NvIiwic2hvcGVyX3Nzb19wcm92aWRlcnMiLCJzaG9wX2Rpc2FibGVfb25lX2RheV9hZnRlcl9ob2xpZGF5IiwiZGV2X2Zyb250YXBpX3N3aXRjaF90cmFuc2xhdGlvbnMiLCJidWd0cmFja2VyX2VzIiwiZGV2X3N2ZS10b2dnbGUtc2tpbi10cmVlLWVsZW1lbnRzIiwiZGV2X2lucG9zdF9wYXlfYnV0dG9uX3Zpc2liaWxpdHkiLCJkZXZfZ2FfdXNlcl9kYXRhX2ZpeCIsInBheW1lbnRfZ3BheV9kYl9jb25maWciLCJwYXltZW50c19zdHJpcGVfZGVsZXRlX2NvbmZpZ3VyYXRpb24iLCJzaG9wZXJfY2xpIiwicDI0X3BheW1lbnRfaGlkZV9ub25lX3Bsbl9wYXltZW50cyIsImRldl9ncHNyX2NvbnRhY3RfZm9ybV91cmwiLCJzdG9yZWZyb250X3JlZ2lzdHJhdGlvbiIsInN2ZS13eXNpd3lnX2Zyb2FsYSIsImRldl9zdmVfZGF0ZS10aW1lLXBpY2tlcnMiLCJpbnBvc3RfaW50ZXJuYXRpb25hbCIsImRldl9zZWxlY3RfdmFyaWFudF93aWR0aF9maXgiLCJkZXZfc3RvcmVmcm9udF9iYXNrZXRfZ2F1Z2VzIiwiZGV2X2ludGVybmF0aW9uYWxfb3JkZXJfaW5kaWNhdG9ycyIsInBheW1lbnRzX3N0cmlwZV9yZWZ1bmRzX2Zyb21fc3RyaXBlIiwiZGV2X3N2ZV9ob3QtZWRnZXMiLCJkZXZfaW50ZXJuYXRpb25hbF9jdXN0b21lcl9pbmRpY2F0b3JzIiwiZGV2X3N2ZV9tb2R1bGVfdHJhbnNsYXRpb25zIiwiZGV2X25ld19sYW5ndWFnZV9jb3B5aW5nIiwiZGV2X25hdGl2ZV9sYW5nX2Rpc3BsYXkiLCJkZXZfc3RvcmVmcm9udF9mb3JtX2hvbmV5cG90Iiwic2hvcGVyX2NhbXBhaWduc19mYWNlYm9va19mZWVkX2NhbXBhaWduX2lkIiwic2hvcGVyX2NhbXBhaWduc19vcmRlcl9maWx0ZXJfcmVmYWN0b3IiLCJhcHBsaWNhdGlvbl9wYXltZW50X3N1cHBvcnRlZGN1cnJlbmNpZXNfaXBhIiwiYXBwbGljYXRpb25fcGF5bWVudF9zdXBwb3J0ZWRjdXJyZW5jaWVzX3dpdGhfZGVmYXVsdF9pcGEiLCJkZXZfZml4X2ZiZV9iYXNrZXRfdmFsdWVfcndkIiwiZGV2X2ZpeF9mYmVfYmFza2V0X3ZhbHVlX3N0b3JlZnJvbnQiLCJkZXZfZml4X2ZiZV9wdXJjaGFzZV92YWx1ZV9yd2QiLCJkZXZfZGl2aXNpb25fYnlfemVyb19maXgiLCJkZXZfY2hhbmdlX2VzX21heF9oaXRzX3NpemVfdXBfdG9fMTAwMDAiLCJwYXltZW50c19maW5hbmNpbmciLCJwYXltZW50c19maW5hbmNpbmdfeW91bGVuZCIsInBheW1lbnRzX2ZpbmFuY2luZ19uZXN0X2Jpem5lc3QiLCJwYXltZW50c19maW5hbmNpbmdfYnJ1dHRvXzIiLCJwYXltZW50c19maW5hbmNpbmdfYnJ1dHRvIiwiZGV2X3ZpZGVvX2xhenlfbG9hZCIsIm1lbnVfbmF2aWdhdGlvbl9yd2QiLCJkZXZfZmlsdGVyc19zdWJjYXRlZ29yaWVzX3djYWciLCJkZXZfYnVuZGxlX3dpdGhfc2FtZV92YXJpYW50c19maXgiLCJkZXZfYnVuZGxlX3dpdGhfc2FtZV92YXJpYW50c18yX2ZpeCIsImRldl9zZWFyY2hfcG9wdXBfZml4ZXMiLCJkZXZfZGVmYXVsdF92YXJpYW50c19maXgiLCJkZXZfc3RvcmVmcm9udF9hYnNfZmlsdGVyIiwi
5ZGV2X2ZhcV9qc29uX2xkIiwiZGV2X3N2ZV9kZWZhdWx0X3ZhbHVlX251bGwiLCJkZXZfc3RvcmVmcm9udF9tZW51X29wdGltaXphdGlvbiIsImRldl90YWdfbGFiZWxfcmVkZXNpZ24iLCJkZXZfZW1wdHlfZmlsdGVyc19maXgiLCJkZXZfZ3JpZF9tb2JpbGVfd3JhcCIsImRldl9saXN0X2Rlc2NyaXB0aW9uX3BhZ2luYXRpb24iLCJhcHBzdG9yZV9wcmljaW5nX3BhY2thZ2VzIiwicGF5bWVudHNfYXV0b3BheV9ncGF5X3Rva2VuIiwic3dpZnRfcHJvZHVjdF9nZnhfd3JpdGUiLCJzd2lmdF9wcm9kdWN0X2dmeF9yZWFkIiwic3dpZnRfcHJvZHVjdF9nZnhfZnNfZGlzYWJsZWQiLCJkZXZfZ2lmX3N3aWZ0X3Byb2R1Y3RfZml4IiwiZGV2X3Nob3Blcl9zc29fd3d3IiwiZGV2X3NvY2lhbF9wcm92aWRlcnNfdXNlcl9jYWNoZSIsImRldl9zd2FwX2Jhc2tldF9hbmFseXRpY3NfZXZlbnRzIiwiZGV2X3N0b3JlZnJvbnRfYmFza2V0X3dhcmlhbnRzX2ZpeCIsImRldl9pbmNvcnJlY3RfdmFyaWFudHNfZml4IiwiZGV2X2ZpeF93ZWJwX3RodW1ibmFpbHMiLCJkZXZfcmVzZW5kX2NvbmZpcm1fcmVnaXN0ZXJfZW1haWwiLCJwYXltZW50X3AyNF9uZXdfc2V0dGluZ3NfcGF5bWVudF9jaGFubmVsc192aWV3IiwiZGV2X2J1bmRsZV9zZWxlY3RfZml4IiwiZGV2X2Zvcm1fY29udGFpbmVyIiwiZGV2X3N2ZV9yZXBlYXRlcl9kcmFnX2FuZF9kcm9wIiwiZGV2X3N2ZV9yZXBlYXRlcl9lZGl0X2xhYmVsIiwicGF5bWVudHNfcDI0X3RvcF91cF9iYWxhbmNlX3Blcl9jdXJyZW5jeSIsImRldl9nZW9sb2MiLCJkZXZfZ2VvbG9jX2N1cnJlbmN5X3BhcmFtX2ZpeCIsImRldl9zdG9yZWZyb250X2RvbnRfcmVuZGVyX3doZW5fbm9fY29udGV4dCIsImRldl9zZWxlY3RfcGxhY2Vob2xkZXIiLCJkZXZfc3ZlX3BvaW50X3BpY2tlciIsImRldl9zdG9yZWZyb250X2NhdGNoX21vZHVsZV9yZW5kZXJfZXJyb3IiLCJkZXZfc3RvcmVmcm9udF9jYXRjaF9leGNlcHRpb25faW5fb2JqZWN0X2FwaSIsImRldl9pbnBvc3RfZGVsaXZlcnlfbWFpbF9zaGlwbWVudCIsImRldl9zdG9yZWZyb250X3ZpdGVfYnVpbGQiLCJkZXZfb3B0aW9uX2Rpc3BsYXlfZml4IiwiZGV2X2ZpeF92YXJpYW50X3ByaWNlcyIsImRldl90YXNrX2hpc3RvcnlfdXBkYXRlIiwiZGV2X3Nlc3Npb25fbWV0cmljc19vcmRlcl9maXgiLCJkZXZfc2tpbnN0b3JlX3ByaWNpbmciLCJkZXZfY2hlY2tfaWZfbG9jYWxlX2V4aXN0cyIsImRldl9zZXNzaW9uX2Jhc2tldF9maXgiLCJkZXZfc3RvcmVmcm9udF92YWxpZGF0ZV9iYXNrZXRfaWQiLCJkZXZfc3BsaXRfYWRkaXRpb25hbF90YXhfaW5mbyIsImRldl9zdmVfcHJvamVjdC1taWdyYXRpb24iLCJkZXZfc3ZlX3ZhbGlkYXRlX21vZHVsZV9odG1sIiwiZGV2X3N2ZV9wb2ludF9waWNrZXJfdjIiLCJkZXZfc3ZlX3VuZG9fcmVkbyIsImRldl9hY2NvcmRpb25faGVpZ2h0X2ZpeCIsImRldl9hZGRpdGlvbmFsX2ZpZWxkc19jaGFuZ2Vfb3B0aW1pemF0aW9uIiwiZGV2X2NvdXBvbl9jb2Rlc19maXgiLCJkZXZfc2VhcmNoX2ljb25fZml4IiwiZGV2X29wdGlvbnNfZmlsdGVyX3NlbGVjdCIsImRldl9yZWFjdGl2ZV9zZWxlY3RlZF9pbmRleCIsImRldl9uZXdzbGV0dGVyX2F0dGFjaG1lbnRzX2xpbWl0cyIsImRldl9nb29nbGVfY3VzdG9tZXJfcmV2aWV3c193aWRnZXRfZml4IiwiZGV2X3N0Zl91cGdyYWRlX3NraW5fZml4IiwicGF5bWVudHNfc3RyaXBlX2Rpc2FibGVfZXhwcmVzc19jaGVja291dCIsImRldl9zdmVfZGl2aWRlciIsImRldl9wcm9wYWdhbmRhX3JlbW92ZV9kYXRhbGF5ZXJfbmFtZSIsImRldl9jb3JlX2hpZGVfZmlsdGVycyIsImRldl9zdmVfcGVyZl9tb2R1bGVfZWRpdCIsInN0b3JlZnJvbnRfb3JkZXJfaW5fdHJhbnNhY3Rpb24iLCJkZXZfc3RvcmVmcm9udF9tb2R1bGVzX2xpc3QiLCJkZXZfZmlsZV9zaXplX2xpbWl0IiwiZGV2X29wdGlvbnNfc2VsZWN0bGlrZV9yZWZhY3RvciIsImRldl9zdmVfZWRpdGFibGVfbGFiZWwiLCJwYXltZW50c19hdXRvcGF5X29uYm9hcmRpbmdfdmVyaWZpY2F0aW9uIiwiZGV2X3NlYXJjaF80MDRfaGlzdG9yeV9maXgiLCJkZXZfc3RvcmVmcm9udF90dXJib19yZXN0b3JlX2xvYWRlZF9ldmVudCIsImRldl9wYXltZW50c19iYXNrZXRfc3RyaXBlX2NhcmRfc3RvcmVmcm9udCIsImRldl9pbnBvc3RfYnV5IiwiZGV2X3NlYXJjaF91eF9maXhlcyIsImRldl9jYWNoZV9zZWFyY2hfcHJvZHVjdHMiLCJkZXZfcHJpY2VfYnV5aW5nX25ldCIsImRldl9wYXltZW50c19iYXNrZXRfc3RyaXBlX2FwcGxlX3BheSIsImRldl9pbmFjdGl2ZV9pbl9vYmplY3RfYXBpX2ZpeCIsImRldl9zdmVfcGVyc2lzdF96b29tX2RldmljZSIsImRldl9zdmVfcGFyZW50X2ZvcmNlZF9oaWRkZW5faW5kaWNhdG9yIiwiYmlnZGF0YV9zdG9ja19hZnRlcl9vcmRlcl9wbGFjZWQiLCJoZXJtZXNfc2hvcGVyX2luaG91c2VfcmV0dXJuc19hcHAiLCJkZXZfc3dpZnRfZGVsZXRlX29iamVjdF9hc3luYyIsImRldl9pbnBvc3RfZGVsaXZlcnlfbWFpbCIsImRldl9hZG1pbl9hbmFseXRpY3MiLCJkZXZfYWRtaW5fZm9ybV9jaGFuZ2VfZGV0ZWN0aW9uIiwiZGV2X2FkbWluX21peHBhbmVsX2FuYWx5dGljc19jbGllbnQiLCJhZG1pbl9za2luX2NoYW5nZSIsImFkbWluX2FuYWx5dGljc19jc3YiLCJhZG1pbl9hbmFseXRpY3NfZW5hYmxlZCIsImFkbWluX2FuYWx5dGljc19yZXBvcnRfb3JkZXJzX3NhbGVzIiwiZGV2X2FkbWluX3NpZGViYXJfZGJfc3RhdGVfc3NyIiwiZGV2X2F1cm9yYV9jb2xvcmluZ19iZWxsIiwiZGV2X2NsYXJpdHlfc3dpdGNoIiwiZGV2X2RhcmtfbW9kZV9ub3ZlbHR5IiwiZGV2X2dpZnRfY2FyZHNfc29vbiIsImRldl9yZXBvcnRzX25vdmVsdHkiLCJub25fc3RvY2tfdmFyaWFudHNfaXBhIiwiZGV2X2FkbWluX2FuYWx5dGljc19hcHBfc3RvcmVfYnJvd3NlIiwicGF5bWVudHNfc3RyaXBlX29uYm9hcmRpbmdfdmVyaWZpY2F0aW9uIiwiZGV2X2ZyZWVfb3JkZXJzX2NzcmZfZml4IiwiZGV2X3N2ZV9zb3J0YWJsZV9saXN0IiwiZGV2X3N0Zl9zb3J0X2l0ZW1zIiwiZGV2X3N0b3JlZnJvbnRfYWlfc2VvIiwiZGV2X3BheW1lbnRzX2Jhc2tldF9wMjRfYXBwbGVf
5cGF5IiwiZGV2X3BheW1lbnRzX2Jhc2tldF9hcHBsZV9wYXkiLCJkZXZfZXhwb3J0X2ZpbHRlcmVkX3Byb2R1Y3RzIiwiY29kZV9taXJyb3JfNiIsImRldl9zdmVfaW5hY3RpdmVfbGFuZ3VhZ2VzIiwiZGV2X2pvYl9xdWV1ZV9vcHRpbWl6YXRpb25zIiwiZGV2X3ByaWNlX2ZpbHRlcl9zb3J0X2RlZmF1bHRfc3RvY2tfb25seSIsImRldl9naWZ0X2NhcmRzX3BheW1lbnRfY2hlY2siLCJkZXZfZ2lmdF9jYXJkcyIsImRldl9wYXltZW50X2dpZnRfY2FyZCIsImRldl9mcm9udF9hcGlfcHJvZHVjdF9saXN0X29wdGltaXphdGlvbiIsImRldl9mcm9udF9hcGlfcHJvZHVjdF9saXN0X29wdGltaXphdGlvbl9jYWNoZSIsImRldl9mcm9udF9hcGlfcHJvZHVjdF9saXN0X3RpbWUiLCJkZXZfY3VzdG9tX2ZtYyIsImRldl9zZW9fY2F0ZWdvcnlfaGVhZGluZyIsImRldl9zZW9fY29sbGVjdGlvbl9oZWFkaW5nIiwiZGV2X3BheW1lbnRzX3AyNF9nb3BheV9nb29nbGVwYXlfaW5fYWxsX2N1cnJlbmNpZXMiLCJkZXZfbW92ZV9HQTRfdG9fbW9kdWxlIiwiZGV2X2NvbnNlbnRfbW9kZV9pbml0X2ZpeCIsImRldl9sb3lhbHR5X2V4cGlyYXRpb25fdGFza19vcHRpbWl6YXRpb24iLCJkZXZfZ29vZ2xlX3Jldmlld3Nfc3RpY2t5X2JhcnNfZml4IiwiZGV2X2Ryb3Bkb3duX2ZpdF92aWV3cG9ydF9wb3NpdGlvbmluZyIsImRldl9lbmFibGVfYW5hbHl0aWNzX2V2ZW50c193aXRoX3ByZWZpeCIsImRldl9pbnBvc3RwYXlfbmV3X2NyZWF0ZV9hY2NvdW50X3VybCIsImRldl9ub3RpZmljYXRpb25zIiwiZGV2X3NsaWRlcl9vcHRpbWl6YXRpb24iLCJkZXZfaHlkcmF0aW9uX2F0dHJpYnV0ZXMiLCJkZXZfYnVndHJhY2tlcl9lc19hY2wiLCJkZXZfaGFuZGxlX2ZsYXNoX21lc3NhZ2UiLCJkZXZfZml4X25vdF9yZWdpc3RlcmVkX2hlbHBlciIsImRldl9idW5kbGVfZnJvbnRfYXBpIiwiZGV2X3Nlb19yZWR1bmRhbnRfaGVhZGluZ3MiLCJkZXZfc3RmX2luc3RhbGxfc2tpbl9qb2IiLCJkZXZfbWF4X3NraW5fc2l6ZSIsImRldl9pb3NfY2FsbF9kZXRlY3Rpb25fZml4IiwiZGV2X3N2ZV9sYXlvdXQtcGVyLW9iamVjdCIsImRldl9zdmVfbGF5b3V0LXBlci1vYmplY3QtdjIiLCJkZXZfc3RvcmVmcm9udF9hZGRyZXNzX2Zvcm1fc2F2ZSIsInNob3Blcl9jYW1wYWlnbnNfaGlzdG9yaWNhbF9wcmljZSIsInN0b3JlZnJvbnRfZmlsbF9zdG9yYWdlX3N0b2NrX29uX3BsYWNlX29yZGVyIiwiZGV2X2ZlYXR1cmVkX3Byb2R1Y3RfdWlfZml4ZXMiLCJkZXZfc2VhcmNoX2ZvY3VzX3RyYXBfZml4IiwiY29tcGFueV9wcm9maWxlX2dvb2dsZV90YXhvbm9teSIsImRldl9rb2pvdHlfYWlfYWN0X3BpbnR1cmEiLCJkZXZfcndkX3Byb2R1Y3RfbGlzdF94bWxfcmVxdWVzdCIsImRldl9yd2RfeG1sX3JlcXVlc3RfMiIsImRldl9zZWN1cmVfZW5jb2RlIiwiZGV2X3J3ZF9iYXNrZXRfeG1sX3JlcXVlc3QiLCJkZXZfcHJvZHVjdF9yYXRpbmdfanNvbmxkX2ZpeCIsImRldl9jYWNoZWRfc2VsZWN0X29wdGlvbnMiLCJkZXZfY2FjaGVfZml4IiwiZGV2X2RhdGFiYXNlX3JlY29ubmVjdF9saW1pdCIsImRldl9zc2xfaW5mb19yZWZhY3RvciIsImRldl9tZW51X21haW5fc2VjdGlvbl9yZWRpcmVjdCIsImRldl9qc29ubGRfZ3NjX3VybHNfZml4IiwiZGV2X2ZtY180MDRfc3RhdHVzIiwiZGV2X3N0b3JlZnJvbnRfcm9ib3RzX3YyIiwiZGV2X3J3ZF9idW5kbGVfb3B0aW9uc19iYXNrZXQiLCJraWxsX2FsbGVncm8iLCJkZXZfcndkX3htbF9yZXF1ZXN0IiwicGF5bWVudHNfbmF0aW9uYWxfcGF5bWVudF9pbnN0aXR1dGlvbl9kaXNjbGFpbWVyIiwic3ZlX2Rldl9tb2R1bGVfcHJldmlldyIsImRldl9zZWFyY2hfZml4ZXMiLCJkZXZfZmlsdGVyc19tb2JpbGVfZm9jdXNfdHJhcCIsImRldl9zZW9fcndkX2RhdGFfdW5pZmljYXRpb24iLCJkZXZfcndkX3VybF9oZWxwZXIiLCJkZXZfZW1haWxfcmVkaXJlY3RfZml4IiwiZGV2X2ZlZWRfam9iX3F1ZXVlIiwiZGV2X2NhdGVnb3J5X3RyZWVfYmF0Y2hfbG9hZCIsImRldl9iYXNrZXRfcXVldWVfc2V0X3ByaWNlX2dyb3VwIiwiZGV2X3NraW5fY29weV9uZXciLCJkZXZfYXJ0aWNsZV9qc29ubGRfZml4ZXMiLCJkZXZfdmF0X2V1X3Zpc2liaWxpdHlfZml4IiwiZGV2X3JlY2FwdGNoYV9maXgiLCJzdmVfZGV2X2R5bmFtaWNfZm9udHMiLCJkZXZfcmVkaXJlY3RzX2xvb2t1cF9vcHRpbWl6YXRpb24iLCJzdmVfZGV2X2NvbHVtbl9yZXNpemVfZHJhZyIsImRldl9leHRlcm5hbF9wYXltZW50c19iYW5uZXIiLCJkZXZfc2VvX3JvYm90cyIsInN2ZV9kZXZfYmFja2dyb3VuZF9jb2xvcl92YXJpYWJsZSIsInBheW1lbnRzX3AyNF9vbmJvYXJkaW5nX3ZlcmlmaWNhdGlvbiIsImRldl9zZWFyY2hfY2xvc2VfYXJpYV9oaWRkZW5fZml4IiwiZGV2X3Bob2VuaXhfbGF6eV9sb2FkZXJfb3B0aW1pemF0aW9uIiwiZGV2X2JpZ2RhdGFfbmV3X2R1bXBzaG9wIiwiZGV2X3Nzb19kZWZhdWx0X3BheW1lbnRfbWV0aG9kX2ZpeCIsImRldl91cGRhdGVfbWFjcm8iLCJkZXZfc2VsZWN0X3dpZHRoX29wdGltaXphdGlvbiIsImRldl9yZWNhcHRjaGFfc29jaWFsX3JlZ2lzdGVyX2ZpeCIsImRldl9xdWV1ZV9wcm9kdWN0X3NvbGRfc3RhdHMiLCJoYXNoZWRfY2FjaGVfdGFncyIsImRldl9zdmVfbWl4cGFuZWwiLCJkZXZfYXBwc3RvcmVfY2FyZF9iYW5uZXIiLCJkZXZfZHJvcGRvd25fcmVmYWN0b3IiLCJkZXZfd2ViYXBpX2NhdGVnb3JpZXNfdHJlZV9iYXRjaF9sb2FkIiwiZGV2X3JlZGlyZWN0c19ydWxlc19jYWNoZSIsImRldl9rb2pvdHlfc3BsaXRfYnV0dG9uIiwiZGV2X3JvYm9fZm9sa3NfbWVudSIsImRldl9yb2JvX2ZvbGtzX21lbnVfbm92ZWx0eSIsImFkbWluX2FuYWx5dGljc19yZXBvcnRfcHJlc2V0cyIsImFkbWluX2FuYWx5dGljc19yZXBvcnRfb3JkZXJzX3Byb2R1Y3RzIiwiZGV2X3JlcG9ydHNfZnJlcXVlbnRseV9wdXJjaGFzZWRfbm92ZWx0eSIsInN2ZV9kZXZfaW5saW5lX21vZHVsZV90ZXh0X2VkaXQiLCJkZXZfcGFnaW5hdG9yX29wdGltaXphdGlvbiIsImRldl9zdG9yZWZyb250X3BhZ2luYXRvcl8yIiwic3RvcmVmcm9udF9kZWZlcl9zdG9ja19jYWNoZV9jbGVhbl9vbl9wbGFjZV9v
5cmRlcl8yIiwic3ZlX2Rldl9ncmlkX2Nvcm5lcnNfcmFkaXVzIiwic3dpZnRfcHJvZHVjdF9nZnhfc2tpcF9yZW5kZXJfY2hlY2siLCJkZXZfc3RvcmVmcm9udF9saXN0X2hhc19hdF9sZWFzdCIsImRldl9leHBvcnRfcHJvZHVjdHNfaW5fcHJvZ3Jlc3NfYmFyIiwic3dpZnRfcHJvZHVjdF9nZnhfc2tpcF9oZWFkIiwic3ZlX2Rldl9zdG9yZWZyb250X21vZHVsZV9yZWluaXQiLCJzdmVfZGV2X3NraW5fZmlsZXMiLCJkZXZfb3JkZXJfdGltZWxpbmUiXQ==" data-ajaxbasket-mode="2"> 6 <meta http-equiv="X-UA-Compatible" content="IE=edge"> 7 <meta charset="utf-8"> 8 9 <link rel="preload" href="/skins/user/rwd_shoper_25/cache/sfc/MzE6NzI5OjUuMjYuNTY.css" as="style"> 10 <link rel="preload" href="/assets/js/frontstore/main.7549223feec23b23f876.min.js" as="script"> 11 <link rel="preload" href="/userdata/public/locales/pl_PL.js?sci=729" as="script"> 12 13 <title>Pistolet do noszenia â jak wybraÄ? | twojabron.pl</title> 14 <meta name="description" content="Pistolet do noszenia: przepisy, kabura, Glock 19, CZ P-10 C czy Glock 26? Sprawdź, kto może legalnie nosiÄ broÅ i jak wybraÄ pierwszy kompakt do EDC" /> 15 <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0"> 16 <meta name="mobile-web-app-capable" content="yes"> 17 18 19 <link rel="canonical" href="https://twojabron.pl/pl/blog/Jak-wybrac-pistolet-do-noszenia-Poradnik-dla-poczatkujacych/134" /> 20 21 22 <link rel="home" href="/" /> 23 <link rel="shortcut icon" href="/skins/user/rwd_shoper_25/images/favicon.png"> 24 <link rel="manifest" href="/userdata/public/manifest.json"> 25 <link rel="apple-touch-icon" sizes="192x192" href="/userdata/public/pwa/icons/192x192_icon.png"> 26 27 <link rel="preconnect" href="https://fonts.googleapis.com"> 28 <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> 29 <link href="https://fonts.googleapis.com/css2?family=Manrope:wght@300;400;700&family=Teko&display=swap" rel="stylesheet"> 30 31 <link rel="dns-prefetch" href="//fonts.gstatic.com"> 32 <link rel="preconnect" href="//fonts.gstatic.com"> 33 <link rel="stylesheet" type="font/woff" href="/skins/user/rwd_shoper_25/images/rwd-custom.woff?gptqpz" crossorigin> 34 <link rel="stylesheet" type="font/woff" href="/skins/user/rwd_shoper_25/images/fontawesome-webfont.woff?v=4.0.3" crossorigin> 35 36 37 <div id="preloader"> 38 <img src="/skins/user/rwd_shoper_25/images/logo.png" alt="twojabron.pl" /> 39 </div> 40 41 <style> 42 html.js #preloader { 43 position: fixed; 44 left: 0; 45 top: 0; 46 width: 100%; 47 height: 100%; 48 right: 0; 49 bottom: 0; 50 background: white; 51 transition: opacity 0.2s; 52 transform: translate3d(0, 0, 0); 53 will-change: opacity; 54 z-index: 999999; 55 opacity: 1; 56 } 57 #preloader img { 58 position: absolute; 59 top: 50%; 60 left: 50%; 61 transform: translate(-50%, -50%); 62 max-width: 90%; 63 max-height: 90%; 64 } 65 #preloader.hidden { 66 display: none !important; 67 } 68 </style> 69 70
70<script> 71 document.getElementsByTagName('html')[0].classList.add("js"); 72 73 var preloader = document.getElementById("preloader"); 74 function hidePreloader(){ 75 setTimeout(function () { 76 preloader.style.opacity = '0'; 77 setTimeout(function () { 78 preloader.classList.add("hidden"); 79 }, 200); 80 }, 0); 81 } 82 if (sessionStorage.getItem("firstVisit") == 1){ 83 preloader.classList.add("hidden"); 84 } 85 sessionStorage.setItem("firstVisit", 1); 86 87 window.userLoggedIn = false; 88 89 </script>
89 90 91 92 <link id="csslink" rel="stylesheet" type="text/css" href="/skins/user/rwd_shoper_25/cache/sfc/MzE6NzI5OjUuMjYuNTY.css" /> 93 94
94<script type="text/javascript" src="/assets/js/frontstore/main.7549223feec23b23f876.min.js"></script>
94 95
95<script type="text/javascript" src="/userdata/public/locales/pl_PL.js?sci=729"></script>
95 96 97
97<script src="https://dcsaascdn.net/js/front-api-1.5.0.min.js" async></script>
97 98<meta name="google-site-verification" content="d9Gxa2LAQh8nIq7rT-X28Tz9GkYP0zHJdFHE53_39Ck" /> 99<meta name="google-site-verification" content="MQsTiOIXp1MjyG5YDKMZ9zBVVbxe0dZT9eW1wMcW5mA" /> 100<!-- Google Tag Manager -->
101<script>
vendor: 331 bytes, lines 101-105
101(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start': 102new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0], 103j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src= 104'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f); 105})(window,document,'script','dataLayer','
105GTM-MB6TS5MR
vendor: 3 bytes, line 105
105');
105</script>
105 106<!-- End Google Tag Manager --> 107<!-- MailerLite Universal -->
108<script> 109 (function(w,d,e,u,f,l,n){w[f]=w[f]||function(){(w[f].q=w[f].q||[]) 110 .push(arguments);},l=d.createElement(e),l.async=1,l.src=u, 111 n=d.getElementsByTagName(e)[0],n.parentNode.insertBefore(l,n);}) 112 (window,document,'script','https://assets.mailerlite.com/js/universal.js','ml'); 113 ml('account', '2452209'); 114</script>
114 115<!-- End MailerLite Universal --> 116<meta name="shoper_campaigns_analytics_measurment_id" content="G-VW40GS7Y2C"/> 117 118 119</head><body id="shop_news134" class="shop_news">
119<script>window.customerPrivacy.onPlatformConsentGranted(() =>{window.Shop = window.Shop || {}; Shop.values = Shop.values || {}; Shop.values.partnerEE=true; Shop.values.partnerData="17914369791382535";
vendor: 317 bytes, line 119
119(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src='//www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);})(window,document,'script','shopLayer','
119GTM-T68LWS
vendor: 3 bytes, line 119
119');
119});</script>
119 120 121<div class="none" id="categoriesCanNotBePurchased" data-ids="20,21,22,23, 24,25,30,26,54,35,81,44,79,86,48,31,27,80,45,49,82,55,87"></div> 122 123 124<div class="wrap rwd"> 125 <div class="header-bar desktop-only"> 126 <div class="container"> 127 <div class="header-bar__left"> 128 <img src="/userdata/public/assets/svg/location.svg" alt="" width="18" height="22" class="location-ico" /> 129 Sklep i strzelnica: ul. MyÅliwska 6, 05-555 SuchodóÅ, Tarczyn, <a href="tel:784695388">tel.: 784 695 388 </a><a class="map" href="/kontakt-i-dane-firmy"> zobacz na mapie</a> 130 </div> 131 <div class="header-bar__right"> 132 Gwarantujemy profesjonalnÄ obsÅugÄ oraz peÅne doradztwo w zakresie doboru sprzÄtu 133 </div> 134 <div class="box" id="box_languages"> 135 136 <div class="innerbox"> 137 <ul class="listwithicons"> 138 <li class="selected" data-count="0"> 139 <a href="/" title="polski / Polska" class="spanhover"> 140 <span>PL</span> 141 </a> 142 </li> 143 144 </ul> 145 </div> 146 </div> 147 </div> 148 </div> 149 <header class="row desktop-only"> 150 <div class="logo-bar row container"> 151 <a href="/" title="Strona gÅówna" class="link-logo link-logo-img"> 152 <img src="/skins/user/rwd_shoper_25/images/logo.png" alt="twojabron.pl" width="85" height="79"> 153 </a> 154 <div class="header-links"> 155 <div class="header-links__link favourities"> 156 <a href="/pl/panel/favourites" class="header-links__ico"> 157 <svg xmlns="http://www.w3.org/2000/svg" width="20" height="21" viewBox="0 0 20 21" fill="none"> 158 <g clip-path="url(#clip0_443_946)"> 159 <mask id="mask0_443_946" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="0" y="0" width="20" height="21"> 160 <path d="M0 0.750002H20V20.75H0V0.750002Z" fill="white"/> 161 </mask> 162 <g mask="url(#mask0_443_946)"> 163 <path d="M2.46875 3.84644H7.48957V1.33601H2.46875V3.84644Z" stroke="#313131" stroke-width="1.5" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/> 164 <path d="M12.5104 3.84644H17.5312V1.33601H12.5104V3.84644Z" stroke="#313131" stroke-width="1.5" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/> 165 </g> 166 <path d="M12.5104 6.35676H7.48959L7.71784 8.86719H12.2822L12.5104 6.35676Z" stroke="#313131" stroke-width="1.5" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/> 167 <path d="M3.72395 6.35669H6.23438V3.84626H3.72395V6.35669Z" stroke="#313131" stroke-width="1.5" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/> 168 <path d="M13.7656 6.35669H16.2761V3.84626H13.7656V6.35669Z" stroke="#313131" stroke-width="1.5" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/> 169 <mask id="mask1_443_946" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="0" y="0" width="20" height="21"> 170 <path d="M0 0.750002H20V20.75H0V0.750002Z" fill="white"/> 171 </mask> 172 <g mask="url(#mask1_443_946)"> 173 <path d="M12.2822 8.86719H13.138L13.7657 13.888H11.8257L11.2552 20.1641H18.7865L17.5312 6.35676H12.5104L12.2822 8.86719Z" stroke="#313131" stroke-width="1.5" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/> 174 <path d="M7.71782 8.86719H6.862L6.23434 13.888H8.17427L8.74477 20.1641H1.21352L2.46876 6.35676H7.48958L7.71782 8.86719Z" stroke="#313131" stroke-width="1.5" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/> 175 </g> 176 <path d="M13.138 8.86708H6.86199L6.23438 13.8879H13.7656L13.138 8.86708Z" stroke="#313131" stroke-width="1.5" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/> 177 </g> 178 <defs> 179 <clipPath id="clip0_443_946"> 180 <rect width="20" height="20" fill="white" transform="translate(0 0.75
180)"/> 181 </clipPath> 182 </defs> 183 </svg> 184 <span class="header-links__name">Ulubione</span> 185 </a> 186 </div> 187 188 <div class="header-links__link my-account"> 189 <a href="/pl/panel" class="header-links__ico"> 190 <svg xmlns="http://www.w3.org/2000/svg" width="25" height="25" viewBox="0 0 25 25" fill="none"> 191 <path d="M16.7489 6.5C16.7489 8.57107 15.0699 10.25 12.9989 10.25C10.9278 10.25 9.24886 8.57107 9.24886 6.5C9.24886 4.42893 10.9278 2.75 12.9989 2.75C15.0699 2.75 16.7489 4.42893 16.7489 6.5Z" stroke="#313131" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> 192 <path d="M5.5 20.6182C5.57031 16.5369 8.90074 13.25 12.9989 13.25C17.0971 13.25 20.4276 16.5371 20.4977 20.6185C18.2149 21.666 15.6753 22.25 12.9992 22.25C10.3229 22.25 7.78296 21.6659 5.5 20.6182Z" stroke="#313131" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> 193 </svg> 194 <span class="header-links__name">Moje konto</span> 195 </a> 196 <div class="header-links__inner"> 197 <ul class="links inline"> 198 <li class="register"> 199 <a href="/pl/reg"class="register"> 200 <span>Zarejestruj siÄ</span> 201 </a> 202 </li> 203 <li class="login"> 204 <a href="/pl/login" class="login"> 205 <span>Zaloguj siÄ</span> 206 </a> 207 </li> 208 </ul> 209 210 </div> 211 </div> 212 <div class="header-links__link quick-basket"> 213 <a href="/pl/basket" title="Koszyk" class="header-links__ico basket empty-basket"> 214 <svg xmlns="http://www.w3.org/2000/svg" width="21" height="21" viewBox="0 0 21 21" fill="none"> 215 <path d="M14.25 9V4.5C14.25 2.42893 12.5711 0.75 10.5 0.75C8.42893 0.75 6.75 2.42893 6.75 4.5V9M18.106 7.00723L19.3692 19.0072C19.4391 19.6715 18.9183 20.25 18.2504 20.25H2.74963C2.08172 20.25 1.56089 19.6715 1.63081 19.0072L2.89397 7.00723C2.95424 6.43466 3.43706 6 4.01279 6H16.9872C17.5629 6 18.0458 6.43466 18.106 7.00723ZM7.125 9C7.125 9.20711 6.9571 9.375 6.75 9.375C6.54289 9.375 6.375 9.20711 6.375 9C6.375 8.79289 6.54289 8.625 6.75 8.625C6.9571 8.625 7.125 8.79289 7.125 9ZM14.625 9C14.625 9.20711 14.4571 9.375 14.25 9.375C14.0429 9.375 13.875 9.20711 13.875 9C13.875 8.79289 14.0429 8.625 14.25 8.625C14.4571 8.625 14.625 8.79289 14.625 9Z" stroke="#313131" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> 216 </svg> 217 <span class="countlabel"> 218 <span></span> 219 <b> 220 (pusty) 221 </b> 222 </span> 223 <span class="header-links__name">Koszyk</span> 224 </a> 225 <div class="basket-contain empty-mobile-basket"> 226 <div class="only-empty"> 227 <p>Twój koszyk jest pusty.</p> 228 <div class="btn close-on-click">Kontynuuj zakupy</div> 229 </div> 230 <div class="basket-products"> 231 <ul class="basket-product-list"> 232 </ul> 233 </div> 234 235 <div class="basket-summery"> 236 <a href="/pl/basket">Zamawiam</a>
237 <span class="basket-price"> 238 <span class="price-total"> 239 <span>suma:</span> 240 <strong class="price-products">0,00 zÅ</strong> 241 </span> 242 </span> 243 </div> 244 </div> 245 246 </div> 247 </div> 248 <div class="search__container"> 249 <form data-product-view-type="" data-search-promotions-route="/pl/promotions/1/default/1/newsName/Jak-wybrac-pistolet-do-noszenia-Poradnik-dla-poczatkujacych/newsId/134" data-base-dir="" class="js__search search search-form" action="/pl/s" method="post"> 250 <div class="none bottest"><!-- <input name="bottest1" value="1" /> --> <input name="bottest2" /></div> 251 <div class="search-input search__input-area r--l-flex r--l-flex-vcenter"> 252 <div class="search__input-area-item"> 253 <span class="js__search-clear-btn search__btn icon icon-close search__icon none" role="button" aria-label="clear search input"></span> 254 <img class="search__loader none" src="/libraries/images/loader.svg"> 255 </div> 256 257 <div class="search__input-area-item search__input-area-item_grow"> 258 <input maxlength="255" class="search__input" name="search" type="search" autocomplete="off" placeholder="Znajdź produkt w sklepie"> 259 </div> 260 261 <div class="search__input-area-item"> 262 <span class="js__search-close-btn icon icon-back" role="button" aria-label="close search"></span> 263 <button type="button" class="js__search-submit-btn search-btn search__input-area-item search__btn-search r--l-flex r--l-flex-vcenter r--l-flex-hcenter"> 264 <svg xmlns="http://www.w3.org/2000/svg" width="20" height="21" viewBox="0 0 20 21" fill="none"> 265 <path fill-rule="evenodd" clip-rule="evenodd" d="M8.25 2.25C4.52208 2.25 1.5 5.27208 1.5 9C1.5 12.7279 4.52208 15.75 8.25 15.75C10.1142 15.75 11.8006 14.9953 13.023 13.773C14.2453 12.5506 15 10.8642 15 9C15 5.27208 11.9779 2.25 8.25 2.25ZM0 9C0 4.44365 3.69365 0.75 8.25 0.75C12.8063 0.75 16.5 4.44365 16.5 9C16.5 11.0078 15.782 12.8491 14.5899 14.2793L19.2803 18.9697C19.5732 19.2626 19.5732 19.7374 19.2803 20.0303C18.9874 20.3232 18.5126 20.3232 18.2197 20.0303L13.5293 15.3399C12.0991 16.532 10.2578 17.25 8.25 17.25C3.69365 17.25 0 13.5563 0 9Z" fill="#313131"/> 266 </svg> 267 </button> 268 </div> 269 </div> 270 271 <div class="search__content"></div> 272 273 <input type="hidden" class="js__search-settings" value="eyJTSE9XX1BIUkFTRV9TVUdHRVNUSU9OUyI6MSwiU0hPUlRFTl9OQU1FUyI6MCwiU0hPV19NT0JJTEVfQlROIjowLCJESVNQTEFZX0ZPUk1BVCI6MSwiUkVTVUxUU19QRVJfUEFHRSI6MTAsIkNBVEVHT1JJRVNfRU5BQkxFRCI6MSwiUFJPRFVDRVJTX0VOQUJMRUQiOjEsIlBST0RVQ1RTX0VOQUJMRUQiOjEsIkZST05UX09SSUdJTkFMX1FVRVJZX1BIUkFTRSI6IjAiLCJQUk9EVUNUX0FVVE9DT01QTEVURV9CVVRUT05fVkVSU0lPTiI6MiwiU0hPV19QUk9EVUNUU19QUklDRSI6MSwiU0hPV19QUk9EVUNUU19TQ09SRSI6MCwiU0hPV19QUk9EVUNUU19BVkFJTEFCSUxJVFkiOjF9"> 274</form> </div> 275 </div> 276 </header> 277 278 <div class="menu row"> 279 <nav class="innermenu row container relative"> 280 <ul class="menu-list"> 281 <li class="menu-head menu-mobile-only"> 282 <div class="menu-nav sidebar-nav"> 283 <span class="sidebar-back"></span> 284 <span class="sidebar-home"></span> 285 <span class="sidebar-close"></span> 286 </div> 287 <div class="menu-current"> 288 <span class="current-name">Menu</span> 289 <span class="current-link none"><a href="">zobacz wszystkie</a></span> 290 </div> 291 </li> 292 <li class="home-link-menu-li">
293 <span class="h3"> 294 295 <a href="/" title="Strona gÅówna"> 296 <img src="/libraries/images/1px.gif" alt="Strona gÅówna" class="px1"> 297 </a> 298 </span> 299 </li> 300 301 <li class="parent" id="hcategory_30"> 302 <span class="h3"> 303 <a href="/kategoria/bron-nowa" id="headlink4" class="spanhover mainlevel"> 304 <span>BROÅ NOWA</span> 305 <img src="/libraries/images/1px.gif" alt="" class="px1"> 306 </a> 307 </span> 308 <div class="megamenu-wrapper"> <div class="submenu level1"> 309 <ul class="level1"> 310 <li class="" id="hcategory_26"> 311 <span class="h3"> 312 <a href="/kategoria/bron-nowa/ar-ak" 313 title="KARABINKI AR/AK" id="headercategory26" class="spanhover"> 314 <span>KARABINKI AR/AK</span> 315 <img src="/libraries/images/1px.gif" alt="" class="px1" /> 316 </a> 317 </span> 318 319 </li> 320 <li class="" id="hcategory_54"> 321 <span class="h3"> 322 <a href="/kategoria/bron-nowa/bron-dluga-centralny-zaplon" 323 title="DÅUGA KULOWA" id="headercategory54" class="spanhover"> 324 <span>DÅUGA KULOWA</span> 325 <img src="/libraries/images/1px.gif" alt="" class="px1" /> 326 </a> 327 </span> 328 329 </li> 330 <li class="" id="hcategory_81"> 331 <span class="h3"> 332 <a href="/kategoria/bron-nowa/bron-krotka-centralny-zaplon" 333 title="PISTOLETY I REWOLWERY" id="headercategory81" class="spanhover"> 334 <span>PISTOLETY I REWOLWERY</span> 335 <img src="/libraries/images/1px.gif" alt="" class="px1" /> 336 </a> 337 </span> 338 339 </li> 340 <li class="" id="hcategory_44"> 341 <span class="h3"> 342 <a href="/kategoria/bron-nowa/bron-dluga-bocznego-zaplonu" 343 title="KARABINKI BOCZNEGO ZAPÅONU" id="headercategory44" class="spanhover"> 344 <span>KARABINKI BOCZNEGO ZAPÅONU</span> 345 <img src="/libraries/images/1px.gif" alt="" class="px1" /> 346 </a> 347 </span> 348 349 </li> 350 <li class="" id="hcategory_79"> 351 <span class="h3"> 352 <a href="/kategoria/bron-nowa/bron-krotka-boczny-zaplon" 353 title="PISTOLETY BOCZNEGO ZAPÅONU" id="headercategory79" class="spanhover"> 354 <span>PISTOLETY BOCZNEGO ZAPÅONU</span>
355 <img src="/libraries/images/1px.gif" alt="" class="px1" /> 356 </a> 357 </span> 358 359 </li> 360 <li class="" id="hcategory_86"> 361 <span class="h3"> 362 <a href="/kategoria/bron-nowa/bron-gladkolufowa" 363 title="BROÅ MYÅLIWSKA ÅRUTOWA" id="headercategory86" class="spanhover"> 364 <span>BROÅ MYÅLIWSKA ÅRUTOWA</span> 365 <img src="/libraries/images/1px.gif" alt="" class="px1" /> 366 </a> 367 </span> 368 369 </li> 370 <li class="" id="hcategory_48"> 371 <span class="h3"> 372 <a href="/kategoria/bron-nowa/bron-kombinowana" 373 title="KOMBINOWANA MYÅLIWSKA" id="headercategory48" class="spanhover"> 374 <span>KOMBINOWANA MYÅLIWSKA</span> 375 <img src="/libraries/images/1px.gif" alt="" class="px1" /> 376 </a> 377 </span> 378 379 </li> 380 <li class="" id="hcategory_35"> 381 <span class="h3"> 382 <a href="/kategoria/bron-nowa/bron-dluga-centralny-zaplon/czesci-broni" 383 title="CZÄÅCI BRONI" id="headercategory35" class="spanhover"> 384 <span>CZÄÅCI BRONI</span> 385 <img src="/libraries/images/1px.gif" alt="" class="px1" /> 386 </a> 387 </span> 388 389 </li> 390 </ul> 391 </div> 392 <div class="menu__category-images"> 393 <div class="menu__category-images-img"> 394 395 </div> 396 397 </div> 398 399 </div> </li> 400 <li class="parent" id="hcategory_31"> 401 <span class="h3"> 402 <a href="/kategoria/bron-uzywana" id="headlink5" class="spanhover mainlevel"> 403 <span>BROÅ UÅ»YWANA</span> 404 <img src="/libraries/images/1px.gif" alt="" class="px1"> 405 </a> 406 </span> 407 <div class="megamenu-wrapper"> <div class="submenu level1"> 408 <ul class="level1"> 409 <li class="" id="hcategory_55"> 410 <span class="h3"> 411 <a href="/kategoria/bron-uzywana/bron-dluga-centralny-zaplon" 412 title="DÅUGA KULOWA" id="headercategory55" class="spanhover"> 413 <span>DÅUGA KULOWA</span> 414 <img src="/libraries/images/1px.gif" alt="" class="px1" /> 415 </a> 416 </span> 417 418 </li> 419 <li class="" id="hcategory_82">
420 <span class="h3"> 421 <a href="/kategoria/bron-uzywana/bron-krotka-centralny-zaplon" 422 title="PISTOLETY I REWOLWERY" id="headercategory82" class="spanhover"> 423 <span>PISTOLETY I REWOLWERY</span> 424 <img src="/libraries/images/1px.gif" alt="" class="px1" /> 425 </a> 426 </span> 427 428 </li> 429 <li class="" id="hcategory_45"> 430 <span class="h3"> 431 <a href="/kategoria/bron-uzywana/bron-dluga-bocznego-zaplonu" 432 title="KARABINKI BOCZNEGO ZAPÅONU" id="headercategory45" class="spanhover"> 433 <span>KARABINKI BOCZNEGO ZAPÅONU</span> 434 <img src="/libraries/images/1px.gif" alt="" class="px1" /> 435 </a> 436 </span> 437 438 </li> 439 <li class="" id="hcategory_80"> 440 <span class="h3"> 441 <a href="/kategoria/bron-uzywana/bron-krotka-boczny-zaplon" 442 title="PISTOLETY BOCZNEGO ZAPÅONU" id="headercategory80" class="spanhover"> 443 <span>PISTOLETY BOCZNEGO ZAPÅONU</span> 444 <img src="/libraries/images/1px.gif" alt="" class="px1" /> 445 </a> 446 </span> 447 448 </li> 449 <li class="" id="hcategory_87"> 450 <span class="h3"> 451 <a href="/kategoria/bron-uzywana/bron-gladkolufowa" 452 title="ÅRUTOWA" id="headercategory87" class="spanhover"> 453 <span>ÅRUTOWA</span> 454 <img src="/libraries/images/1px.gif" alt="" class="px1" /> 455 </a> 456 </span> 457 458 </li> 459 <li class="" id="hcategory_49"> 460 <span class="h3"> 461 <a href="/kategoria/bron-uzywana/bron-kombinowana" 462 title="KOMBINOWANA MYÅLIWSKA" id="headercategory49" class="spanhover"> 463 <span>KOMBINOWANA MYÅLIWSKA</span> 464 <img src="/libraries/images/1px.gif" alt="" class="px1" /> 465 </a> 466 </span> 467 468 </li> 469 <li class="" id="hcategory_116"> 470 <span class="h3"> 471 <a href="/pl/c/CZESCI-BRONI/116" 472 title="CZÄÅCI BRONI" id="headercategory116" class="spanhover"> 473 <span>CZÄÅCI BRONI</span> 474 <img src="/libraries/images/1px.gif" alt="" class="px1" /> 475 </a> 476 </span> 477 478 </li> 479 </ul> 480 </div> 481 <div class="menu__category-images"> 482 <div class="menu__category-images-img"> 483 484 </div> 485 486 </div> 487 488 </div> </li> 489 <li class="parent" id="hcategory_20">
490 <span class="h3"> 491 <a href="/kategoria/amunicja" id="headlink9" class="spanhover mainlevel"> 492 <span>AMUNICJA</span> 493 <img src="/libraries/images/1px.gif" alt="" class="px1"> 494 </a> 495 </span> 496 <div class="megamenu-wrapper"> <div class="submenu level1"> 497 <ul class="level1"> 498 <li class="" id="hcategory_23"> 499 <span class="h3"> 500 <a href="/kategoria/amunicja/amunicja-kulowa-sportowa" 501 title="AMUNICJA KULOWA SPORTOWA" id="headercategory23" class="spanhover"> 502 <span>AMUNICJA KULOWA SPORTOWA</span> 503 <img src="/libraries/images/1px.gif" alt="" class="px1" /> 504 </a> 505 </span> 506 507 </li> 508 <li class="" id="hcategory_25"> 509 <span class="h3"> 510 <a href="/kategoria/amunicja/amunicja-srutowa-sportowa" 511 title="AMUNICJA ÅRUTOWA SPORTOWA" id="headercategory25" class="spanhover"> 512 <span>AMUNICJA ÅRUTOWA SPORTOWA</span> 513 <img src="/libraries/images/1px.gif" alt="" class="px1" /> 514 </a> 515 </span> 516 517 </li> 518 <li class="" id="hcategory_21"> 519 <span class="h3"> 520 <a href="/kategoria/amunicja/amunicja-bocznego-zaplonu" 521 title="AMUNICJA BOCZNEGO ZAPÅONU" id="headercategory21" class="spanhover"> 522 <span>AMUNICJA BOCZNEGO ZAPÅONU</span> 523 <img src="/libraries/images/1px.gif" alt="" class="px1" /> 524 </a> 525 </span> 526 527 </li> 528 <li class="" id="hcategory_22"> 529 <span class="h3"> 530 <a href="/kategoria/amunicja/amunicja-kulowa-mysliwska" 531 title="AMUNICJA KULOWA MYÅLIWSKA" id="headercategory22" class="spanhover"> 532 <span>AMUNICJA KULOWA MYÅLIWSKA</span> 533 <img src="/libraries/images/1px.gif" alt="" class="px1" /> 534 </a> 535 </span> 536 537 </li> 538 <li class="" id="hcategory_24"> 539 <span class="h3"> 540 <a href="/kategoria/amunicja/amunicja-srutowa-mysliwska" 541 title="AMUNICJA ÅRUTOWA MYÅLIWSKA" id="headercategory24" class="spanhover"> 542 <span>AMUNICJA ÅRUTOWA MYÅLIWSKA</span> 543 <img src="/libraries/images/1px.gif" alt="" class="px1" /> 544 </a> 545 </span> 546 547 </li> 548 </ul> 549 </div> 550 <div class="menu__category-images"> 551 <div class="menu__category-images-img"> 552 553 </div> 554 555 </div> 556 557 </div> </li> 558 <li class="parent" id="hcategory_68">
559 <span class="h3"> 560 <a href="/kategoria/termowizja" id="headlink7" class="spanhover mainlevel"> 561 <span>TERMOWIZJA</span> 562 <img src="/libraries/images/1px.gif" alt="" class="px1"> 563 </a> 564 </span> 565 <div class="megamenu-wrapper"> <div class="submenu level1"> 566 <ul class="level1"> 567 <li class="" id="hcategory_33"> 568 <span class="h3"> 569 <a href="/kategoria/termowizja/celowniki-termowizyjne" 570 title="CELOWNIKI I LUNETY TERMOWIZYJNE" id="headercategory33" class="spanhover"> 571 <span>CELOWNIKI I LUNETY TERMOWIZYJNE</span> 572 <img src="/libraries/images/1px.gif" alt="" class="px1" /> 573 </a> 574 </span> 575 576 </li> 577 <li class="" id="hcategory_63"> 578 <span class="h3"> 579 <a href="/kategoria/termowizja/monikulary-termowizyjne" 580 title="MONOKULARY TERMOWIZYJNE" id="headercategory63" class="spanhover"> 581 <span>MONOKULARY TERMOWIZYJNE</span> 582 <img src="/libraries/images/1px.gif" alt="" class="px1" /> 583 </a> 584 </span> 585 586 </li> 587 <li class="" id="hcategory_67"> 588 <span class="h3"> 589 <a href="/kategoria/termowizja/nasadki-termowizyjne" 590 title="NASADKI TERMOWIZYJNE" id="headercategory67" class="spanhover"> 591 <span>NASADKI TERMOWIZYJNE</span> 592 <img src="/libraries/images/1px.gif" alt="" class="px1" /> 593 </a> 594 </span> 595 596 </li> 597 <li class="" id="hcategory_60"> 598 <span class="h3"> 599 <a href="/kategoria/termowizja/lornetki-termowizyjne" 600 title="LORNETKI TERMOWIZYJNE" id="headercategory60" class="spanhover"> 601 <span>LORNETKI TERMOWIZYJNE</span> 602 <img src="/libraries/images/1px.gif" alt="" class="px1" /> 603 </a> 604 </span> 605 606 </li> 607 <li class="" id="hcategory_69"> 608 <span class="h3"> 609 <a href="/kategoria/termowizja/noktowizja-i-termowizja-uzywana" 610 title="TERMOWIZJA UŻYWANA" id="headercategory69" class="spanhover"> 611 <span>TERMOWIZJA UŻYWANA</span> 612 <img src="/libraries/images/1px.gif" alt="" class="px1" /> 613 </a> 614 </span> 615 616 </li> 617 </ul> 618 </div> 619 <div class="menu__category-images"> 620 <div class="menu__category-images-img"> 621 622 </div> 623 624 </div> 625 626 </div> </li> 627 <li class="parent" id="hcategory_94">
628 <span class="h3"> 629 <a href="/kategoria/noktowizja" id="headlink6" class="spanhover mainlevel"> 630 <span>NOKTOWIZJA</span> 631 <img src="/libraries/images/1px.gif" alt="" class="px1"> 632 </a> 633 </span> 634 <div class="megamenu-wrapper"> <div class="submenu level1"> 635 <ul class="level1"> 636 <li class="" id="hcategory_100"> 637 <span class="h3"> 638 <a href="/kategoria/noktowizja/celowniki-i-lunety" 639 title="CELOWNIKI I LUNETY NOKTOWIZYJNE" id="headercategory100" class="spanhover"> 640 <span>CELOWNIKI I LUNETY NOKTOWIZYJNE</span> 641 <img src="/libraries/images/1px.gif" alt="" class="px1" /> 642 </a> 643 </span> 644 645 </li> 646 <li class="" id="hcategory_95"> 647 <span class="h3"> 648 <a href="/pl/c/MONOKULARY-NOKTOWIZYJNE/95" 649 title="MONOKULARY NOKTOWIZYJNE" id="headercategory95" class="spanhover"> 650 <span>MONOKULARY NOKTOWIZYJNE</span> 651 <img src="/libraries/images/1px.gif" alt="" class="px1" /> 652 </a> 653 </span> 654 655 </li> 656 <li class="" id="hcategory_101"> 657 <span class="h3"> 658 <a href="/kategoria/noktowizja/nasadki-noktowizyjne" 659 title="NASADKI NOKTOWIZYJNE" id="headercategory101" class="spanhover"> 660 <span>NASADKI NOKTOWIZYJNE</span> 661 <img src="/libraries/images/1px.gif" alt="" class="px1" /> 662 </a> 663 </span> 664 665 </li> 666 <li class="" id="hcategory_102"> 667 <span class="h3"> 668 <a href="/pl/c/LORNETKI-NOKTOWIZYJNE/102" 669 title="LORNETKI NOKTOWIZYJNE" id="headercategory102" class="spanhover"> 670 <span>LORNETKI NOKTOWIZYJNE</span> 671 <img src="/libraries/images/1px.gif" alt="" class="px1" /> 672 </a> 673 </span> 674 675 </li> 676 <li class="" id="hcategory_105"> 677 <span class="h3"> 678 <a href="/pl/c/ILUMINATORY/105" 679 title="ILUMINATORY" id="headercategory105" class="spanhover"> 680 <span>ILUMINATORY</span> 681 <img src="/libraries/images/1px.gif" alt="" class="px1" /> 682 </a> 683 </span> 684 685 </li> 686 <li class="" id="hcategory_103"> 687 <span class="h3"> 688 <a href="/kategoria/noktowizja/noktowizja-uzywana" 689 title="NOKTOWIZJA UŻYWANA" id="headercategory103" class="spanhover">
690 <span>NOKTOWIZJA UÅ»YWANA</span> 691 <img src="/libraries/images/1px.gif" alt="" class="px1" /> 692 </a> 693 </span> 694 695 </li> 696 </ul> 697 </div> 698 <div class="menu__category-images"> 699 <div class="menu__category-images-img"> 700 701 </div> 702 703 </div> 704 705 </div> </li> 706 <li class="parent" id="hcategory_76"> 707 <span class="h3"> 708 <a href="/kategoria/optyka" id="headlink8" class="spanhover mainlevel"> 709 <span>OPTYKA</span> 710 <img src="/libraries/images/1px.gif" alt="" class="px1"> 711 </a> 712 </span> 713 <div class="megamenu-wrapper"> <div class="submenu level1"> 714 <ul class="level1"> 715 <li class="" id="hcategory_140"> 716 <span class="h3"> 717 <a href="/pl/c/MONOKULARY/140" 718 title="MONOKULARY" id="headercategory140" class="spanhover"> 719 <span>MONOKULARY</span> 720 <img src="/libraries/images/1px.gif" alt="" class="px1" /> 721 </a> 722 </span> 723 724 </li> 725 <li class="" id="hcategory_143"> 726 <span class="h3"> 727 <a href="/pl/c/CELOWNIKI-PRYZMATYCZNE/143" 728 title="CELOWNIKI PRYZMATYCZNE" id="headercategory143" class="spanhover"> 729 <span>CELOWNIKI PRYZMATYCZNE</span> 730 <img src="/libraries/images/1px.gif" alt="" class="px1" /> 731 </a> 732 </span> 733 734 </li> 735 <li class="" id="hcategory_144"> 736 <span class="h3"> 737 <a href="/pl/c/POWIEKSZALNIKI/144" 738 title="POWIÄKSZALNIKI" id="headercategory144" class="spanhover"> 739 <span>POWIÄKSZALNIKI</span> 740 <img src="/libraries/images/1px.gif" alt="" class="px1" /> 741 </a> 742 </span> 743 744 </li> 745 <li class="" id="hcategory_61"> 746 <span class="h3"> 747 <a href="/kategoria/optyka/lunety-celownicze" 748 title="LUNETY CELOWNICZE" id="headercategory61" class="spanhover"> 749 <span>LUNETY CELOWNICZE</span> 750 <img src="/libraries/images/1px.gif" alt="" class="px1" /> 751 </a> 752 </span> 753 754 </li> 755 <li class="" id="hcategory_122"> 756 <span class="h3"> 757 <a href="/kategoria/optyka/lunety-obserwacyjne" 758 title="LUNETY OBSERWACYJNE" id="headercategory122" class="spanhover">
759 <span>LUNETY OBSERWACYJNE</span> 760 <img src="/libraries/images/1px.gif" alt="" class="px1" /> 761 </a> 762 </span> 763 764 </li> 765 <li class="" id="hcategory_58"> 766 <span class="h3"> 767 <a href="/kategoria/optyka/lornetki" 768 title="LORNETKI" id="headercategory58" class="spanhover"> 769 <span>LORNETKI</span> 770 <img src="/libraries/images/1px.gif" alt="" class="px1" /> 771 </a> 772 </span> 773 774 </li> 775 <li class="" id="hcategory_47"> 776 <span class="h3"> 777 <a href="/kategoria/optyka/kolimatory" 778 title="KOLIMATORY" id="headercategory47" class="spanhover"> 779 <span>KOLIMATORY</span> 780 <img src="/libraries/images/1px.gif" alt="" class="px1" /> 781 </a> 782 </span> 783 784 </li> 785 <li class="" id="hcategory_107"> 786 <span class="h3"> 787 <a href="/kategoria/optyka/dalmierze" 788 title="DALMIERZE" id="headercategory107" class="spanhover"> 789 <span>DALMIERZE</span> 790 <img src="/libraries/images/1px.gif" alt="" class="px1" /> 791 </a> 792 </span> 793 794 </li> 795 <li class="" id="hcategory_77"> 796 <span class="h3"> 797 <a href="/kategoria/optyka/optyka-uzywana" 798 title="OPTYKA UŻYWANA" id="headercategory77" class="spanhover"> 799 <span>OPTYKA UŻYWANA</span> 800 <img src="/libraries/images/1px.gif" alt="" class="px1" /> 801 </a> 802 </span> 803 804 </li> 805 <li class="" id="hcategory_17"> 806 <span class="h3"> 807 <a href="/kategoria/optyka/akcesoria-optyka-2" 808 title="AKCESORIA" id="headercategory17" class="spanhover"> 809 <span>AKCESORIA</span> 810 <img src="/libraries/images/1px.gif" alt="" class="px1" /> 811 </a> 812 </span> 813 814 </li> 815 </ul> 816 </div> 817 <div class="menu__category-images"> 818 <div class="menu__category-images-img"> 819 820 </div> 821 822 </div> 823 824 </div> </li> 825 <li class="parent" id="hcategory_18"> 826 <span class="h3"> 827 <a href="/kategoria/akcesoria" id="headlink10" class="spanhover mainlevel">
828 <span>AKCESORIA</span> 829 <img src="/libraries/images/1px.gif" alt="" class="px1"> 830 </a> 831 </span> 832 <div class="megamenu-wrapper"> <div class="submenu level1"> 833 <ul class="level1"> 834 <li class="" id="hcategory_147"> 835 <span class="h3"> 836 <a href="/pl/c/STATYWY/147" 837 title="STATYWY" id="headercategory147" class="spanhover"> 838 <span>STATYWY</span> 839 <img src="/libraries/images/1px.gif" alt="" class="px1" /> 840 </a> 841 </span> 842 843 </li> 844 <li class="" id="hcategory_148"> 845 <span class="h3"> 846 <a href="/pl/c/SZKLA-POWIEKSZAJACE/148" 847 title="SZKÅA POWIÄKSZAJÄCE" id="headercategory148" class="spanhover"> 848 <span>SZKÅA POWIÄKSZAJÄCE</span> 849 <img src="/libraries/images/1px.gif" alt="" class="px1" /> 850 </a> 851 </span> 852 853 </li> 854 <li class="" id="hcategory_149"> 855 <span class="h3"> 856 <a href="/pl/c/ODZIEZ/149" 857 title="ODZIEÅ»" id="headercategory149" class="spanhover"> 858 <span>ODZIEÅ»</span> 859 <img src="/libraries/images/1px.gif" alt="" class="px1" /> 860 </a> 861 </span> 862 863 </li> 864 <li class="" id="hcategory_139"> 865 <span class="h3"> 866 <a href="/pl/c/AKUMULATORY-I-LADOWARKI/139" 867 title="AKUMULATORY I ÅADOWARKI" id="headercategory139" class="spanhover"> 868 <span>AKUMULATORY I ÅADOWARKI</span> 869 <img src="/libraries/images/1px.gif" alt="" class="px1" /> 870 </a> 871 </span> 872 873 </li> 874 <li class="" id="hcategory_124"> 875 <span class="h3"> 876 <a href="/kategoria/akcesoria/plecaki-mysliwskie" 877 title="PLECAKI" id="headercategory124" class="spanhover"> 878 <span>PLECAKI</span> 879 <img src="/libraries/images/1px.gif" alt="" class="px1" /> 880 </a> 881 </span> 882 883 </li> 884 <li class="" id="hcategory_138"> 885 <span class="h3"> 886 <a href="/pl/c/ADAPTERY/138" 887 title="ADAPTERY" id="headercategory138" class="spanhover"> 888 <span>ADAPTERY</span> 889 <img src="/libraries/images/1px.gif" alt="" class="px1" /> 890 </a> 891 </span> 892 893 </li> 894 <li class="" id="hcategory_37">
895 <span class="h3"> 896 <a href="/kategoria/akcesoria/dwojnog-i-pastoraly" 897 title="DWÃJNÃG I PASTORAÅY" id="headercategory37" class="spanhover"> 898 <span>DWÃJNÃG I PASTORAÅY</span> 899 <img src="/libraries/images/1px.gif" alt="" class="px1" /> 900 </a> 901 </span> 902 903 </li> 904 <li class="" id="hcategory_38"> 905 <span class="h3"> 906 <a href="/kategoria/akcesoria/futeraly-na-bron" 907 title="FUTERAÅY / WALIZKI NA BROÅ" id="headercategory38" class="spanhover"> 908 <span>FUTERAÅY / WALIZKI NA BROÅ</span> 909 <img src="/libraries/images/1px.gif" alt="" class="px1" /> 910 </a> 911 </span> 912 913 </li> 914 <li class="" id="hcategory_46"> 915 <span class="h3"> 916 <a href="/kategoria/akcesoria/kolby" 917 title="KOLBY" id="headercategory46" class="spanhover"> 918 <span>KOLBY</span> 919 <img src="/libraries/images/1px.gif" alt="" class="px1" /> 920 </a> 921 </span> 922 923 </li> 924 <li class="" id="hcategory_70"> 925 <span class="h3"> 926 <a href="/kategoria/akcesoria/noze" 927 title="NOÅ»E MYÅLIWSKIE" id="headercategory70" class="spanhover"> 928 <span>NOÅ»E MYÅLIWSKIE</span> 929 <img src="/libraries/images/1px.gif" alt="" class="px1" /> 930 </a> 931 </span> 932 933 </li> 934 <li class="" id="hcategory_72"> 935 <span class="h3"> 936 <a href="/kategoria/akcesoria/ochronniki-slu
936chu" 937 title="OCHRONNIKI SÅUCHU" id="headercategory72" class="spanhover"> 938 <span>OCHRONNIKI SÅUCHU</span> 939 <img src="/libraries/images/1px.gif" alt="" class="px1" /> 940 </a> 941 </span> 942 943 </li> 944 <li class="" id="hcategory_142"> 945 <span class="h3"> 946 <a href="/pl/c/TERMOSY-I-NACZYNIA-TURYSTYCZNE/142" 947 title="TERMOSY I NACZYNIA TURYSTYCZNE" id="headercategory142" class="spanhover"> 948 <span>TERMOSY I NACZYNIA TURYSTYCZNE</span> 949 <img src="/libraries/images/1px.gif" alt="" class="px1" /> 950 </a> 951 </span> 952 953 </li> 954 <li class="" id="hcategory_40"> 955 <span class="h3"> 956 <a href="/kategoria/akcesoria/inne" 957 title="INNE" id="headercategory40" class="spanhover"> 958 <span>INNE</span> 959 <img src="/libraries/images/1px.gif" alt="" class="px1" /> 960 </a> 961 </span> 962 963 </li> 964 </ul> 965 </div> 966 <div class="menu__category-images"> 967 <div class="menu__category-images-img"> 968 969 </div> 970 971 </div> 972 973 </div> </li> 974 <li class="parent" id="hcategory_109"> 975 <span class="h3"> 976 <a href="/kategoria/montaze-i-tlumiki" id="headlink11" class="spanhover mainlevel"> 977 <span>MONTAÅ»E I TÅUMIKI</span> 978 <img src="/libraries/images/1px.gif" alt="" class="px1"> 979 </a> 980 </span> 981 <div class="megamenu-wrapper"> <div class="submenu level1"> 982 <ul class="level1"> 983 <li class="" id="hcategory_111"> 984 <span class="h3"> 985 <a href="/kategoria/montaze-i-tlumiki/tlumiki" 986 title="TÅUMIKI" id="headercategory111" class="spanhover"> 987 <span>TÅUMIKI</span> 988 <img src="/libraries/images/1px.gif" alt="" class="px1" /> 989 </a> 990 </span> 991 992 </li> 993 <li class="" id="hcategory_112"> 994 <span class="h3"> 995 <a href="/kategoria/montaze-i-tlumiki/montaze" 996 title="MONTAÅ»E" id="headercategory112" class="spanhover"> 997 <span>MONTAÅ»E</span> 998 <img src="/libraries/images/1px.gif" alt="" class="px1" /> 999 </a> 1000 </span> 1001 1002 </li> 1003 <li class="" id="hcategory_117">
1004 <span class="h3"> 1005 <a href="/pl/c/SZYNY-WEAVER-PICATINNY/117" 1006 title="SZYNY WEAVER / PICATINNY" id="headercategory117" class="spanhover"> 1007 <span>SZYNY WEAVER / PICATINNY</span> 1008 <img src="/libraries/images/1px.gif" alt="" class="px1" /> 1009 </a> 1010 </span> 1011 1012 </li> 1013 </ul> 1014 </div> 1015 <div class="menu__category-images"> 1016 <div class="menu__category-images-img"> 1017 1018 </div> 1019 1020 </div> 1021 1022 </div> </li> 1023 <li id="hcategory_123"> 1024 <span class="h3"> 1025 <a href="/kategoria/fotopulapki" id="headlink16" class="spanhover mainlevel"> 1026 <span>FOTOPUÅAPKI</span> 1027 <img src="/libraries/images/1px.gif" alt="" class="px1"> 1028 </a> 1029 </span> 1030 </li> 1031 <li> 1032 <span class="h3"> 1033 <a href="/rusznikarnia" id="headlink17" class="spanhover mainlevel"> 1034 <span>RUSZNIKARNIA</span> 1035 <img src="/libraries/images/1px.gif" alt="" class="px1"> 1036 </a> 1037 </span> 1038 </li> 1039 <li id="hcategory_110"> 1040 <span class="h3"> 1041 <a href="/kategoria/uzywane" id="headlink12" class="spanhover mainlevel"> 1042 <span>UÅ»YWANE</span> 1043 <img src="/libraries/images/1px.gif" alt="" class="px1"> 1044 </a> 1045 </span> 1046 </li> 1047 <li> 1048 <span class="h3"> 1049 <a href="/pl/new" id="headlink13" class="spanhover mainlevel"> 1050 <span>NowoÅci</span> 1051 <img src="/libraries/images/1px.gif" alt="" class="px1"> 1052 </a> 1053 </span> 1054 </li> 1055 <li> 1056 <span class="h3"> 1057 <a href="/pl/promotions" id="headlink3" class="spanhover mainlevel"> 1058 <span>Promocje</span> 1059 <img src="/libraries/images/1px.gif" alt="" class="px1"> 1060 </a> 1061 </span> 1062 </li> 1063 <div class="contact menu-desktop-only"> 1064 <span class="name"> 1065 <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20" fill="none"> 1066 <path d="M19.4219 16.4404V10.4404C19.4219 5.46987 15.3924 1.44043 10.4219 1.44043C5.45131 1.44043 1.42188 5.46987 1.42188 10.4404V16.4404M3.92188 19.4404C2.54116 19.4404 1.42188 18.3211 1.42188 16.9404V14.9404C1.42188 13.5597 2.54116 12.4404 3.92188 12.4404C5.30259 12.4404 6.42188 13.5597 6.42188 14.9404V16.9404C6.42188 18.3211 5.30259 19.4404 3.92188 19.4404ZM16.9219 19.4404C15.5412 19.4404 14.4219 18.3211 14.4219 16.9404V14.9404C14.4219 13.5597 15.5412 12.4404 16.9219 12.4404C18.3026 12.4404 19.4219 13.5597 19.4219 14.9404V16.9404C19.4219 18.3211 18.3026 19.4404 16.9219 19.4404Z" stroke="black" stroke-linecap="round" stroke-linejoin="round"/> 1067 </svg> 1068 Kontakt 1069 <img src="/userdata/public/assets/svg/chevron-down.svg" alt="" width="20" height="20" /> 1070 </span> 1071 <div class="box resetcss box_custom" id="box_custom33"> 1072 1073 <!-- TELEFONY --> 1074<div class="section" style="background: #fafafb; border-left: 3px solid #c33; border-radius: 8px; padding: 10px 12px; box-shadow: 0 1px 6px rgba(0,0,0,0.05); margin: 14px 0;"> 1075<div class="header" style="display: flex; align-items: center; gap: 8px; font-weight: bold; font-size: 16px; letter-spacing: 0.1px;"><span style="font-size: 17px;">ð</span>Telefony kontaktowe:</div> 1076<div class="inner" style="margin-top: 6px; font-size: 14.5px; line-height: 1.4;"> 1077<div class="item" style="margin: 6px 0;"> 1078<p style="margin: 0 0 3px 0; font-weight: 600;">BroÅ myÅliwska, termowizja, optyka:</p> 1079<p style="margin: 0;"><span style="opacity: .5;">, </span> <a style="color: #c00; text-decoration: none; background: rgba(204,0,0,.08); padding: 1px 6px; border-radius: 999px; font-weight: bold;" href="tel:+48784695388">+48 784 695 388</a></p> 1080</div> 1081<div class="item" style="margin: 6px 0;"> 1082<p style="margin: 0 0 3px 0; font-weight: 600;">Pistolety, AR, broÅ sportowa:</p> 1083<p style="margin: 0;"><a style="color: #c00; text-decoration: none; background: rgba(204,0,0,.08); padding: 1px 6px; border-radius: 999px; font-weight: bold;" href="tel:+48666088198">
1083+48 666 088 198</a> <span style="opacity: .5;">, </span> <a style="color: #c00; text-decoration: none; background: rgba(204,0,0,.08); padding: 1px 6px; border-radius: 999px; font-weight: bold;" href="tel:+48784695388">+48 784 695 388</a></p> 1084</div> 1085<div class="item" style="margin: 6px 0;"> 1086<p style="margin: 0 0 3px 0; font-weight: 600;">Amunicja i akcesoria myÅliwskie:</p> 1087<p style="margin: 0;"><a style="color: #c00; text-decoration: none; background: rgba(204,0,0,.08); padding: 1px 6px; border-radius: 999px; font-weight: bold;" href="tel:+48604224149">+48 604 224 149</a> <span style="opacity: .5;">, </span> <a style="color: #c00; text-decoration: none; background: rgba(204,0,0,.08); padding: 1px 6px; border-radius: 999px; font-weight: bold;" href="tel:+48784695388">+48 784 695 388</a></p> 1088</div> 1089<div class="item" style="margin: 6px 0;"> 1090<p style="margin: 0 0 3px 0; font-weight: 600;">Zamówienia (sklep internetowy):</p> 1091<p style="margin: 0;"><a style="color: #c00; text-decoration: none; background: rgba(204,0,0,.08); padding: 1px 6px; border-radius: 999px; font-weight: bold;" href="tel:+48666088295">+48 666 088 295</a></p> 1092</div> 1093</div> 1094</div> 1095<!-- MAILE --> 1096<div class="section" style="background: #f7f8fb; border-left: 3px solid #667; border-radius: 8px; padding: 10px 12px; box-shadow: 0 1px 6px rgba(0,0,0,0.04); margin: 14px 0;"> 1097<div class="header" style="display: flex; align-items: center; gap: 8px; font-weight: bold; font-size: 16px; letter-spacing: 0.1px;"><span style="font-size: 17px;">âï¸</span>Adresy mailowe:</div> 1098<div class="inner" style="margin-top: 6px; font-size: 14.5px; line-height: 1.4;"> 1099<div class="item emails" style="display: flex; flex-wrap: wrap; gap: 8px;"><a style="color: #111; text-decoration: underline;" href="/cdn-cgi/l/email-protection#e0938b8c8590a094978f8a8182928f8ece908c"><span class="__cf_email__" data-cfemail="c3b0a8afa6b383b7b4aca9a2a1b1acadedb3af">[email protected]</span></a> <a style="color: #111; text-decoration: underline;" href="/cdn-cgi/l/email-protection#3e4a4951545f5c4c51507e4a4951545f5c4c5150104e52"><span class="__cf_email__" data-cfemail="80f4f7efeae1e2f2efeec0f4f7efeae1e2f2efeeaef0ec">[email protected]</span></a></div> 1100</div> 1101</div> 1102 1103 1104 1105 </div> 1106 </div> 1107 1108 <li class="menu-footer menu-mobile-only"> 1109 <div class="menu-location"> 1110 <img src="/userdata/public/assets/svg/location.svg" alt="" width="18" height="22" class="location-ico" /> 1111 Sklep i strzelnica: ul. MyÅliwska 6, 05-555 SuchodóÅ, Tarczyn, <a href="tel:784695388">tel.: 784 695 388 </a><a class="map" href="/kontakt-i-dane-firmy"> zobacz na mapie</a> 1112 </div> 1113 <div class="menu-social"> 1114 <a href="https://www.facebook.com/twojabronpl/" target="_blank" rel="noopener" class="facebook sm"> 1115 <svg xmlns="http://www.w3.org/2000/svg" width="29" height="28" viewBox="0 0 29 28" fill="none"> 1116 <circle cx="14.5" cy="14" r="13" stroke="#313131" stroke-width="2"/> 1117 <path d="M16.0337 12.4368H16.2337V12.2368V11.2236V11.0236H16.0337H14.2178V10.571C14.2178 9.89214 14.358 9.45886 14.5894 9.21679C14.8292 8.97691 15.2696 8.83048 15.9702 8.83048H16.1702V8.63048V7.6001V7.4001H15.9702C14.8675 7.4001 14.0213 7.64477 13.4804 8.17908L13.4804 8.17907L13.4788 8.18063C12.9505 8.71417 12.7067 9.52565 12.7067 10.571V11.0236H11.7003H11.5003V11.2236V12.2368V12.4368H11.7003H12.7067V20.6001V20.8001H12.9067H14.0178H14.2178V20.6001V12.4368H16.0337Z" fill="#313131" stroke="#313131" stroke-width="0.4"/> 1118 </svg> 1119 </a> 1120 <a href="https://www.facebook.com/twojabronpl/" target="_blank" rel="noopener" class="instagram sm"> 1121 <svg xmlns="http://www.w3.org/2000/svg" width="29" height="28" viewBox="0 0 29 28" fill="none"> 1122 <rect x="1.5" y="1" width="26" height="26" rx="2" stroke="#313131" stroke-width="2"/> 1123 <circle cx="14.5" cy="14" r="6" stroke="#313131" stroke-width="2"/> 1124 </svg> 1125 </a> 1126 </div> 1127 </li> 1128 </ul> 1129 1130 <ul class="menu-mobile menu-mobile-only"> 1131 <li class="menu-mobile-li small-menu"> 1132 <a> 1133 <svg xmlns="http://www.w3.org/2000/svg" width="17" height="16" viewB
1133ox="0 0 17 16" fill="none"> 1134 <g clip-path="url(#clip0_300_12483)"> 1135 <path d="M15.9375 1.71429H0.6375C0.289 1.71429 0 1.43905 0 1.10714C0 0.775238 0.289 0.5 0.6375 0.5H15.9375C16.286 0.5 16.575 0.775238 16.575 1.10714C16.575 1.43905 16.286 1.71429 15.9375 1.71429Z" fill="#333333"/> 1136 <path d="M15.9375 8.19036H0.6375C0.289 8.19036 0 7.91512 0 7.58322C0 7.25131 0.289 6.97607 0.6375 6.97607H15.9375C16.286 6.97607 16.575 7.25131 16.575 7.58322C16.575 7.91512 16.286 8.19036 15.9375 8.19036Z" fill="#333333"/> 1137 <path d="M15.9375 14.6667H0.6375C0.289 14.6667 0 14.3914 0 14.0595C0 13.7276 0.289 13.4524 0.6375 13.4524H15.9375C16.286 13.4524 16.575 13.7276 16.575 14.0595C16.575 14.3914 16.286 14.6667 15.9375 14.6667Z" fill="#333333"/> 1138 </g> 1139 <defs> 1140 <clipPath id="clip0_300_12483"> 1141 <rect width="17" height="14.5714" fill="white" transform="translate(0 0.5)"/> 1142 </clipPath> 1143 </defs> 1144 </svg> 1145 </a> 1146 </li> 1147 <li class="menu-mobile-li small-search" id="activ-search"> 1148 <a title="Szukaj" class=""> 1149 <svg xmlns="http://www.w3.org/2000/svg" width="24" height="25" viewBox="0 0 24 25" fill="none"> 1150 <path fill-rule="evenodd" clip-rule="evenodd" d="M10.25 4C6.52208 4 3.5 7.02208 3.5 10.75C3.5 14.4779 6.52208 17.5 10.25 17.5C12.1142 17.5 13.8006 16.7453 15.023 15.523C16.2453 14.3006 17 12.6142 17 10.75C17 7.02208 13.9779 4 10.25 4ZM2 10.75C2 6.19365 5.69365 2.5 10.25 2.5C14.8063 2.5 18.5 6.19365 18.5 10.75C18.5 12.7578 17.782 14.5991 16.5899 16.0293L21.2803 20.7197C21.5732 21.0126 21.5732 21.4874 21.2803 21.7803C20.9874 22.0732 20.5126 22.0732 20.2197 21.7803L15.5293 17.0899C14.0991 18.282 12.2578 19 10.25 19C5.69365 19 2 15.3063 2 10.75Z" fill="#313131"/> 1151 </svg> 1152 </a> 1153 </li> 1154 <li class="menu-mobile-li small-logo"> 1155 <a href="/" title="Strona gÅówna"> 1156 <img src="/skins/user/rwd_shoper_25/images/logo.png" alt="twojabron.pl" width="85" height="79"> 1157 </a> 1158 </li> 1159 <li class="menu-mobile-li small-panel"> 1160 <a href="/pl/panel/favourites" title="Ulubione" class=""> 1161 <svg xmlns="http://www.w3.org/2000/svg" width="21" height="20" viewBox="0 0 21 20" fill="none"> 1162 <g clip-path="url(#clip0_300_12567)"> 1163 <mask id="mask0_300_12567" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="0" y="0" width="21" height="20"> 1164 <path d="M0.235352 1.90735e-06H20.2353V20H0.235352V1.90735e-06Z" fill="white"/> 1165 </mask> 1166 <g mask="url(#mask0_300_12567)"> 1167 <path d="M2.7041 3.09644H7.72492V0.586006H2.7041V3.09644Z" stroke="#313131" stroke-width="1.5" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/> 1168 <path d="M12.7458 3.09644H17.7667V0.586006H12.7458V3.09644Z" stroke="#313131" stroke-width="1.5" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/> 1169 </g> 1170 <path d="M12.7457 5.60676H7.72485L7.9531 8.11719H12.5175L12.7457 5.60676Z" stroke="#313131" stroke-width="1.5" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/> 1171 <path d="M3.95923 5.60669H6.46966V3.09626H3.95923V5.60669Z" stroke="#313131" stroke-width="1.5" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/> 1172 <path d="M14.001 5.60669H16.5114V3.09626H14.001V5.60669Z" stroke="#313131" stroke-width="1.5" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/> 1173 <mask id="mask1_300_12567" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="0" y="0" width="21" height="20"> 1174 <path d="M0.235352 1.90735e-06H20.2353V20H0.235352V1.90735e-06Z" fill="white"/> 1175 </mask> 1176 <g mask="url(#mask1_300_12567)"> 1177 <path d="M12.5177 8.11719H13.3735L14.0012 13.138H12.0612L11.4907 19.4141H19.022L17.7667 5.60676H12.7459L12.5177 8.11719Z" stroke="#313131" stroke-width="1.5" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/> 1178 <path d="M7.95327 8.11719H7.09745L6.46979 13.138H8.40972L8.98022 19.4141H1.44897L2.70421 5.60676H7.72503L7.95327 8.11719Z" stroke="#313131" stroke-width="1.5" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/> 1179 </g> 1180 <path d="M13.3734 8.11708H7.09734L6.46973 13.1379H14.001L13.3734 8.11708Z" stroke="#313131" stroke-width="1.5" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/> 1181 </g> 1182 <defs> 1183 <clipPath id="clip0_300_12567"> 1184 <rect width="20" height="20" fill="white" transform="translate(0.235352)"/> 1185 </clipPath> 1186 </defs> 1187 </svg> 1188 </a> 1189 </li> 1190 <li class="menu-mobile-li small-panel" id="activ-panel"> 1191 <a href="/pl/panel" title="Moje konto" class=""> 1192 <svg xmlns="http://www.w3.org/2000/svg" width="25" height="24" viewBox="0 0 25 24" fill="none"> 1193 <path d="M16.4842 5.75C16.4842 7.82107 14.8053 9.5 12.7342 9.5C10.6631 9.5 8.98422 7.82107 8.98422 5.75C8.98422 3.67893 10.6631 2 12.7342 2C14.8053 2 16.4842 3.67893 16.4842 5.75Z" stroke="#313131" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> 1194 <path d="M5.23535 19.8682C5.30566 15.7869 8.63609 12.5 12.7342 12.5C16.8324 12.5 20.1629 15.7871 20.2331 19.8685C17.9503 20.916 15.4106 21.5 12.7345 21.5C10.0582 21.5 7.51831 20.9159 5.23535 19.8682Z" stroke="#313131" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> 1195 </svg> 1196 </a> 1197 </li> 1198 <li class="menu-mobile-li small-cart"> 1199 <a href="/pl/basket" title="Koszyk" class="" data-basket-count="0"> 1200 <svg xmlns="http://www.w3.org/2000/svg" width="25" height="24" viewBox="0 0 25 24" fill="none"> 1201 <path d="M16.4853 10.25V5.75C16.4853 3.67893 14.8064 2 12.7353 2C10.6643 2 8.98535 3.67893 8.98535 5.75V10.25M20.3414 8.25723L21.6045 20.2572C21.6745 20.9215 21.1536 21.5 20.4857 21.5H4.98498C4.31707 21.5 3.79624 20.9215 3.86617 20.2572L5.12932 8.25723C5.18959 7.68466 5.67241 7.25 6.24814 7.25H19.2226C19.7983 7.25 20.2811 7.68466 20.3414 8.25723ZM9.36035 10.25C9.36035 10.4571 9.19245 10.625 8.98535 10.625C8.77824 10.625 8.61035 10.4571 8.61035 10.25C8.61035 10.0429 8.77824 9.875 8.98535 9.875C9.19245 9.875 9.36035 10.0429 9.36035 10.25ZM16.8603 10.25C16.8603 10.4571 16.6925 10.625 16.4853 10.625C16.2782 10.625 16.1103 10.4571 16.1103 10.25C16.1103 10.0429 16.2782 9.875 16.4853 9.875C16.6925 9.875 16.8603 10.0429 16.8603 10.25Z" stroke="#313131" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> 1202 </svg> 1203 </a> 1204 </li> 1205 </ul> 1206 </nav> 1207 </div> 1208 <div class="breadcrumbs large tablet row"> 1209 <div class="innerbreadcrumbs row container"> 1210 <a href="/" title="Strona gÅówna" rel="nofollow" class="breadcrumb-home left none">
1211 <span>JesteÅ w:</span> 1212 </a> 1213 1214 <ul itemscope itemtype="https://schema.org/BreadcrumbList" class="path left inline"> 1215 1216 <li class="bred-1 " itemprop="itemListElement" itemscope itemtype="https://schema.org/ListItem"> 1217 <a href="/" itemprop="item"> <span class="raq">»</span> 1218 <span itemprop="name">Strona gÅówna</span> 1219 </a> 1220 <meta itemprop="position" content="1" /> 1221 </li> 1222 <li class="bred-2 " itemprop="itemListElement" itemscope itemtype="https://schema.org/ListItem"> 1223 <a href="/pl/blog" itemprop="item"> <span class="raq">»</span> 1224 <span itemprop="name">Blog</span> 1225 </a> 1226 <meta itemprop="position" content="2" /> 1227 </li> 1228 <li class="bred-3 last" > 1229 <span class="raq">»</span> 1230 <span>Jak wybraÄ pistolet do noszenia? Poradnik dla poczÄ tkujÄ cych</span> 1231 1232 </li> 1233 </ul> 1234 </div> 1235 </div> 1236 1237 1238 1239 <div class="top row"> 1240 <div class="container slider-ammunution-wrapper"> 1241 1242 <div class="box resetcss box_custom" id="box_custom36"> 1243 1244 1245 1246 1247 1248 </div> 1249 </div> 1250 <div class="container"> 1251 </div> 1252 1253 </div>
vendor: 117 bytes, lines 1253-1254
1253 1254 <script data-cfasync="false" src="/cdn-cgi/scripts/5c5dd728/cloudflare-static/email-decode.min.js"></script>
1254<script>hidePreloader()</script>
1254 <div class="main row"> 1255 <div class="innermain container"> 1256 <div class="s-row"> 1257 1258 <div class="centercol s-grid-12"> 1259 1260 1261 <article class="box" id="box_article"> 1262 1263 1264 <div class="row article-info none"> 1265 1266 </div> 1267 <div class="date"> 1268 2 października 2026 1269 </div> 1270 <div class="row article-header"> 1271 <span class="article-name">Jak wybraÄ pistolet do noszenia? Poradnik dla poczÄ tkujÄ cych</span> 1272 </div> 1273 <div class="author"> 1274 Kuba z twojabron.pl 1275 </div> 1276 1277 <div class="resetcss row article-short-content"> 1278 <p style="text-align: justify;">Pistolet do noszenia rzÄ dzi siÄ zupeÅnie innymi prawami niż ten, z którego strzelasz na strzelnicy â i to dosÅownie, bo zaczyna siÄ od przepisów. Zanim w ogóle zastanowisz siÄ nad modelem, musisz wiedzieÄ, czy cel Twojego pozwolenia w ogóle uprawnia do noszenia, bo ustawa traktuje tÄ kwestiÄ bardzo precyzyjnie. Dopiero potem przychodzi czas na sprzÄt, a tu wszystkie kryteria stajÄ na gÅowie: masa i dÅugoÅÄ lufy z zalet zamieniajÄ siÄ w wady, a decyduje coÅ, o czym maÅo kto myÅli przy zakupie â wysokoÅÄ chwytu i jakoÅÄ kabury. W tym poradniku tÅumaczymy przepisy dotyczÄ ce noszenia broni, pokazujemy różnice miÄdzy kompaktem a subkompaktem i podpowiadamy konkretne modele, które sprawdzÄ siÄ na start.</p> 1279 </div> 1280 <img class="article-image" src="/userdata/public/news/images/134-1790879622.jpeg" alt="Jak wybraÄ pistolet do noszenia? Poradnik dla poczÄ tkujÄ cych"> 1281 1282 1283 <div class="resetcss row article-content"> 1284 1285 1286 <h2>Jaki pistolet do noszenia wybraÄ? Przepisy, kryteria i polecane modele</h2> 1287<nav class="spis-tresci" style="background: #f5f5f5; padding: 16px 20px; border-left: 4px solid #222; margin-bottom: 32px;"><strong>Spis treÅci</strong> 1288<ol style="margin: 8px 0 0 20px; padding: 0;"> 1289<li><a href="#definicja">Co w Åwietle prawa oznacza ânoszenie pistoletu"?</a></li> 1290<li><a href="#kto-moze">Kto w Polsce może legalnie nosiÄ pistolet?</a></li> 1291<li><a href="#jak-nosic">Jak legalnie nosiÄ pistolet? Kabura i zasady</a></li> 1292<li><a href="#roznice">Pistolet do noszenia a pistolet na strzelnicÄ â co je różni?</a></li> 1293<li><a href="#kryteria">Na co zwróciÄ uwagÄ przy wyborze pistoletu do noszenia?</a></li> 1294<li><a href="#modele">Jakie pistolety sprawdzÄ siÄ do noszenia?</a></li> 1295<li><a href="#tabela">Kompakt vs subkompakt vs stalowy klasyk â porównanie parametrów</a></li> 1296<li><a href="#kaliber">Jaki kaliber wybraÄ do noszenia?</a></li> 1297<li><a href="#trening">Dlaczego trening po zakupie jest obowiÄ zkowy?</a></li> 1298<li><a href="#bledy">Jakich bÅÄdów uniknÄ Ä przy wyborze pistoletu do noszenia?</a></li> 1299<li><a href="#faq">FAQ â najczÄÅciej zadawane pytania</a></li> 1300<li><a href="#podsumowanie">Podsumowanie</a></li> 1301<li><a href="#polecamy">Przy okazji polecamy</a></li> 1302</ol> 1303</nav> 1304<p style="text-align: justify;"><span style="font-weight: 400;">Pistolet do noszenia to zupeÅnie inna kategoria wyboru niż pistolet na strzelnicÄ â i poniżej przechodzimy przez niÄ warstwa po warstwie: najpierw prawo, bo od niego zależy, czy w ogóle wolno Ci nosiÄ, potem kryteria wyboru, a na koÅcu konkretne modele, które sprawdzajÄ siÄ w codziennym, skrytym noszeniu.</span></p> 1305<h2 id="definicja">Co w Åwietle prawa oznacza ânoszenie pistoletu"?</h2> 1306<p style="text-align: justify;"><span style="font-weight: 400;">To pytanie brzmi jak formalnoÅÄ, ale od odpowiedzi zależy dosÅownie wszystko â ÅÄ cznie z tym, czy zachowasz pozwolenie. Ustawa o broni i amunicji definiuje sprawÄ bardzo precyzyjnie w art. 10 ust. 9: <strong>noszeniem broni jest każdy sposób przemieszczania zaÅadowanej broni przez osobÄ jÄ posiadajÄ cÄ </strong>.</span></p> 1307<p style="text-align: justify;"><span style="font-weight: 400;">
1307Kluczowe sÅowo to âzaÅadowanej". JeÅli jedziesz na strzelnicÄ z rozÅadowanym pistoletem w futerale i osobno spakowanÄ amunicjÄ â to nie jest noszenie, tylko <strong>przemieszczanie</strong> (w Årodowisku strzeleckim mówi siÄ też âprzenoszenie"). Może to robiÄ wÅaÅciwie każdy posiadacz pozwolenia. Ustawa nie definiuje wprost, czym jest âbroÅ zaÅadowana", ale w przyjÄtej interpretacji noszenie zaczyna siÄ w momencie, gdy w broni jest amunicja â choÄby w podpiÄtym magazynku, przy pustej komorze nabojowej.</span></p> 1308<p style="text-align: justify;"><span style="font-weight: 400;">Ta granica bywa źródÅem naprawdÄ poważnych kÅopotów. Kolekcjoner, który podpiÄ Å magazynek âna chwilÄ" w drodze do samochodu, formalnie nosi broÅ â a jemu akurat nie wolno.</span></p> 1309<h2 id="kto-moze">Kto w Polsce może legalnie nosiÄ pistolet?</h2> 1310<p style="text-align: justify;"><span style="font-weight: 400;">Prawo do noszenia zależy od <strong>celu, w jakim wydano pozwolenie</strong> â a nie od tego, jaki pistolet kupiÅeÅ. Ten sam egzemplarz w rÄkach dwóch osób może byÄ noszony legalnie albo nielegalnie.</span></p> 1311<ul> 1312<li>â <strong>Pozwolenie do ochrony osobistej oraz do ochrony bezpieczeÅstwa innych osób i mienia</strong> â najszersze uprawnienia. BroÅ można nosiÄ także w Årodkach transportu publicznego: zaÅadowanÄ , ale bez wprowadzonego naboju do komory nabojowej i w stanie zabezpieczonym (§ 2 ust. 2 rozporzÄ dzenia z 10 kwietnia 2000 r. w sprawie zasad przewożenia broni i amunicji Årodkami transportu publicznego).</li> 1313<li>â <strong>Pozwolenie do celów sportowych, szkoleniowych i Åowieckich</strong> â noszenie jest dozwolone, ale w Årodkach transportu publicznego broÅ przewozi siÄ już wyÅÄ cznie rozÅadowanÄ , bez amunicji w komorze i w magazynkach.</li> 1314<li>â <strong>Pozwolenie do celów kolekcjonerskich i pamiÄ tkowych</strong> â art. 10 ust. 8 ustawy wprost zakazuje noszenia takiej broni bez zgody wÅaÅciwego organu Policji.</li> 1315</ul> 1316<p style="text-align: justify;"><span style="font-weight: 400;">Od zasady dotyczÄ cej transportu publicznego jest jeden wyjÄ tek bezwzglÄdny, o którym warto pamiÄtaÄ przed podrÃ³Å¼Ä : zgodnie z art. 35 ust. 2 ustawy <strong>przewożenie broni i amunicji w kabinach pasażerskich statków powietrznych jest zakazane</strong> dla wszystkich poza osobami specjalnie do tego upoważnionymi. BroÅ leci wyÅÄ cznie w bagażu rejestrowanym, na zasadach okreÅlonych przez przewoźnika.</span></p> 1317<p style="text-align: justify;"><span style="font-weight: 400;">Jest jeszcze jeden zapis, o którym warto wiedzieÄ: zgodnie z art. 10 ust. 7 <strong>organ Policji może w samym pozwoleniu ograniczyÄ lub caÅkowicie wykluczyÄ możliwoÅÄ noszenia broni</strong>, co odnotowuje siÄ w legitymacji posiadacza broni. Zanim wiÄc zaplanujesz cokolwiek, sprawdź, co masz wpisane w swojej legitymacji.</span></p> 1318<h3>Pozwolenie do ochrony osobistej â jak wyglÄ da w praktyce?</h3> 1319<p style="text-align: justify;"><span style="font-weight: 400;">Warto powiedzieÄ to wprost: to najtrudniejsza do zdobycia kategoria pozwolenia dla cywila. Ustawa wymaga wykazania ważnej przyczyny, którÄ w tym przypadku jest <strong>staÅe, realne i ponadprzeciÄtne zagrożenie życia, zdrowia lub mienia</strong>. Ocena należy do organu Policji i bywa uznaniowa â sama chÄÄ posiadania broni âna wszelki wypadek" nie wystarczy.</span></p> 1320<p style="text-align: justify;"><span style="font-weight: 400;">Statystyki pokazujÄ jednak, jak bardzo zmieniÅa to jedna nowelizacja. WedÅug danych Komendy GÅównej Policji w 2022 roku wydano w tej kategorii zaledwie <strong>154 decyzje</strong>. Po wejÅciu w życie w lipcu 2023 r. ustawy o zmianie niektórych ustaw w celu likwidowania zbÄdnych barier administracyjnych i prawnych liczba ta wzrosÅa do <strong>6 242 w 2023 roku</strong> i <strong>9 589 w 2024 roku</strong>. Rok 2025 przyniósÅ już jednak wyraźny spadek â <strong>7 254 decyzje</strong>
1320, co oznacza, że szczyt mamy prawdopodobnie za sobÄ .</span></p> 1321<p style="text-align: justify;"><span style="font-weight: 400;">ŹródÅem tego wzrostu byÅ dodany wówczas art. 10 ust. 3a, który za ważnÄ przyczynÄ uznaÅ <strong>chÄÄ wzmocnienia potencjaÅu obronnego RP deklarowanÄ przez funkcjonariuszy sÅużb mundurowych i żoÅnierzy zawodowych</strong> posiadajÄ cych przydzielonÄ broÅ sÅużbowÄ . Dla pozostaÅych cywilów wymagania pozostaÅy dokÅadnie takie same.</span></p> 1322<p style="text-align: justify;"><span style="font-weight: 400;">W praktyce oznacza to, że wiÄkszoÅÄ osób noszÄ cych dziÅ pistolet robi to na podstawie pozwolenia sportowego. Jak je zdobyÄ, opisaliÅmy krok po kroku we wpisie <a href="https://twojabron.pl/pl/blog/Jak-uzyskac-pozwolenie-na-bron-sportowa-Wszystko,co-powinienes-wiedziec/36">o pozwoleniu na broÅ sportowÄ </a>.</span></p> 1323<p style="text-align: justify;"><span style="font-weight: 400;"><img lazy src="data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs%3D" data-src="/userdata/public/assets/BLOG%20-%20TBCH/pexels-dbgalvanis-30871191.jpg" alt="Pistolet do noszenia â kompaktowy pistolet w widoku z boku" width="1300" /><noscript><img src="/userdata/public/assets/BLOG%20-%20TBCH/pexels-dbgalvanis-30871191.jpg" alt="Pistolet do noszenia â kompaktowy pistolet w widoku z boku" width="1300" /></noscript></span></p> 1324<h2 id="jak-nosic">Jak legalnie nosiÄ pistolet? Kabura i zasady</h2> 1325<p style="text-align: justify;"><span style="font-weight: 400;">Sposób noszenia reguluje rozporzÄ dzenie Ministra Spraw WewnÄtrznych z 26 sierpnia 2014 r. w sprawie przechowywania, noszenia oraz ewidencjonowania broni i amunicji. Zasady sÄ krótkie i konkretne:</span></p> 1326<ul> 1327<li><strong>BroÅ palnÄ nosi siÄ w kaburach lub futeraÅach</strong> â nigdy luzem w kieszeni czy za paskiem.</li> 1328<li><strong>
1328BroÅ do ochrony osobistej nosi siÄ w sposób jak najmniej widoczny, w kaburze przylegajÄ cej do ciaÅa.</strong></li> 1329<li><strong>BroÅ do innych celów</strong> â o ile pozwala na to jej wielkoÅÄ i iloÅÄ â nosi siÄ w ten sam sposób.</li> 1330</ul> 1331<p style="text-align: justify;"><span style="font-weight: 400;">Uwaga na czÄsty mit: przepisy <strong>nie nakazujÄ noszenia z pustÄ komorÄ nabojowÄ </strong> przy zwykÅym noszeniu. Wymóg braku naboju w komorze pojawia siÄ dopiero w transporcie publicznym â i dotyczy broni do ochrony osobistej oraz ochrony bezpieczeÅstwa innych osób i mienia, bo pozostaÅe kategorie nie mogÄ tam w ogóle mieÄ broni zaÅadowanej.</span></p> 1332<p style="text-align: justify;"><span style="font-weight: 400;">DochodzÄ do tego zakazy sytuacyjne: z broniÄ nie wchodzi siÄ na imprezy masowe ani na zgromadzenia publiczne. I rzecz absolutnie podstawowa â <strong>noszenie broni w stanie po użyciu alkoholu lub Årodka podobnie dziaÅajÄ cego jest wykroczeniem</strong> z art. 51 ust. 2 pkt 4 ustawy, a organ Policji w takim przypadku obligatoryjnie cofa pozwolenie (art. 18 ust. 1 pkt 4). Co wiÄcej, przepis obejmuje także przemieszczanie siÄ w takim stanie z broniÄ rozÅadowanÄ . Tu nie ma żadnego marginesu.</span></p> 1333<p style="text-align: justify;"><span style="font-weight: 400;"><img lazy src="data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs%3D" data-src="/userdata/public/assets/BLOG/pexels-martijn-stoof-2150654344-36773091.jpg" alt="Pas sÅużbowy funkcjonariusza z pistoletem w kaburze, paÅkÄ teleskopowÄ i radiotelefonem" width="1300" /><noscript><img src="/userdata/public/assets/BLOG/pexels-martijn-stoof-2150654344-36773091.jpg" alt="Pas sÅużbowy funkcjonariusza z pistoletem w kaburze, paÅkÄ teleskopowÄ i radiotelefonem" width="1300" /></noscript></span></p> 1334<h2 id="roznice">Pistolet do noszenia a pistolet na strzelnicÄ â co je różni?</h2> 1335<p style="text-align: justify;"><span style="font-weight: 400;">Jeżeli czytaÅeÅ nasz <a href="https://twojabron.pl/pl/blog/Jak-wybrac-pistolet-na-strzelnice-Poradnik-dla-poczatkujacych/70">poradnik o wyborze pistoletu na strzelnicÄ</a>, zauważysz, że kryteria sÄ tu niemal odwrotne. To nie przypadek â to dwa różne narzÄdzia do dwóch różnych zadaÅ.</span></p> 1336<p style="text-align: justify;"><span style="font-weight: 400;">Na strzelnicy zaletÄ jest masa (tÅumi odrzut), dÅuga lufa (dÅuższa linia celownicza, lepsze skupienie) i regulowane przyrzÄ dy. Przy noszeniu każda z tych cech zamienia siÄ w wadÄ: <strong>ciÄżki pistolet obciÄ Å¼a pasek przez caÅy dzieÅ, dÅugi zamek uwiera przy siadaniu, a regulowana szczerbinka zaczepia o ubranie</strong> przy dobyciu.</span></p> 1337<p style="text-align: justify;"><span style="font-weight: 400;">StÄ d prosty wniosek: pistolet do noszenia to zawsze kompromis. Kompromis miÄdzy tym, jak dobrze siÄ z niego strzela, a tym, jak Åatwo go ze sobÄ zabraÄ. CaÅa sztuka wyboru polega na ustawieniu tego kompromisu tam, gdzie pasuje do Twojej sylwetki, stylu ubierania i tego, ile godzin dziennie faktycznie bÄdziesz go nosiÅ.</span></p> 1338<h2 id="kryteria">Na co zwróciÄ uwagÄ przy wyborze pistoletu do noszenia?</h2> 1339<h3>Gabaryty â klasa wielkoÅci ma znaczenie wiÄksze niż marka</h3> 1340<p style="text-align: justify;"><span style="font-weight: 400;">Rynek dzieli pistolety na trzy klasy i to ten podziaÅ, a nie logo na zamku, decyduje o codziennym komforcie:</span></p> 1341<ul> 1342<li><strong>PeÅnowymiarowe (full-size)</strong> â lufa ok. 110â130 mm. Åwietnie siÄ z nich strzela, ale realnie ukryje je tylko luźna kurtka.</li> 1343<li><strong>Kompakty</strong> â lufa ok. 95â105 mm, dÅugoÅÄ ok. 180â190 mm. ZÅoty Årodek i najczÄstszy wybór do codziennego noszenia (EDC â everyday carry).</li> 1344<li><strong>Subkompakty</strong> â lufa poniżej 90 mm, skrócony chwyt. ZnikajÄ pod koszulÄ , ale wymagajÄ wyraźnie lepszej techniki.</li> 1345</ul> 1346<p style="text-align: justify;"><span style="font-weight: 400;">Praktyczna wskazówka: <strong>o możliwoÅci skrytego noszenia decyduje wysokoÅÄ chwytu, nie dÅugoÅÄ lufy.</strong> To rÄkojeÅÄ odstaje od ciaÅa i rysuje siÄ pod ubraniem. Dlatego kompakt z krótszym chwytem bywa Åatwiejszy do ukrycia niż subkompakt z magazynkiem z przedÅużkÄ .</span></p> 1347<h3>Masa i materiaÅ szkieletu</h3> 1348<p style="text-align: justify;"><span style="font-weight: 400;">Tu pojawia siÄ klasyczny konflikt. <strong>Szkielet polimerowy</strong> to 600â750 g i pistolet, o którym po póŠdnia zapominasz. <strong>Szkielet stalowy</strong>
1348 to 850â950 g, czyli wyraźnie odczuwalna masa na pasku â ale też znacznie Åagodniejszy odrzut i szybszy powrót na cel. Aluminium jest kompromisem pomiÄdzy nimi.</span></p> 1349<p style="text-align: justify;"><span style="font-weight: 400;">Wybór zależy od tego, co robisz czÄÅciej: nosisz czy strzelasz. JeÅli pistolet ma byÄ z TobÄ osiem godzin dziennie, każde 200 g robi różnicÄ. JeÅli nosisz sporadycznie, a trenujesz regularnie â stal bÄdzie przyjemniejsza.</span></p> 1350<h3>Spust i bezpieczniki</h3> 1351<p style="text-align: justify;"><span style="font-weight: 400;">Przy noszeniu ten wybór ma wymiar bezpieczeÅstwa, nie tylko komfortu.</span></p> 1352<ul> 1353<li><strong>Striker-fired (iglicowy)</strong> â jeden, powtarzalny opór przy każdym strzale, zwykle bez bezpiecznika zewnÄtrznego (rolÄ tÄ peÅniÄ bezpieczniki automatyczne, np. w spuÅcie). Prosto, przewidywalnie, bez dodatkowych ruchów przy dobyciu.</li> 1354<li><strong>DA/SA z bezpiecznikiem lub zwalniaczem kurka</strong> â dÅugi, ciÄżki pierwszy strzaÅ daje dodatkowy margines bezpieczeÅstwa. Wymaga jednak nauczenia siÄ dwóch różnych spustów i wyrobienia odruchu odbezpieczania.</li> 1355</ul> 1356<p style="text-align: justify;"><span style="font-weight: 400;">Dla wiÄkszoÅci osób noszÄ cych pierwszy pistolet <strong>rozwiÄ zanie iglicowe jest bezpieczniejsze wÅaÅnie dlatego, że nie wymaga dodatkowych czynnoÅci</strong> â w stresie liczba ruchów do wykonania powinna byÄ minimalna. Warunek jest jeden: dobra, sztywna kabura zakrywajÄ ca kabÅÄ k spustu.</span></p> 1357<h3>NiezawodnoÅÄ i pojemnoÅÄ magazynka</h3> 1358<p style="text-align: justify;"><span style="font-weight: 400;">W pistolecie sportowym zaciÄcie to strata punktu. W pistolecie do noszenia â zupeÅnie inna kategoria problemu. Dlatego tu <strong>wybieraj konstrukcje sprawdzone, o dÅugiej historii i dużej bazie użytkowników</strong>, a nie nowinki. PojemnoÅÄ 12â15 naboi w kompakcie to standard; subkompakty schodzÄ do 10, ale zwykle przyjmujÄ dÅuższe magazynki z wiÄkszych modeli.</span></p> 1359<h3>Kabura â kupuj razem z broniÄ , nie âkiedyÅ potem"</h3> 1360<p style="text-align: justify;"><span style="font-weight: 400;">To najczÄÅciej pomijany element caÅej ukÅadanki, a decyduje o powodzeniu bardziej niż sam pistolet. Dobra kabura musi byÄ <strong>sztywna, zakrywaÄ kabÅÄ k spustu, pewnie trzymaÄ broÅ bez pasków i zapiÄÄ oraz umożliwiaÄ jednorÄczne wÅożenie z powrotem</strong>. Tania, miÄkka kabura z materiaÅu to prosta droga do tego, że pistolet zostanie w szafie.</span></p> 1361<p style="text-align: justify;"><span style="font-weight: 400;">Do tego potrzebny jest <strong>solidny, sztywny pas</strong> â bez niego nawet najlepsza kabura bÄdzie siÄ przechylaÄ i uwieraÄ. To wydatek rzÄdu kilkuset zÅotych, który zmienia komfort noszenia nie do poznania.</span></p> 1362<h2 id="modele">Jakie pistolety sprawdzÄ siÄ do noszenia?</h2> 1363<h3>Kompakt polimerowy â najbezpieczniejszy pierwszy wybór</h3> 1364<p style="text-align: justify;"><span style="font-weight: 400;"><strong>Glock 19</strong> to model, który zdefiniowaÅ caÅÄ kategoriÄ. DÅugoÅÄ ok. 185 mm, lufa 102 mm, masa ok. 670 g i 15+1 naboi â proporcje na tyle udane, że od dekad pozostaje punktem odniesienia dla konkurencji. Prosta budowa, spust iglicowy, praktycznie nieograniczony wybór kabur i akcesoriów.</span></p> 1365<p style="text-align: justify;"><span style="font-weight: 400;">Warto wiedzieÄ, co dokÅadnie oznacza oznaczenie <strong>Gen. 6</strong>, na które można siÄ natknÄ Ä w ofertach â u nas znajdziesz je na karcie <a href="/WKLEJ-LINK-GLOCK-19-GEN6-OR">Glocka 19 Gen. 6 OR</a>. Szósta generacja (dostÄpna dla modeli G17, G19, G45 oraz â na rynkach poza USA â G49) jest <strong>fabrycznie przystosowana pod kolimator</strong>: nie ma już osobnej wersji MOS, a w zestawie znajdujÄ siÄ pÅytki montażowe. Standardem jest też pÅaski jÄzyk spustowy, nowa tekstura chwytu RTF6, podciÄty kabÅÄ k i pojedyncza sprÄżyna powrotna zamiast podwójnej. <strong>Magazynki z poprzednich generacji pasujÄ bez zastrzeżeÅ.</strong> Z kaburami bywa różnie: szkielet zostaÅ przeprojektowany (wyższe podciÄcie kabÅÄ ka, inny profil chwytu), wiÄc wiÄkszoÅÄ kabur z Gen. 5 pasuje, ale czÄÅÄ producentów oferuje osobne wersje pod Gen. 6 â przed zakupem sprawdź to u konkretnego producenta. Lufy w Gen. 6 majÄ zmienionÄ geometriÄ i nie sÄ zam
1365ienne z wczeÅniejszymi generacjami.</span></p> 1366<p style="text-align: justify;"><span style="font-weight: 400;">RównorzÄdnÄ alternatywÄ jest <strong>CZ P-10 C</strong>: 187 mm dÅugoÅci (a wiÄc niemal identycznie jak Glock 19), lufa 102 mm, masa 740 g, 15+1, trzy wymienne nakÅadki chwytu i spust chwalony jako jeden z najlepszych w klasie polimerowych konstrukcji iglicowych. Wielu strzelców uważa go za lepiej leÅ¼Ä cy w dÅoni od Glocka â i to jest dokÅadnie ta różnica, której nie rozstrzygniesz bez wziÄcia obu do rÄki.</span></p> 1367<ul> 1368<li>â najlepszy stosunek możliwoÅci strzeleckich do gabarytów</li> 1369<li>â niska masa â realnie da siÄ nosiÄ caÅy dzieÅ</li> 1370<li>â ogromny wybór kabur, magazynków i czÄÅci</li> 1371<li>â trudniejsze do ukrycia pod samÄ koszulkÄ niż subkompakt</li> 1372</ul> 1373<h3>Subkompakt â gdy priorytetem jest dyskrecja</h3> 1374<p style="text-align: justify;"><span style="font-weight: 400;"><strong>Glock 26</strong> to klasyk kategorii i jeden z najpopularniejszych pistoletów do skrytego noszenia na Åwiecie: dÅugoÅÄ ok. 163 mm, lufa 87 mm, masa ok. 615 g, 10+1 naboi. Skrócony chwyt sprawia, że pistolet znika pod ubraniem â i jednoczeÅnie że mieszczÄ siÄ na nim tylko dwa palce. Ma to jednak ogromnÄ zaletÄ praktycznÄ : <strong>przyjmuje magazynki od Glocka 19 i 17</strong>, wiÄc na strzelnicy możesz strzelaÄ z peÅnym chwytem, a nosiÄ z krótkim.</span></p> 1375<p style="text-align: justify;"><span style="font-weight: 400;">Jedno zastrzeżenie dla porzÄ dku: <strong>Glock 26 nie doczekaÅ siÄ na razie wersji Gen. 6</strong> â szósta generacja objÄÅa jak dotÄ d wyÅÄ cznie modele G17, G19, G45 i G49. KupujÄ c subkompakt, kupujesz konstrukcjÄ w Gen. 5, co samo w sobie nie jest wadÄ , bo to sprawdzona i dopracowana platforma.</span></p> 1376<p style="text-align: justify;"><span style="font-weight: 400;">Uczciwe zastrzeżenie: krótsza lufa i mniejsza masa oznaczajÄ wyraźniejszy podrzut i krótszÄ liniÄ celowniczÄ . To <strong>trudniejszy pistolet do dobrego strzelania</strong>, nie Åatwiejszy. JeÅli to Twój pierwszy egzemplarz, lepiej zaczÄ Ä od kompaktu.</span></p> 1377<h3>Stalowy kompakt â dla ceniÄ cych klasykÄ i miÄkki odrzut</h3> 1378<p style="text-align: justify;"><span style="font-weight: 400;"><strong>CZ 75 Compact</strong> to zmniejszona wersja jednej z najsÅynniejszych konstrukcji w historii. DÅugoÅÄ ok. 184 mm, lufa ok. 96 mm, masa ok. 930 g, 14+1 naboi, mechanizm DA/SA z bezpiecznikiem skrzydeÅkowym. Stalowy szkielet daje <strong>najÅagodniejszy odrzut w caÅej stawce</strong> â to najprzyjemniejszy do strzelania kompakt z tej trójki.</span></p> 1379<p style="text-align: justify;"><span style="font-weight: 400;">CenÄ jest masa: o ponad 300 g wiÄcej niż Glock 26, czyli mniej wiÄcej o poÅowÄ. PodobnÄ filozofiÄ reprezentuje <strong>CZ 75 P-01</strong> ze szkieletem aluminiowym, który obniża masÄ przy zachowaniu klasycznej ergonomii CZ. Warto też spojrzeÄ na <strong>CZ P-07</strong> â polimerowy odpowiednik z ukÅadem DA/SA, wyraźnie lżejszy i jeden z taÅszych rozsÄ dnych wyborów w tej klasie.</span></p> 1380<p style="text-align: justify;"><span style="font-weight: 400;">Z nowszych konstrukcji uwagÄ zwraca <strong>CZ Shadow 2 Carry</strong> â aluminiowa, skrócona odmiana sportowego Shadow 2 z lufÄ 102 mm, pojemnoÅciÄ 15+1, zwalniaczem kurka zamiast bezpiecznika skrzydeÅkowego i zamkiem frezowanym bezpoÅrednio pod kolimator, bez pÅytek. Jest wyraźnie lżejszy od stalowego CZ 75 Compact, korzysta z tych samych magazynków co on i P-01, a przy tym zachowuje spust znany z serii Shadow.</span></p> 1381<ul> 1382<li>â najmiÄkszy odrzut i doskonaÅa ergonomia chwytu</li> 1383<li>â bezpiecznik skrzydeÅkowy â możliwoÅÄ noszenia w trybie âcocked and locked"</li> 1384<li>â najwyższa masa w zestawieniu</li> 1385<li>â koniecznoÅÄ opanowania dwóch różnych oporów spustu</li> 1386</ul> 1387<div style="background: #f5f5f5; border-left: 4px solid #222; border-radius: 4px; padding: 18px 22px; margin: 28px 0;"> 1388<p style="text-align: justify; margin: 0;"><span style="font-weight: 400;">ð Zobacz w naszej ofercie: <a style="text-decoration: underline;" href="/WKLEJ-LINK-GLOCK-19-GEN6-OR">Pistolet Glock 19 Gen. 6 OR</a>, <a style="text-decoration: underline;" href="https://twojabron.pl/cz-75-compact">Pistolet CZ 75 Compact</a>, <a style="text-decoration: underline;" href="/WKLEJ-LINK-CZ-SHADOW-2-CARRY">Pistolet CZ Shadow 2 Carry</a>, <a style="text-decoration: underline;" href="https://twojabron.pl/pl/producer/Glock/57">pistolety Glock</a>, <a style="text-decoration: underline;" href="https://twojabron.pl/pl/producer/CZ/36">pistolety CZ</a> oraz peÅnÄ kategoriÄ <a style="text-decoration: underline;" href="https://twojabron.pl/kategoria/bron-nowa/bron-krotka-centralny-zaplon">pistoletów centralnego zapÅonu</a>.</span></p> 1389</div> 1390<h2 id="tabela">Kompakt vs subkompakt vs stalowy klasyk â porównanie parametrów</h2> 1391<div style="overflow-x: auto; -webkit-overflow-scrolling: touch; margin: 25px 0;"> 1392<table style="width: 100%; min-width: 780px; border-collapse: collapse; table-layout: fixed; font-size: 15px; line-height: 1.6;"><colgroup> <col style="width: 20%;" /> <col style="width: 13%;" /> <col style="width: 12%;" /> <col style="width: 13%;" /> <col style="width: 14%;" /> <col style="width: 28%;" /> </colgroup> 1393<thead> 1394<tr style="background: #222; color: #ffffff;"> 1395<th style="padding: 12px 14px; border: 1px solid #ddd; text-align: left;">Model</th>
1396<th style="padding: 12px 14px; border: 1px solid #ddd; text-align: left;">DÅ. caÅkowita</th> 1397<th style="padding: 12px 14px; border: 1px solid #ddd; text-align: left;">DÅ. lufy</th> 1398<th style="padding: 12px 14px; border: 1px solid #ddd; text-align: left;">Masa</th> 1399<th style="padding: 12px 14px; border: 1px solid #ddd; text-align: left;">PojemnoÅÄ</th> 1400<th style="padding: 12px 14px; border: 1px solid #ddd; text-align: left;">Dla kogo</th> 1401</tr> 1402</thead> 1403<tbody> 1404<tr style="background: #f9f9f9;"> 1405<td style="padding: 10px 14px; border: 1px solid #ddd;"><strong>Glock 19</strong><br />kompakt polimerowy</td> 1406<td style="padding: 10px 14px; border: 1px solid #ddd; white-space: nowrap;">ok. 185 mm</td> 1407<td style="padding: 10px 14px; border: 1px solid #ddd; white-space: nowrap;">102 mm</td> 1408<td style="padding: 10px 14px; border: 1px solid #ddd; white-space: nowrap;">ok. 670 g</td> 1409<td style="padding: 10px 14px; border: 1px solid #ddd; white-space: nowrap;">15+1</td> 1410<td style="padding: 10px 14px; border: 1px solid #ddd;">Pierwszy pistolet do noszenia â najbezpieczniejszy uniwersalny wybór</td> 1411</tr> 1412<tr style="background: #ffffff;"> 1413<td style="padding: 10px 14px; border: 1px solid #ddd;"><strong>CZ P-10 C</strong><br />kompakt polimerowy</td> 1414<td style="padding: 10px 14px; border: 1px solid #ddd; white-space: nowrap;">ok. 187 mm</td> 1415<td style="padding: 10px 14px; border: 1px solid #ddd; white-space: nowrap;">102 mm</td> 1416<td style="padding: 10px 14px; border: 1px solid #ddd; white-space: nowrap;">ok. 740 g</td> 1417<td style="padding: 10px 14px; border: 1px solid #ddd; white-space: nowrap;">15+1</td> 1418<td style="padding: 10px 14px; border: 1px solid #ddd;">CeniÄ cy lepszy spust i wymienne nakÅadki chwytu</td> 1419</tr> 1420<tr style="background: #f9f9f9;"> 1421<td style="padding: 10px 14px; border: 1px solid #ddd;"><strong>Glock 26</strong><br />subkompakt</td> 1422<td style="padding: 10px 14px; border: 1px solid #ddd; white-space: nowrap;">ok. 163 mm</td> 1423<td style="padding: 10px 14px; border: 1px solid #ddd; white-space: nowrap;">87 mm</td> 1424<td style="padding: 10px 14px; border: 1px solid #ddd; white-space: nowrap;">ok. 615 g</td> 1425<td style="padding: 10px 14px; border: 1px solid #ddd; white-space: nowrap;">10+1</td> 1426<td style="padding: 10px 14px; border: 1px solid #ddd;">Maksymalna dyskrecja, skryte noszenie pod lekkim ubraniem</td> 1427</tr> 1428<tr style="background: #ffffff;"> 1429<td style="padding: 10px 14px; border: 1px solid #ddd;"><strong>CZ 75 Compact</strong><br />kompakt stalowy</td> 1430<td style="padding: 10px 14px; border: 1px solid #ddd; white-space: nowrap;">ok. 184 mm</td> 1431<td style="padding: 10px 14px; border: 1px solid #ddd; white-space: nowrap;">ok. 96 mm</td> 1432<td style="padding: 10px 14px; border: 1px solid #ddd; white-space: nowrap;">ok. 930 g</td> 1433<td style="padding: 10px 14px; border: 1px solid #ddd; white-space: nowrap;">14+1</td> 1434<td style="padding: 10px 14px; border: 1px solid #ddd;">CeniÄ cy klasykÄ, miÄkki odrzut i mechanizm DA/SA</td> 1435</tr> 1436</tbody> 1437</table> 1438</div> 1439<p style="text-align: justify;"><span style="font-weight: 400;">Masa katalogowa z pustym magazynkiem, bez amunicji â w peÅni zaÅadowany pistolet bÄdzie ciÄższy o ok. 150â250 g, w zależnoÅci od modelu i pojemnoÅci magazynka. Dane dla Glocków dotyczÄ generacji 5.</span></p> 1440<h2 id="kaliber">Jaki kaliber wybraÄ do noszenia?</h2> 1441<p style="text-align: justify;"><span style="font-weight: 400;">Tutaj dyskusja jest krótsza, niż mogÅoby siÄ wydawaÄ. <strong>9Ã19 mm to praktyczny standard</strong> i nie ma powodu, by od niego odchodziÄ. Powody sÄ trzy: rozsÄ dny odrzut nawet w lekkiej konstrukcji, wysoka pojemnoÅÄ magazynków przy zachowaniu sensownych gabarytów oraz dostÄpnoÅÄ i cena amunicji, która pozwala realnie trenowaÄ.</span></p> 1442<p style="text-align: justify;"><span style="font-weight: 400;">Mocniejsze kalibry â .40 S&W czy .45 ACP â oznaczajÄ ostrzejszy odrzut w lekkim pistolecie i mniej naboi w magazynku. SÅabsze, jak .380 Auto (9Ã17), pozwalajÄ zmniejszyÄ gabaryty, ale ograniczajÄ
1442wybór modeli i skutecznoÅÄ. WiÄcej o różnicach miÄdzy nabojami znajdziesz w naszym wpisie <a href="https://twojabron.pl/pl/blog/Najczesciej-wystepujace-kalibry-broni-palnej-kompleksowy-poradnik/45">o najczÄÅciej wystÄpujÄ cych kalibrach broni palnej</a>.</span></p> 1443<p style="text-align: justify;"><span style="font-weight: 400;">Jedna uwaga praktyczna: <strong>ta sama amunicja zachowuje siÄ inaczej w lufie 102 mm i 87 mm</strong>. Po zakupie subkompaktu warto sprawdziÄ na strzelnicy, jak konkretny typ naboju pracuje wÅaÅnie w Twoim egzemplarzu â zwÅaszcza pod kÄ tem niezawodnoÅci podawania.</span></p> 1444<p style="text-align: justify;"><span style="font-weight: 400;"><img lazy src="data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs%3D" data-src="/userdata/public/assets/BLOG/pexels-perfect-lens-7558205.jpg" alt="Naboje pistoletowe leÅ¼Ä ce na ciemnym tle w klimatycznym oÅwietleniu" width="1300" /><noscript><img src="/userdata/public/assets/BLOG/pexels-perfect-lens-7558205.jpg" alt="Naboje pistoletowe leÅ¼Ä ce na ciemnym tle w klimatycznym oÅwietleniu" width="1300" /></noscript></span></p> 1445<h2 id="trening">Dlaczego trening po zakupie jest obowiÄ zkowy?</h2> 1446<p style="text-align: justify;"><span style="font-weight: 400;">Noszenie pistoletu to nie stan posiadania, tylko <strong>zestaw umiejÄtnoÅci, które trzeba utrzymywaÄ</strong>. Dobycie z kabury spod ubrania, kontrola sytuacji, Åwiadome zabezpieczenie, bezpieczne odÅożenie broni â to wszystko wymaga powtórzeÅ, których nie zastÄ pi lektura instrukcji.</span></p> 1447<p style="text-align: justify;"><span style="font-weight: 400;">Minimum, które ma sens: <strong>regularny trening bezstrzaÅowy w domu</strong> (z broni sprawdzonej jako rozÅadowana, w bezpiecznym kierunku) plus systematyczne wyjÅcia na strzelnicÄ. Warto też pamiÄtaÄ, że trening z dobyciem z kabury na wielu obiektach wymaga zgody prowadzÄ cego strzelanie â najlepiej ustaliÄ to wczeÅniej.</span></p> 1448<p style="text-align: justify;"><span style="font-weight: 400;">Do tego dochodzi kwestia prawna: prawo do noszenia broni nie jest prawem do jej użycia. Zasady obrony koniecznej reguluje Kodeks karny i warto je znaÄ na poziomie znacznie gÅÄbszym niż hasÅowy. Przydatne bÄdzie też przypomnienie zasad <a href="https://twojabron.pl/pl/blog/Jak-legalnie-przewozic-bron/69">legalnego przewożenia broni</a> oraz <a href="https://twojabron.pl/pl/blog/Wszystko,co-musisz-wiedziec-o-bezpiecznym-przechowywaniu-broni/2">bezpiecznego przechowywania</a>.</span></p> 1449<h2 id="bledy">Jakich bÅÄdów uniknÄ Ä przy wyborze pistoletu do noszenia?</h2> 1450<ul> 1451<li>â <strong>Wybór najmniejszego możliwego modelu âbo Åatwiej ukryÄ".</strong> Subkompakt, z którego strzelasz źle i którego nie lubisz trenowaÄ, jest gorszym wyborem niż kompakt.</li> 1452<li>â <strong>OszczÄdzanie na kaburze i pasku.</strong> Klasyczny scenariusz: kilka tysiÄcy zÅotych na broÅ i kilkadziesiÄ t zÅotych na kaburÄ, po czym pistolet zostaje w szafie.</li> 1453<li>â <strong>Ignorowanie zapisów w legitymacji posiadacza broni.</strong> Cel pozwolenia i ewentualne ograniczenia noszenia to pierwsza rzecz do sprawdzenia, nie ostatnia.</li> 1454<li>â <strong>Zakup bez wczeÅniejszego przestrzelania.</strong> Ergonomia kompaktu jest bardziej wymagajÄ ca niż peÅnowymiarowego pistoletu â różnice czuÄ od pierwszego magazynka.</li> 1455<li>â <strong>Traktowanie zakupu jako koÅca procesu.</strong> Bez treningu pistolet w kaburze jest tylko ciÄżarem.</li> 1456</ul> 1457<div style="background: #ED1C24; border-radius: 8px; padding: 20px 25px; margin: 25px 0; text-align: center;"> 1458<p style="text-align: center; margin: 0;"><strong><span style="color: #ffffff;">Chcesz wziÄ Ä kilka kompaktów do rÄki przed decyzjÄ ?</span></strong></p> 1459<p style="text-align: center; margin: 8px 0 0 0;"><span style="font-weight: 400; color: #ffffff;">Sklep, rusznikarnia i strzelnica Twoja BroÅ mieszczÄ siÄ pod jednym adresem: ul. MyÅliwska 6, SuchodóŠkoÅo Tarczyna, okoÅo 40 km od Warszawy. Na miejscu porównasz modele i przetestujesz je na strzelnicy, również w weekendy.</span></p> 1460<p style="text-align: center; margin: 8px 0 0 0;"><strong><span style="color: #ffffff;">Umów siÄ telefonicznie: <a style="color: #ffffff; text-decoration: underline;" href="tel:784695388">784 695 388</a></span></strong></p> 1461</div> 1462<h2 id="faq">FAQ â najczÄÅciej zadawane pytania</h2> 1463<h3>Czy z pozwoleniem sportowym mogÄ nosiÄ pistolet?</h3> 1464<p style="text-align: justify;"><span style="font-weight: 400;">Tak, ustawa nie zakazuje noszenia broni posiadanej na podstawie pozwolenia do celów sportowych. W Årodkach transportu publicznego broÅ musi byÄ jednak przewożona rozÅadowana â bez amunicji w komorze nabojowej i w magazynkach. Trzeba też sprawdziÄ legitymacjÄ posiadacza broni: organ Policji może w pozwoleniu ograniczyÄ lub wykluczyÄ możliwoÅÄ noszenia.</span></p> 1465<h3>Czy broÅ kolekcjonerskÄ można nosiÄ?</h3> 1466<p style="text-align: justify;"><span style="font-weight: 400;">Nie. Art. 10 ust. 8 ustawy o broni i amunicji zakazuje noszenia broni posiadanej na podstawie pozwolenia do celów kolekcjonerskich lub pamiÄ tkowych bez zgody wÅaÅciwego organu Policji. Można jÄ natomiast legalnie przemieszczaÄ w stanie rozÅadowanym, np. na strzelnicÄ.</span></p> 1467<h3>Czy pistolet trzeba nosiÄ z pustÄ komorÄ nabojowÄ ?</h3> 1468<p style="text-align: justify;"><span style="font-weight: 400;">Przepisy nie wprowadzajÄ takiego wymogu przy zwykÅym noszeniu. Pojawia siÄ on w Årodkach transportu publicznego, gdzie broÅ co do zasady przewozi siÄ rozÅadowanÄ â wyjÄ tkiem jest broÅ do ochrony osobistej oraz ochrony bezpieczeÅstwa innych osób i mienia, która może byÄ za
1468Åadowana, ale bez naboju w komorze i w stanie zabezpieczonym.</span></p> 1469<h3>Czy mogÄ wziÄ Ä pistolet do samolotu?</h3> 1470<p style="text-align: justify;"><span style="font-weight: 400;">Nie do kabiny pasażerskiej. Art. 35 ust. 2 ustawy o broni i amunicji zakazuje przewożenia broni i amunicji w kabinach pasażerskich statków powietrznych osobom innym niż specjalnie do tego upoważnione. BroÅ podróżuje wyÅÄ cznie w bagażu rejestrowanym, na warunkach okreÅlonych przez przewoźnika.</span></p> 1471<h3>Jaki pistolet do noszenia dla poczÄ tkujÄ cego bÄdzie najlepszy?</h3> 1472<p style="text-align: justify;"><span style="font-weight: 400;">Kompakt polimerowy w kalibrze 9Ã19 â Glock 19 lub CZ P-10 C. Oba majÄ masÄ ok. 670â740 g, pojemnoÅÄ 15+1, prosty spust iglicowy i ogromny wybór kabur. To najlepszy kompromis miÄdzy komfortem noszenia a ÅatwoÅciÄ trafiania.</span></p> 1473<h3>Ile kosztuje pistolet do noszenia wraz z osprzÄtem?</h3> 1474<p style="text-align: justify;"><span style="font-weight: 400;">Orientacyjnie (stan na 2026 r.) sam pistolet w tej klasie to wydatek od ok. 3 000 zÅ. Do tego trzeba doliczyÄ sztywnÄ kaburÄ i solidny pas â razem zwykle ok. 10â20% ceny pistoletu â dodatkowe magazynki oraz szafÄ na broÅ klasy S1. Realny budżet startowy to ok. 5 000â6 500 zÅ, a o aktualne ceny konkretnych modeli najlepiej zapytaÄ w sklepie.</span></p> 1475<h2 id="podsumowanie">Podsumowanie</h2> 1476<p style="text-align: justify;"><span style="font-weight: 400;">Wybór pistoletu do noszenia zaczyna siÄ nie od modelu, tylko od <strong>legitymacji posiadacza broni</strong> â to cel pozwolenia decyduje o tym, czy w ogóle wolno Ci nosiÄ. Dopiero potem przychodzi czas na sprzÄt.</span></p> 1477<p style="text-align: justify;"><span style="font-weight: 400;">A tu rekomendacja jest doÅÄ jednoznaczna: dla wiÄkszoÅci osób <strong>kompakt polimerowy w 9Ã19 â Glock 19 albo CZ P-10 C â to najrozsÄ dniejszy pierwszy wybór</strong>. WystarczajÄ co maÅy, żeby go realnie nosiÄ, i wystarczajÄ co duży, żeby dobrze siÄ z niego strzelaÅo. Subkompakt w rodzaju Glocka 26 ma sens, gdy dyskrecja jest absolutnym priorytetem i masz już wyrobionÄ technikÄ. Stalowy CZ 75 Compact wybiorÄ ci, którzy ceniÄ miÄkki odrzut i klasycznÄ ergonomiÄ bardziej niż każde zaoszczÄdzone 200 gramów.</span></p> 1478<p style="text-align: justify;"><span style="font-weight: 400;">I jedna rzecz, której żadna tabela nie zastÄ pi: <strong>kompakty różniÄ siÄ w dÅoni znacznie bardziej niż peÅnowymiarowe pistolety</strong>. Krótszy chwyt oznacza, że drobne różnice w profilu rÄkojeÅci sÄ od razu wyczuwalne. Weź kilka modeli do rÄki, zanim zdecydujesz.</span></p> 1479<p style="text-align: justify;"><span style="font-size: 10pt; color: #666;"><em>Stan prawny: wrzesieÅ 2026 r. Przepisy dotyczÄ ce noszenia broni bywajÄ nowelizowane â przed podjÄciem decyzji warto zweryfikowaÄ aktualne brzmienie ustawy o broni i amunicji oraz rozporzÄ dzeÅ wykonawczych.</em></span></p> 1480<h2 id="polecamy">Przy okazji polecamy</h2> 1481<ul style="list-style: none; padding-left: 0;"> 1482<li style="margin-bottom: 8px;">ð <a href="https://twojabron.pl/pl/blog/Jak-wybrac-pistolet-na-strzelnice-Poradnik-dla-poczatkujacych/70">Jak wybraÄ pistolet na strzelnicÄ? Poradnik dla poczÄ tkujÄ cych</a></li> 1483<li style="margin-bottom: 8px;">ð <a href="https://twojabron.pl/pl/blog/Jak-legalnie-przewozic-bron/69">Jak legalnie przewoziÄ broÅ? Kompletny przewodnik</a></li> 1484<li style="margin-bottom: 8px;">ð <a href="https://twojabron.pl/pl/blog/Jak-uzyskac-pozwolenie-na-bron-sportowa-Wszystko,co-powinienes-wiedziec/36">Jak uzyskaÄ pozwolenie na broÅ sportowÄ ? Wszystko, co powinieneÅ wiedzieÄ</a></li> 1485</ul> 1486 </div> 1487 1488 </article> 1489 1490 <ul class="article-tags"> 1491 <li><a href="/pl/blog/tag/bron">#broÅ</a></li> 1492 <li><a href="/pl/blog/tag/rodzaje-broni">#rodzaje broni</a></li> 1493 <li><a href="/pl/blog/tag/akcesoria">#akcesoria</a></li> 1494 </ul> 1495 1496 1497 1498 </div> 1499 1500 </div> 1501 </div> 1502 </div> 1503<div class="bottom-footer row"> 1504 <div class="container"> 1505 <div class="box" id="box_loginsmall"> 1506 <div class="boxhead">
1507 <span><img src="/libraries/images/1px.gif" alt="" class="px1">Zaloguj siÄ</span> 1508 </div> 1509 <div class="innerbox"> 1510 <form action="https://twojabron.pl/pl/login" method="post"> 1511 <fieldset> 1512 <div class="none bottest"><!-- <input name="bottest1" value="1" /> --> <input name="bottest2" /></div> 1513 <div class="row login-inputs"> 1514 <label for="mail_input">E-mail:</label> 1515 <input type="text" name="mail" class="mail" id="mail_input"> 1516 <label for="pass_input">HasÅo:</label> 1517 <input type="password" name="pass" class="pass" id="pass_input"> 1518 </div> 1519 1520 1521 1522 <div class="row"> 1523 <button type="submit" class="btn login"> 1524 <img src="/libraries/images/1px.gif" alt="" class="px1"> 1525 <span>Zaloguj siÄ</span> 1526 </button> 1527 </div> 1528 <a href="/pl/passremind" class="remind row"> 1529 <img src="/libraries/images/1px.gif" alt="" class="px1"> 1530 <span>Nie pamiÄtasz hasÅa?</span> 1531 </a> 1532 1533 1534 <div class="social-login-buttons"> 1535 <h3> 1536 Lub zaloguj siÄ przez: 1537 </h3> 1538 <div class="buttons-wrapper"> 1539 <a class="btn btn-login-facebook r--hspacing-xs" href="/pl/login/facebook"> 1540 <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20" fill="none"> 1541 <path d="M19.9999 10C19.9999 4.47715 15.5228 0 9.99997 0C4.47713 0 0 4.47715 0 10C0 14.9913 3.65684 19.1283 8.43747 19.8785V12.8906H5.89842V10H8.43747V7.79688C8.43747 5.29062 9.93039 3.90625 12.2146 3.90625C13.3087 3.90625 14.4531 4.10156 14.4531 4.10156V6.5625H13.1921C11.9499 6.5625 11.5625 7.33334 11.5625 8.12417V10H14.3359L13.8925 12.8906H11.5625V19.8785C16.3431 19.1283 19.9999 14.9913 19.9999 10Z" fill="white"></path> 1542 <path d="M13.8925 12.8906L14.3359 9.99998H11.5625V8.12414C11.5625 7.33333 11.9499 6.56249 13.1921 6.56249H14.4531V4.10156C14.4531 4.10156 13.3087 3.90625 12.2146 3.90625C9.93039 3.90625 8.43748 5.29061 8.43748 7.79686V9.99998H5.89844V12.8906H8.43748V19.8785C8.95437 19.9595 9.47678 20.0001 9.99997 19.9999C10.5315 19.9999 11.0533 19.9583 11.5625 19.8785V12.8906H13.8925Z" fill="#2563EB"></path> 1543 </svg> 1544 Facebook 1545 1546 </a> 1547 1548 <a class="btn btn-login-google r--hspacing-xs" href="/pl/login/google"> 1549 <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20" fill="none"> 1550 <path d="M19.9997 10.2249C19.9997 9.56659 19.9401 8.94159 19.8379 8.33325H10.2168V12.0916H15.7255C15.4786 13.3249 14.7549 14.3666 13.6821 15.0749V17.5749H16.9686C18.8928 15.8333 19.9997 13.2666 19.9997 10.2249Z" fill="#4285F4"></path> 1551 <path d="M10.2164 19.9999C12.9751 19.9999 15.2824 19.0999 16.9682 17.5749L13.6817 15.0749C12.7622 15.6749 11.5957 16.0415 10.2164 16.0415C7.55147 16.0415 5.29519 14.2832 4.48633 11.9082H1.09766V14.4832C2.77497 17.7499 6.22324 19.9999 10.2164 19.9999Z" fill="#34A853"></path> 1552 <path d="M4.48702 11.9083C4.27416 11.3083 4.16347 10.6666 4.16347 9.99993C4.16347 9.33327 4.28267 8.6916 4.48702 8.0916V5.5166H1.09834C0.400169 6.8666 0 8.38327 0 9.99993C0 11.6166 0.400169 13.1333 1.09834 14.4833L4.48702 11.9083Z" fill="#FBBC05"></path> 1553 <path d="M10.2164 3.95833C11.7235 3.95833 13.0687 4.46667 14.133 5.45834L17.0449 2.60833C15.2824 0.991668 12.9751 0 10.2164 0C6.22324 0 2.77497 2.25 1.09766 5.51667L4.48633 8.09167C5.29519 5.71667 7.55147 3.95833 10.2164 3.95833Z" fill="#EA4335"></path> 1554 </svg> 1555 Google 1556 </a> 1557 </div> 1558 </div> 1559 <div class="login-register"> 1560 <h4>Nie masz jeszcze konta?</h4> 1561 <a href="/pl/reg" class="register row btn">
1562 <img src="/libraries/images/1px.gif" alt="" class="px1"> 1563 <span>Zarejestruj siÄ</span> 1564 </a> 1565 </div> 1566 </fieldset> 1567 </form> 1568 </div> 1569 </div> 1570 </div> 1571</div><footer class="footer row"> 1572 <div class="innerfooter container row"> 1573 <div class="footer__company-info"> 1574 <a href="/" title="Strona gÅówna"> 1575 <img lazy src="data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs%3D" data-src="/skins/user/rwd_shoper_25/images/logo.png" alt="twojabron.pl"> 1576 </a> 1577 <p> 1578 Gwarantujemy fachowÄ obsÅugÄ oraz peÅne doradztwo w zakresie doboru sprzÄtu. Nasza firma wciÄ Å¼ siÄ rozwija i stale poszerza ofertÄ. Na koniec każdego zakupu przez PaÅstwa najbardziej s
1578atysfakcjonuje nas Wasza radoÅÄ, która nas umacnia w przekonaniu, że to co robimy jest ważne i potrzebne. 1579 </p> 1580 </div> 1581 <ul class="overall"> 1582 <li class="overall flex flex-3" id="footgroup1"> 1583 <ul> 1584 <li class="head hidden">Pomoc</li> 1585 <li> 1586 <a href="/o-firmie" title="O firmie" id="footlink8"> 1587 <img alt="" src="/libraries/images/1px.gif"> 1588 O firmie 1589 </a> 1590 </li> 1591 <li> 1592 <a href="/pl/i/Regulamin-sklepu/27" title="Regulamin sklepu" id="footlink27"> 1593 <img alt="" src="/libraries/images/1px.gif"> 1594 Regulamin sklepu 1595 </a> 1596 </li> 1597 <li> 1598 <a href="/pl/i/Praca/19" title="Praca" id="footlink21"> 1599 <img alt="" src="/libraries/images/1px.gif"> 1600 Praca 1601 </a> 1602 </li> 1603 <li> 1604 <a href="/pl/i/Klauzula-informacyjna-dla-uczestnikow-rekrutacji/20" title="Klauzula informacyjna dla uczestników rekrutacji" id="footlink22"> 1605 <img alt="" src="/libraries/images/1px.gif"> 1606 Klauzula informacyjna dla uczestników rekrutacji 1607 </a> 1608 </li> 1609 <li> 1610 <a href="/regulamin/voucher" title="Regulamin voucher" id="footlink23"> 1611 <img alt="" src="/libraries/images/1px.gif"> 1612 Regulamin voucher 1613 </a> 1614 </li> 1615 <li> 1616 <a href="/kontakt-i-dane-firmy" title="Kontakt i dane firmy" id="footlink9"> 1617 <img alt="" src="/libraries/images/1px.gif"> 1618 Kontakt i dane firmy 1619 </a> 1620 </li> 1621 <li> 1622 <a href="/pl/blog" title="Blog" id="footlink24"> 1623 <img alt="" src="/libraries/images/1px.gif"> 1624 Blog 1625 </a> 1626 </li> 1627 </ul> 1628 </li> 1629 <li class="overall flex flex-3" id="footgroup5"> 1630 <ul> 1631 <li class="head hidden">Moje konto</li> 1632 <li> 1633 <a href="/panel/" title="Twoje zamówienia" id="footlink13">
1634 <img alt="" src="/libraries/images/1px.gif"> 1635 Twoje zamówienia 1636 </a> 1637 </li> 1638 <li> 1639 <a href="/panel/edit" title="Ustawienia konta" id="footlink14"> 1640 <img alt="" src="/libraries/images/1px.gif"> 1641 Ustawienia konta 1642 </a> 1643 </li> 1644 <li> 1645 <a href="/panel/favourites" title="Przechowalnia" id="footlink15"> 1646 <img alt="" src="/libraries/images/1px.gif"> 1647 Przechowalnia 1648 </a> 1649 </li> 1650 </ul> 1651 </li> 1652 <li class="overall flex flex-3" id="footgroup4"> 1653 <ul> 1654 <li class="head hidden">PÅatnoÅci i dostawa</li> 1655 <li> 1656 <a href="/pl/i/Formy-platnosci/10" title="Formy pÅatnoÅci" id="footlink10"> 1657 <img alt="" src="/libraries/images/1px.gif"> 1658 Formy pÅatnoÅci 1659 </a> 1660 </li> 1661 <li> 1662 <a href="https://zwroty-shoper.pl/019ecfeb-5c07-7e4d-994d-f8bc6574b824/twojabron.pl/pl_PL" title="Zwrot / OdstÄ pienie od zakupu" id="footlink25"> 1663 <img alt="" src="/libraries/images/1px.gif"> 1664 Zwrot / OdstÄ pienie od zakupu 1665 </a> 1666 </li> 1667 <li> 1668 <a href="/pl/i/Czas-i-koszty-dostawy/4" title="Czas i koszty dostawy" id="footlink4"> 1669 <img alt="" src="/libraries/images/1px.gif"> 1670 Czas i koszty dostawy 1671 </a> 1672 </li> 1673 <li> 1674 <a href="/pl/i/Raty/6" title="Raty" id="footlink17"> 1675 <img alt="" src="/libraries/images/1px.gif"> 1676 Raty 1677 </a> 1678 </li> 1679 <li> 1680 <a href="/pl/i/Zwroty-i-reklamacje/7" title="Zwroty i reklamacje" id="footlink6"> 1681 <img alt="" src="/libraries/images/1px.gif"> 1682 Zwroty i reklamacje 1683 </a> 1684 </li> 1685 <li> 1686 <a href="/pl/i/Czas-realizacji-zamowienia/5" title="Czas realizacji zamówienia" id="footlink5">
1687 <img alt="" src="/libraries/images/1px.gif"> 1688 Czas realizacji zamówienia 1689 </a> 1690 </li> 1691 </ul> 1692 </li> 1693 </ul> 1694 <div class="row footer__links"> 1695 <a href="https://www.youtube.com/@TBCHOfficial" target="_blank" rel="noopener" class="youtube_sm" aria-label="YouTube"> 1696 <svg xmlns="http://www.w3.org/2000/svg" width="29" height="28" viewBox="0 0 29 28" fill="none" style="position:relative; top:3px;"> 1697<rect x="1.5" y="3" width="26" height="22" rx="6" stroke="#313131" stroke-width="2"/> 1698<path d="M11.5 8.5L20.5 14L11.5 19.5V8.5Z" fill="#313131"/> 1699 </svg> 1700</a> 1701 <a href="https://www.facebook.com/twojabronpl/" target="_blank" rel="noopener" class="facebook sm"> 1702 <svg xmlns="http://www.w3.org/2000/svg" width="29" height="28" viewBox="0 0 29 28" fill="none"> 1703 <circle cx="14.5" cy="14" r="13" stroke="#313131" stroke-width="2"/> 1704 <path d="M16.0337 12.4368H16.2337V12.2368V11.2236V11.0236H16.0337H14.2178V10.571C14.2178 9.89214 14.358 9.45886 14.5894 9.21679C14.8292 8.97691 15.2696 8.83048 15.9702 8.83048H16.1702V8.63048V7.6001V7.4001H15.9702C14.8675 7.4001 14.0213 7.64477 13.4804 8.17908L13.4804 8.17907L13.4788 8.18063C12.9505 8.71417 12.7067 9.52565 12.7067 10.571V11.0236H11.7003H11.5003V11.2236V12.2368V12.4368H11.7003H12.7067V20.6001V20.8001H12.9067H14.0178H14.2178V20.6001V12.4368H16.0337Z" fill="#313131" stroke="#313131" stroke-width="0.4"/> 1705 </svg> 1706 </a> 1707 <a href="https://www.instagram.com/twojabron.pl/" target="_blank" rel="noopener" class="instagram sm"> 1708 <svg xmlns="http://www.w3.org/2000/svg" width="29" height="28" viewBox="0 0 29 28" fill="none"> 1709 <rect x="1.5" y="1" width="26" height="26" rx="2" stroke="#313131" stroke-width="2"/> 1710 <circle cx="14.5" cy="14" r="6" stroke="#313131" stroke-width="2"/> 1711 </svg> 1712 </a> 1713 <span class="blik pay"> 1714 <img lazy src="data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs%3D" data-src="/userdata/public/assets/icons/blik.svg" alt="" width="51" height="18" /> 1715 </span> 1716 <span class="inbank pay"> 1717 <img lazy src="data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs%3D" data-src="/userdata/public/assets/icons/inbank.webp" alt="" width="45" height="18" /> 1718 </span> 1719 <span class="przelewy24 pay"> 1720 <img lazy src="data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs%3D" data-src="/userdata/public/assets/svg/przelewy24.svg" alt="" width="51" height="18" /> 1721 </span> 1722 <span class="paypal pay"> 1723 <img lazy src="data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs%3D" data-src="/userdata/public/assets/icons/payPo-ico.svg" alt="" width="51" height="18" /> 1724 </span> 1725 </div> 1726 <div class="row footer__copy"> 1727 <a href="https://www.shoper.pl/premium/" target="_blank" rel="noopener" title="Sklep internetowy Shoper Premium" class="popup">Shoper Premium</a> 1728 1729 <span> 1730 Made with 1731 <svg xmlns="http://www.w3.org/2000/svg" width="21" height="20" viewBox="0 0 21 20" fill="none"> 1732 <path d="M9.69882 5.04064L10.4995 6.11089L11.3002 5.04064C11.962 4.15605 13.021 3.58325 14.1995 3.58325C16.2009 3.58325 17.8329 5.21419 17.8329 7.24158C17.8329 8.12449 17.6922 8.93741 17.4481 9.6921L17.4481 9.69209L17.446 9.6986C16.8593 11.5554 15.6495 13.0721 14.3154 14.2186C12.977 15.3689 11.5712 16.0965 10.6941 16.3949L10.6941 16.3948L10.6847 16.3981C10.6847 16.3981 10.6687 16.4029 10.6344 16.4078C10.5968 16.4131 10.5502 16.4166 10.4995 16.4166C10.4488 16.4166 10.4023 16.4131 10.3646 16.4078C10.3338 16.4034 10.3177 16.399 10.3148 16.3982L10.305 16.3949C9.42789 16.0965 8.02203 15.3689 6.68361 14.2186C5.3496 13.0721 4.13979 11.5554 3.55306 9.6986L3.55308 9.6986L3.55098 9.6921C3.30681 8.93742 3.1662 8.12449 3.1662 7.24158C3.1662 5.21419 4.79815 3.58325 6.79953 3.58325C7.97806 3.58325 9.03702 4.15605 9.69882 5.
173204064Z" stroke="#ED1C24" stroke-width="2"/> 1733 </svg> 1734 by 1735 <a href="https://www.mamezi.pl/" target="_blank" rel="noopener" title="Mamezi Studio" class="popup"> mamezi.pl</a> 1736 </span> 1737 <span class="desktop-only">Copyright 2023</span> 1738 </div> 1739 </div> 1740 1741 </footer> 1742 1743 <div class="up"> 1744 <a href="#" title="do góry" class="btn fa fa-2x fa-angle-up"> 1745 <img src="/libraries/images/1px.gif" alt="" class="px1" /> 1746 <span>do góry</span> 1747 </a> 1748 </div> 1749</div><!-- and of wrap --> 1750 1751<div class="modal-overlay"></div><!-- overlay for modal lightbox--> 1752
1753<script type="text/javascript" src="/skins/user/rwd_shoper_25/js/lazyloader.js"></script>
vendor: 2 bytes, line 1753
1753
1754<script type="text/javascript" src="/skins/user/rwd_shoper_25/js/user.js?sci=729"></script>
vendor: 2 bytes, line 1754
1754
1755<script type="text/javascript" src="/skins/user/rwd_shoper_25/js/scripts.js?sci=729"></script>
1755 1756 1757 1758 1759 <div class="info-message info-message_hidden"> 1760 <strong class="info-message__text">Sklep jest w trybie podglÄ du</strong> 1761 </div> 1762 1763<!-- Google Tag Manager (noscript) -->
vendor: 69 bytes, lines 1763-1764
1763 1764<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=
1764GTM-MB6TS5MR
vendor: 85 bytes, lines 1764-1765
1764" 1765height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
1766<!-- End Google Tag Manager (noscript) -->
1767<script type="text/javascript" src="https://shoper.inbank.dev/public/getscript.html?inbankshopid=381&inbankhoplng=1" async></script>
vendor: 1 bytes, line 1767
1767
1768<script type="text/javascript"> 1769 var content_types = { 1770 shop_index: 'Main page', 1771 shop_product: 'Products | Product', 1772 shop_product_list: 'Products | Category', 1773 shop_categories_list: 'Products | Categories list', 1774 shop_product_producer: 'Products | Vendor', 1775 shop_product_promo: 'Products | Promotions', 1776 shop_product_new: 'Products | New', 1777 shop_product_day: 'Products | Products of the day', 1778 shop_product_search: 'Products | Search results', 1779 shop_product_loyaltylist: 'Products | Loyalty list', 1780 shop_product_mailfriend: 'Products | Mail to friend', 1781 shop_infopage: 'Info page', 1782 shop_news: 'Blog | News', 1783 shop_news_list: 'Blog | News list', 1784 shop_news_category_list: 'Blog | Category', 1785 shop_news_tag_list: 'Blog | Tag list', 1786 shop_basket: 'Cart | Cart', 1787 shop_basket_address: 'Cart | Address', 1788 shop_basket_step2: 'Cart | Step 2', 1789 shop_basket_step3: 'Cart | Step 3', 1790 shop_basket_done: 'Cart | Done', 1791 shop_basket_finished: 'Cart | Finished', 1792 shop_login: 'User | Login', 1793 shop_login_register: 'User | Register', 1794 shop_login_passremind: 'User | Password reminder', 1795 shop_panel: 'Panel | Main', 1796 shop_panel_orders: 'Panel | Order list', 1797 shop_panel_order: 'Panel | Order', 1798 shop_panel_payment: 'Panel | Payment', 1799 shop_panel_comments: 'Panel | Comments', 1800 shop_panel_favourites: 'Panel | Favourites', 1801 shop_panel_addresses: 'Panel | Addresses', 1802 shop_panel_address: 'Panel | Address', 1803 shop_panel_password: 'Panel | Password change', 1804 shop_panel_edit: 'Panel | Edit profile', 1805 shop_contact: 'Contact form', 1806 shop_facebook_splash: 'Facebook splash', 1807 shop_links_list: 'Links list', 1808 shop_newsletter_unsign: 'Newsletter | Unsign' 1809 }; 1810 document.addEventListener('DOMContentLoaded', function () { 1811 var shoperCampaignsLayer = {}; 1812 1813 var content_type = content_types[document.body.className.split(' ')[0]]; 1814 1815 if (!!document.cookie.indexOf("admin_ip_verify")) { 1816 var visitor_type = 'user'; 1817 } else { 1818 var visitor_type = 'admin'; 1819 } 1820 1821 if (eval(atob(document.querySelector('head').getAttribute('data-features'))).includes('shoper_campaigns_google_app')) { 1822 1823 } 1824 1825 1826 if (eval(atob(document.querySelector('head').getAttribute('data-features'))).includes('shoper_campaigns_facebook_app')) { 1827 1828 } 1829 1830 if (window.shopLayer && Object.keys(shoperCampaignsLayer).length > 0) { 1831 shopLayer.push(Object.assign( 1832 shoperCampaignsLayer, 1833 { 1834 ads_installed: 'true', 1835 ads_contentType: content_type, 1836 ads_visitorType: visitor_type, 1837 }, 1838 )); 1839 } 1840 }); 1841</script>
vendor: 1 bytes, line 1841
1841
1842<script> 1843 // ========================================== 1844 // File: widget-search-runtime-snippet.html 1845 // Role: RWD Widget Search Logic 1846 // ========================================== 1847 (function bootstrapWidgetLogic() { 1848 if (window.BeekingWidgetLogic && window.BeekingWidgetLogic.version === 1) { 1849 dispatchReadyEvent(); 1850 return; 1851 } 1852 1853 function dispatchReadyEvent() { 1854 try { 1855 window.dispatchEvent(new CustomEvent('beeking:widget-logic-ready')); 1856 } catch (error) { 1857 var event = document.createEvent('Event'); 1858 event.initEvent('beeking:widget-logic-ready', true, true); 1859 window.dispatchEvent(event); 1860 } 1861 } 1862 1863 function createRuntimeMethods(deps) { 1864 var shared = deps.shared; 1865 var getConfig = deps.getConfig; 1866 var getState = deps.getState; 1867 var getRefs = deps.getRefs; 1868 var isPreviewMode = deps.isPreviewMode; 1869 var isEnhancedMotion = deps.isEnhancedMotion; 1870 var buildBasePayload = deps.buildBasePayload; 1871 var getClientSessionId = deps.getClientSessionId; 1872 var postBeekingJson = deps.postBeekingJson; 1873 var updateURLState = deps.updateURLState; 1874 var state = getState(); 1875 var scrollTimeout = null; 1876 var SEARCH_FALLBACK_DELAY_MS = 2000; 1877 1878 function getResultsEl() { return getRefs().resultsEl; } 1879 function getSidebarEl() { return getRefs().sidebarEl; } 1880 function getInputEl() { return getRefs().inputEl; } 1881 function getConfigSnapshot() { return getConfig(); } 1882 1883 function buildShoperComparisonUrl(query, searchId) { 1884 var CONFIG = getConfigSnapshot(); 1885 var lang = shared.getWidgetLanguage(); 1886 var url = '/webapi/front/' + lang + '/search/short-list?text=' + encodeURIComponent(query) + '&org=' + encodeURIComponent(query); 1887 url += '&clientSessionId=' + encodeURIComponent(getClientSessionId()); 1888 if (searchId) url += '&searchId=' + encodeURIComponent(searchId); 1889 if (CONFIG.uniqueId) url += '&uniqueId=' + encodeURIComponent(CONFIG.uniqueId); 1890 return url; 1891 } 1892 1893 function trackShoperSearch(query, data, searchId) { 1894 var CONFIG = getConfigSnapshot(); 1895 if (!CONFIG.trackShoperSearchEndpoint) return; 1896 var summary = shared.extractShoperSearchSummary(data); 1897 var products = Array.isArray(summary.products) ? summary.products : []; 1898 var categories = Array.isArray(summary.categories) ? summary.categories : []; 1899 var producers = Array.isArray(summary.producers) ? summary.producers : []; 1900 var payload = buildBasePayload({ 1901 query: query || '', 1902 shopUrl: CONFIG.shopUrl, 1903 products: products, 1904 categories: categories, 1905 producers: producers, 1906 productsCount: typeof summary.productsCount === 'number' ? summary.productsCount : products.length, 1907 categoriesCount: typeof summary.categoriesCount === 'number' ? summary.categoriesCount : categories.length, 1908 producersCount: typeof summary.producersCount === 'number' ? summary.producersCount : producers.length 1909 }); 1910 if (searchId) payload.searchId = searchId; 1911 postBeekingJson(CONFIG.trackShoperSearchEndpoint, payload, { keepalive: true }).catch(function () { });
1912 } 1913 1914 function triggerShoperComparisonSearch(query, searchId) { 1915 if (!query) return; 1916 if (state.shoperComparisonAbortController) { 1917 try { state.shoperComparisonAbortController.abort(); } catch (error) { } 1918 } 1919 state.shoperComparisonAbortController = new AbortController(); 1920 var controller = state.shoperComparisonAbortController; 1921 fetch(buildShoperComparisonUrl(query, searchId), { 1922 signal: controller.signal, 1923 credentials: 'same-origin' 1924 }) 1925 .then(function (res) { 1926 if (!res.ok) throw new Error('HTTP ' + res.status); 1927 return res.json(); 1928 }) 1929 .then(function (data) { 1930 trackShoperSearch(query, data, searchId); 1931 }) 1932 .catch(function () { }) 1933 .finally(function () { 1934 if (state.shoperComparisonAbortController === controller) state.shoperComparisonAbortController = null; 1935 }); 1936 } 1937 1938 function clearSearchFallbackTimer() { 1939 if (state.searchFallbackTimer) { 1940 clearTimeout(state.searchFallbackTimer); 1941 state.searchFallbackTimer = null; 1942 } 1943 } 1944 1945 function isSearchStillActive(query, searchId, signal) { 1946 if (signal && signal.aborted) return false; 1947 return state.query === query && state.searchId === searchId; 1948 } 1949 1950 function parseAIResponseNumber(value) { 1951 if (typeof value === 'number' && isFinite(value)) return value; 1952 if (typeof value === 'string') { 1953 var parsed = parseFloat(value); 1954 if (isFinite(parsed)) return parsed; 1955 } 1956 return null; 1957 } 1958 1959 function getAIProductScore(product) { 1960 if (!product || typeof product !== 'object') return null; 1961 var finalScore = parseAIResponseNumber(product.relevantScoreBreakdown && product.relevantScoreBreakdown.finalScore); 1962 if (finalScore !== null) return finalScore; 1963 return parseAIResponseNumber(product.relevantScore); 1964 } 1965 1966 function normalizeAIResponse(data) { 1967 if (!data || typeof data !== 'object') { 1968 return { 1969 result: data, 1970 shouldShowEmptyState: false 1971 }; 1972 } 1973 1974 var normalized = Object.assign({}, data); 1975 var filteredProducts = Array.isArray(data.filteredProducts) ? data.filteredProducts.slice() : []; 1976 var relatedProducts = Array.isArray(data.relatedProducts) ? data.relatedProducts.slice() : []; 1977 var hardCutoffThreshold = parseAIResponseNumber(data.hard_cutoff_threshold); 1978 1979 if (hardCutoffThreshold !== null) { 1980 filteredProducts = filteredProducts.filter(function (product) { 1981 var score = getAIProductScore(product); 1982 return score === null || score >= hardCutoffThreshold; 1983 }); 1984 1985 relatedProducts = relatedProducts.filter(function (product) { 1986 var score = getAIProductScore(product); 1987 return score === null || score >= hardCutoffThreshold; 1988 }); 1989 } 1990 1991 normalized.filteredProducts = filteredProducts; 1992 normalized.relatedProducts = relatedProducts; 1993 1994 return { 1995 result: normalized, 1996 shouldShowEmptyState: normalized.success === true && filteredProducts.length === 0 && relatedProducts.length === 0 1997 }; 1998 } 1999 2000 function normalizeShoperFallbackResults(data, query) { 2001 var lang = shared.getWidgetLanguage(); 2002 var langCode = lang.split('_')[0]; 2003 var products = []; 2004 2005 if (data && data.products && data.products.list && Array.isArray(data.products.list)) products = data.products.list; 2006 else if (Array.isArray(data)) products = data; 2007 else if (data && data.products && Array.isArray(data.products)) products = data.products; 2008 else if (data && data.results && Array.isArray(data.results)) products = data.results; 2009 else if (data && data.items && Array.isArray(data.items)) products = data.items; 2010 else if (data && typeof data === 'object') products = Object.values(data); 2011 2012 if (!products.length) { 2013 return null; 2014 } 2015 2016 var results = {};
2017 products.forEach(function (product, index) { 2018 if (!product || (!product.product_id && !product.id && !product.name && !product.title)) { 2019 return; 2020 } 2021 2022 var price = product.price || product.price_gross || product.price_net || ''; 2023 if (typeof price === 'string') { 2024 price = price.replace(/\s/g, '').replace(',', '.').replace(/[^\d.]/g, ''); 2025 } 2026 2027 var promotionPrice = product.promotion_price || product.promotionPrice || null; 2028 if (promotionPrice && typeof promotionPrice === 'string') { 2029 promotionPrice = promotionPrice.replace(/\s/g, '').replace(',', '.').replace(/[^\d.]/g, ''); 2030 } 2031 2032 var stock = (product.attributes && product.attributes.stock) || product.stock || product.availability || null; 2033 var producerName = (product.attributes && product.attributes.producer_name) || product.brand || ''; 2034 var imgUrl = product.img || product.image || product.image_url || product.photo || ''; 2035 if (imgUrl && !imgUrl.startsWith('http') && !imgUrl.startsWith('//')) { 2036 imgUrl = imgUrl.startsWith('/') ? imgUrl : '/' + imgUrl; 2037 } 2038 2039 var productUrl = product.url || product.link || product.seo_url || ''; 2040 if (productUrl && !productUrl.startsWith('http') && !productUrl.startsWith('//')) { 2041 productUrl = productUrl.startsWith('/') ? productUrl : '/' + productUrl; 2042 } else if (!productUrl) { 2043 productUrl = '/' + langCode + '/searchquery/' + encodeURIComponent(query) + '/1/full/5'; 2044 } 2045 2046 results['product_' + index] = { 2047 id: String(product.product_id || product.id || ('fallback_' + index)), 2048 product_id: String(product.product_id || product.id || ''), 2049 name: product.name || product.title || '', 2050 title: product.name || product.title || '', 2051 url: productUrl, 2052 img: imgUrl, 2053 price: price, 2054 promotionPrice: promotionPrice || null, 2055 promotion_price: promotionPrice || null, 2056 stock: stock, 2057 category: product.category ? { name: product.category.name || product.category } : null, 2058 attributes: product.attributes || {}, 2059 brand: producerName, 2060 tags: product.tags || '' 2061 }; 2062 }); 2063 2064 if (Object.keys(results).length === 0) { 2065 return null; 2066 } 2067 2068 return { 2069 results: results, 2070 isShoperFallback: true 2071 }; 2072 } 2073 2074 function fetchShoperFallbackResults(query, searchId, signal) { 2075 return fetch(buildShoperComparisonUrl(query, searchId), { 2076 signal: signal, 2077 credentials: 'same-origin' 2078 }) 2079 .then(function (res) { 2080 if (!res.ok) throw new Error('HTTP ' + res.status); 2081 return res.json(); 2082 }) 2083 .then(function (data) { 2084 return normalizeShoperFallbackResults(data, query); 2085 }) 2086 .catch(function (error) { 2087 if (error && error.name === 'AbortError') return null; 2088 return null; 2089 }); 2090 } 2091 2092 function handleScroll() { 2093 var resultsEl = getResultsEl(); 2094 var inputEl = getInputEl(); 2095 if (!resultsEl || !inputEl) return; 2096 if (scrollTimeout) clearTimeout(scrollTimeout); 2097 scrollTimeout = setTimeout(function () { 2098 if (isPreviewMode() && !inputEl.value.trim()) return; 2099 if (!inputEl.value.trim()) return; 2100 if (state.loading || state.isLoadingMore || state.isFiltering || !state.hasMore) return; 2101 var scrollTop = resultsEl.scrollTop; 2102 var scrollHeight = resultsEl.scrollHeight; 2103 var clientHeight = resultsEl.clientHeight; 2104 var dist = scrollHeight - (scrollTop + clientHeight); 2105 if (dist <= 50 && scrollHeight > clientHeight) { 2106 showLoadMoreSpinner(); 2107 loadNextPage(); 2108 } 2109 }, 100); 2110 } 2111 2112 function showLoadMoreSpinner() { 2113 var resultsEl = getResultsEl(); 2114 if (!resultsEl || resultsEl.querySelector('.shoper-load-more')) return; 2115 resultsEl.insertAdjacentHTML('beforeend', '<div class="shoper-load-more"><div class="shoper-load-more-spinner"></div><span class="shoper-load-more-text">
2115Åadowanie...</span></div>'); 2116 } 2117 2118 function hideLoadMoreSpinner() { 2119 var resultsEl = getResultsEl(); 2120 if (!resultsEl) return; 2121 var spinner = resultsEl.querySelector('.shoper-load-more'); 2122 if (spinner) spinner.remove(); 2123 } 2124 2125 function scrollToFirstNewProductRow(existingCount) { 2126 var resultsEl = getResultsEl(); 2127 if (!resultsEl) return; 2128 var allFiltered = resultsEl.querySelectorAll('.shoper-product-card:not(.shoper-related-product)'); 2129 if (allFiltered.length > existingCount) { 2130 var firstNew = allFiltered[existingCount]; 2131 if (firstNew) { 2132 resultsEl.scrollTo({ 2133 top: Math.max(0, firstNew.offsetTop - 120), 2134 behavior: isEnhancedMotion() ? 'smooth' : 'auto' 2135 }); 2136 } 2137 } 2138 } 2139 2140 function transformCategoryArrayToTree(apiNodes) { 2141 if (!Array.isArray(apiNodes)) return {}; 2142 var tree = {}; 2143 apiNodes.forEach(function (node) { 2144 var rawId = node.categoryId || node.category_id || node.id; 2145 var key = String(node.id || rawId); 2146 tree[key] = { 2147 name: node.name, 2148 value: String(rawId), 2149 children: node.children && node.children.length > 0 ? transformCategoryArrayToTree(node.children) : {} 2150 }; 2151 }); 2152 return tree; 2153 } 2154 2155 function buildTreeFromFlat(nodes) { 2156 var tree = {}; 2157 var map = {}; 2158 nodes.forEach(function (node) { 2159 var id = String(node.categoryId || node.category_id || node.id); 2160 map[id] = Object.assign({}, node, { id: id, children: [] }); 2161 }); 2162 nodes.forEach(function (node) { 2163 var id = String(node.categoryId || node.category_id || node.id); 2164 var parentId = node.parentId || node.parent_id; 2165 if (parentId) parentId = String(parentId); 2166 if (parentId && parentId !== '0' && map[parentId]) map[parentId].children.push(map[id]); 2167 else tree[id] = map[id]; 2168 }); 2169 return transformCategoryArrayToTree(Object.values(tree)); 2170 } 2171 2172 function buildCategoryMap(tree) { 2173 var map = {}; 2174 Object.values(tree).forEach(function (node) { 2175 map[node.value] = node; 2176 if (node.children) map = Object.assign({}, map, buildCategoryMap(node.children)); 2177 }); 2178 return map; 2179 } 2180 2181 async function fetchCategories() { 2182 var CONFIG = getConfigSnapshot(); 2183 try { 2184 var response = await postBeekingJson(CONFIG.categoriesEndpoint, buildBasePayload()); 2185 if (!response.ok) throw new Error('Failed'); 2186 var data = await response.json(); 2187 var treeData = {}; 2188 if (Array.isArray(data)) { 2189 if (data.some(function (node) { return node.children && node.children.length > 0; })) treeData = transformCategoryArrayToTree(data); 2190 else treeData = buildTreeFromFlat(data); 2191 } 2192 state.allCategories = treeData; 2193 state.categoryMap = buildCategoryMap(state.allCategories); 2194 } catch (error) { 2195 state.allCategories = {}; 2196 } 2197 } 2198 2199 async function fetchProducers() { 2200 var CONFIG = getConfigSnapshot(); 2201 try { 2202 var response = await postBeekingJson(CONFIG.producersEndpoint, buildBasePayload()); 2203 if (!response.ok) throw new Error('Failed'); 2204 var data = await response.json(); 2205 state.allProducers = Array.isArray(data) ? data : []; 2206 } catch (error) { 2207 state.allProducers = []; 2208 } 2209 } 2210 2211 async function fetchFilters() { 2212 var sidebarEl = getSidebarEl(); 2213 state.loadingFilters = true; 2214 try { 2215 await Promise.all([fetchCategories(), fetchProducers()]); 2216 state.filtersLoaded = true; 2217 if (sidebarEl && !isPreviewMode()) renderSidebar(); 2218 if (window.onFiltersLoaded) window.onFiltersLoaded(); 2219 } catch (error) { 2220 console.error('Error loading filters', error); 2221 } finally { 2222 state.loadingFilters = false; 2223 } 2224 } 2225 2226 function trackFullscreenOpen(query) { 2227 var CONFIG = getConfigSnapshot(); 2228 if (!CONFIG.trackFullscreenOpenEndpoint) return; 2229 try { 2230 postBeekingJson(CONFIG.trackFullscreenOpenEndpoint, buildBasePayload({ 2231 query: query || '', 2232 shopUrl: CONFIG.shopUrl 2233 })).catch(function () { });
2234 } catch (error) { } 2235 } 2236 2237 function trackPreviewOpen(query) { 2238 var CONFIG = getConfigSnapshot(); 2239 if (!CONFIG.trackPreviewOpenEndpoint) return; 2240 try { 2241 postBeekingJson(CONFIG.trackPreviewOpenEndpoint, buildBasePayload({ 2242 query: query || '', 2243 shopUrl: CONFIG.shopUrl 2244 })).catch(function () { }); 2245 } catch (error) { } 2246 } 2247 2248 function trackClick(product) { 2249 var CONFIG = getConfigSnapshot(); 2250 if (!CONFIG.trackEndpoint) return; 2251 var top10Ids = []; 2252 if (state.results && state.results.length > 0) { 2253 var resultCount = Math.min(state.results.length, 10); 2254 for (var i = 0; i < resultCount; i++) top10Ids.push(String(state.results[i].product_id || state.results[i].id)); 2255 } else if (isPreviewMode() && state.topProducts && state.topProducts.length > 0) { 2256 var topCount = Math.min(state.topProducts.length, 10); 2257 for (var j = 0; j < topCount; j++) top10Ids.push(String(state.topProducts[j].product_id || state.topProducts[j].id)); 2258 } 2259 var payload = buildBasePayload({ 2260 query: state.query, 2261 product: { 2262 id: product.id || String(product.product_id), 2263 product_id: product.product_id || product.id, 2264 title: product.name 2265 }, 2266 shopUrl: CONFIG.shopUrl, 2267 isFullscreen: true, 2268 topResultsProductIds: top10Ids 2269 }); 2270 if (state.searchId) payload.searchId = state.searchId; 2271 postBeekingJson(CONFIG.trackEndpoint, payload, { keepalive: true }).catch(function (error) { 2272 console.error(error); 2273 }); 2274 } 2275 2276 async function fetchTopData() { 2277 var CONFIG = getConfigSnapshot(); 2278 if (state.topDataLoading || state.topDataLoaded) return; 2279 state.topDataLoading = true; 2280 try { 2281 var response = await fetch( 2282 CONFIG.apiUrl + CONFIG.topDataEndpoint + 2283 '?uniqueId=' + encodeURIComponent(CONFIG.uniqueId) + 2284 '&clientSessionId=' + encodeURIComponent(getClientSessionId()), 2285 { method: 'GET', headers: { 'Content-Type': 'application/json' } } 2286 ); 2287 if (!response.ok) throw new Error('Failed'); 2288 var data = await response.json(); 2289 state.topProducts = data.topProducts || []; 2290 state.topCategories = data.topCategories || []; 2291 state.topQueries = data.topQueries || []; 2292 state.topDataLoaded = true; 2293 state.topDataLoading = false; 2294 if (isPreviewMode() && (!getInputEl() || !getInputEl().value.trim())) renderTopProducts(); 2295 } catch (error) { 2296 console.error('Error fetching top data:', error); 2297 state.topProducts = []; 2298 state.topCategories = []; 2299 state.topQueries = []; 2300 state.topDataLoading = false; 2301 } 2302 } 2303 2304 function renderTopProducts() { 2305 var resultsEl = getResultsEl(); 2306 var CONFIG = getConfigSnapshot(); 2307 if (!resultsEl) return; 2308 if (state.topDataLoading) { 2309 resultsEl.innerHTML = '<div class="shoper-loading"><div class="shoper-loading-spinner"></div><span>Åadowanie popularnych produktów...</span></div>'; 2310 renderPreviewSidebar(true); 2311 return; 2312 } 2313 if (!state.topDataLoaded || state.topProducts.length === 0) { 2314 resultsEl.innerHTML = '<div class="shoper-empty">Wpisz aby wyszukaÄ produkty...</div>'; 2315 renderPreviewSidebar(false); 2316 return; 2317 } 2318 resultsEl.innerHTML = window.BeekingWidgetRender.getTopProductsHTML(state.topProducts, CONFIG.showStockInResults); 2319 resultsEl.scrollTop = 0; 2320 renderPreviewSidebar(false); 2321 } 2322 2323 function renderPreviewSidebar(isLoading) { 2324 var sidebarEl = getSidebarEl(); 2325 var inputEl = getInputEl(); 2326 if (!sidebarEl) return; 2327 if (isLoading) { 2328 sidebarEl.innerHTML = '<div class="shoper-preview-sidebar-loading"><div class="shoper-loading-spinner"></div></div>'; 2329 return; 2330 } 2331 var matchedCats = state.matchedCategories || []; 2332 sidebarEl.innerHTML = window.BeekingWidgetRender.getPreviewSidebarHTML(state.topQueries, state.topCategories, matchedCats); 2333 sidebarEl.querySelectorAll('.shoper-query-pill').forEach(function (pill) { 2334 pill.addEventListener('click', function () { 2335 var q = this.getAttribute('data-query'); 2336 if (q && inputEl) { 2337 inputEl.value = q; 2338 performSearch(q); 2339 } 2340 }); 2341 }); 2342 } 2343 2344 function parsePrice(priceStr) { 2345 if (!priceStr) return 0; 2346 return parseFloat(priceStr.replace(/[^\d.,]/g, '').replace(',', '.').trim()) || 0; 2347 } 2348 2349 function renderLoading() { 2350 var resultsEl = getResultsEl(); 2351 if (resultsEl) resultsEl.innerHTML = '<div class="shoper-loading">Searching...</div>'; 2352 } 2353 2354 function renderEmptyState(msg) { 2355 var resultsEl = getResultsEl(); 2356 var sidebarEl = getSidebarEl(); 2357 if (resultsEl) resultsEl.innerHTML = '<div class="shoper-empty">' + (msg || 'No results found.') + '</div>'; 2358 if (sidebarEl) sidebarEl.innerHTML = ''; 2359 } 2360 2361 function renderError() { 2362 var resultsEl = getResultsEl(); 2363 if (resultsEl) resultsEl.innerHTML = '<div class="shoper-empty">Something went wrong. Please try again.</div>'; 2364 } 2365 2366 function decorateCardHtml(html, extraClass, animationDelay) { 2367 var nextHtml = html.replace('class="shoper-product-card', 'class="shoper-product-card' + (extraClass ? ' ' + extraClass : '')); 2368 if (animationDelay !== null && animationDelay !== undefined) { 2369 if (nextHtml.indexOf('<a ') === 0) nextHtml = nextHtml.replace('<a ', '<a style="--reorder-delay: ' + animationDelay + 'ms;" '); 2370 else if (nextHtml.indexOf('<div ') === 0) nextHtml = nextHtml.replace('<div ', '<div style="--reorder-delay: ' + animationDelay + 'ms;" '); 2371 } 2372 return nextHtml; 2373 } 2374 2375 function buildProductCardsHtml(products, startIndex, extraClass, builder) { 2376 return products.map(function (product, index) { 2377 var absoluteIndex = (startIndex || 0) + index; 2378 var animationDelay = isEnhancedMotion() && absoluteIndex < 8 ? absoluteIndex * 20 : null; 2379 var className = animationDelay !== null ? ('reorder-enter' + (extraClass ? ' ' + extraClass : '')) : extraClass; 2380 return decorateCardHtml(builder(product), className, animationDelay); 2381 }).join(''); 2382 } 2383 2384 function scheduleReorderCleanup() { 2385 var resultsEl = getResultsEl(); 2386 if (!resultsEl || !isEnhancedMotion()) return; 2387 setTimeout(function () { 2388 resultsEl.querySelectorAll('.reorder-enter').forEach(function (el) { 2389 el.classList.remove('reorder-enter'); 2390 el.style.removeProperty('--reorder-delay'); 2391 }); 2392 }, 320); 2393 } 2394 2395 function renderResults(productsToRender, append) { 2396 var resultsEl = getResultsEl(); 2397 var CONFIG = getConfigSnapshot(); 2398 if (!resultsEl) return; 2399 var html = productsToRender.map(function (product) { 2400 return window.BeekingWidgetRender.createProductCardHtml(product, CONFIG.showStockInResults); 2401 }).join(''); 2402 if (append) resultsEl.insertAdjacentHTML('beforeend', html); 2403 else { 2404 resultsEl.innerHTML = html; 2405 resultsEl.scrollTop = 0; 2406 } 2407 } 2408 2409 function animateReorder(newFiltered, newRelated, append) { 2410 var resultsEl = getResultsEl(); 2411 var CONFIG = getConfigSnapshot(); 2412 if (!resultsEl) return; 2413 if (!append && isEnhancedMotion()) { 2414 resultsEl.querySelectorAll('.shoper-product-card').forEach(function (card) { 2415 card.classList.add('reordering'); 2416 }); 2417 } 2418 var filteredToRender = state.filteredResults.slice(); 2419 var relatedToRender = state.relatedProducts.slice(); 2420 var existingCount = state.filteredResults.length - newFiltered.length; 2421 2422 function buildRelatedProductHtml(product) { 2423 return window.BeekingWidgetRender.createProductCardHtml(product, CONFIG.showStockInResults); 2424 } 2425 2426 function proceedWithRender() { 2427 if (!append) { 2428 resultsEl.innerHTML = ''; 2429 } else { 2430 var allCardsArr = Array.from(resultsEl.querySelectorAll('.shoper-product-card:not(.shoper-related-product)')); 2431 var separator = resultsEl.querySelector('.shoper-related-separator'); 2432 var allRelated = resultsEl.querySelectorAll('.shoper-related-product'); 2433 for (var i = existingCount; i < allCardsArr.length; i++) allCardsArr[i].remove(); 2434 if (separator) separator.remove(); 2435 allRelated.forEach(function (el) { el.remove(); }); 2436 var appendedHtml = buildProductCardsHtml(newFiltered, 0, '', function (product) { 2437 return window.BeekingWidgetRender.createProductCardHtml(product, CONFIG.showStockInResults); 2438 }); 2439 if (state.relatedProducts.length > 0) { 2440 if (state.filteredResults.length > 0) appendedHtml += '<div class="shoper-related-separator"><span>Produkty powiÄ zane</span></div>'; 2441 appendedHtml += buildProductCardsHtml(state.relatedProducts, newFiltered.length, 'shoper-related-product', buildRelatedProductHtml); 2442 } 2443 if (appendedHtml) resultsEl.insertAdjacentHTML('beforeend', appendedHtml); 2444 } 2445 if (append) { 2446 scheduleReorderCleanup(); 2447 scrollToFirstNewProductRow(existingCount); 2448 } 2449 } 2450 2451 if (append) { 2452 proceedWithRender(); 2453 return; 2454 } 2455 2456 var renderDelay = isEnhancedMotion() ? 120 : 0; 2457 setTimeout(function () { 2458 var html = ''; 2459 if (filteredToRender.length === 0 && state.relatedProducts.length > 0) { 2460 html += '<div class="shoper-search-message" style="grid-column: 1 / -1; padding: 0.5rem 0; margin-bottom: 0.5rem; text-align: center; color: #6b7280; font-size: 0.9rem;">Nie znaleziono dokÅadnych dopasowaÅ dla "<strong>' + state.query + '</strong>", ale mogÄ CiÄ zainteresowaÄ te produkty:</div>'; 2461 } 2462 html += buildProductCardsHtml(filteredToRender, 0, '', function (product) { 2463 return window.BeekingWidgetRender.createProductCardHtml(product, CONFIG.showStockInResults); 2464 }); 2465 if (filteredToRender.length > 0 && relatedToRender.length > 0) { 2466 html += '<div class="shoper-related-separator"><span>Produkty powiÄ zane</span></div>'; 2467 } 2468 html += buildProductCardsHtml(relatedToRender, filteredToRender.length, 'shoper-related-product', buildRelatedProductHtml); 2469 resultsEl.innerHTML = html; 2470 scheduleReorderCleanup(); 2471 }, renderDelay); 2472 } 2473
2474 function renderSidebar() { 2475 var sidebarEl = getSidebarEl(); 2476 if (!sidebarEl || isPreviewMode()) return; 2477 sidebarEl.innerHTML = window.BeekingWidgetRender.getSidebarHTML(state); 2478 attachSidebarListeners(state.maxPriceInResults || 500, sidebarEl); 2479 } 2480 2481 function attachSidebarListeners(rangeMax, rootElement) { 2482 var root = rootElement || getSidebarEl(); 2483 if (!root) return; 2484 var resetBtn = root.querySelector('.shoper-reset-filters-btn'); 2485 if (resetBtn) { 2486 resetBtn.addEventListener('click', function () { 2487 state.filters = { categories: [], producers: [], minPrice: 0, maxPrice: null }; 2488 state.page = 1; 2489 state.hasMore = true; 2490 root.querySelectorAll('input[type="checkbox"]').forEach(function (cb) { cb.checked = false; }); 2491 var rangeMaxVal = state.maxPriceInResults || 500; 2492 var minRange = root.querySelector('#shoper-range-min'); 2493 var maxRange = root.querySelector('#shoper-range-max'); 2494 var minInput = root.querySelector('#shoper-price-min-input'); 2495 var maxInput = root.querySelector('#shoper-price-max-input'); 2496 if (minRange) minRange.value = 0; 2497 if (maxRange) maxRange.value = rangeMaxVal; 2498 if (minInput) minInput.value = 0; 2499 if (maxInput) maxInput.value = rangeMaxVal; 2500 updateVisuals(null, root); 2501 fetchProducts(false); 2502 updateURLState(); 2503 }); 2504 } 2505 2506 var producerSearch = root.querySelector('.shoper-producer-search'); 2507 if (producerSearch) { 2508 producerSearch.addEventListener('input', function (e) { 2509 var query = e.target.value.toLowerCase(); 2510 root.querySelectorAll('.shoper-producer-list .shoper-filter-item').forEach(function (item) { 2511 var text = item.textContent || item.innerText; 2512 item.style.display = text.toLowerCase().includes(query) ? '' : 'none'; 2513 }); 2514 }); 2515 } 2516 2517 root.querySelectorAll('.shoper-tree-toggle').forEach(function (toggle) { 2518 toggle.addEventListener('click', function (e) { 2519 e.stopPropagation(); 2520 toggle.classList.toggle('expanded'); 2521 var nodeId = toggle.getAttribute('data-node-id'); 2522 if (nodeId) { 2523 if (toggle.classList.contains('expanded')) state.expandedNodes.add(nodeId); 2524 else state.expandedNodes.delete(nodeId); 2525 } 2526 var li = toggle.closest('li'); 2527 var ul = li && li.querySelector('ul'); 2528 if (ul) ul.classList.toggle('expanded'); 2529 }); 2530 }); 2531 2532 root.querySelectorAll('.category-filter').forEach(function (cb) { 2533 cb.addEventListener('change', function (e) { 2534 var value = e.target.value; 2535 if (e.target.checked) state.filters.categories.push(value); 2536 else state.filters.categories = state.filters.categories.filter(function (id) { return id !== value; }); 2537 debouncedFetch(); 2538 }); 2539 }); 2540 2541 root.querySelectorAll('.producer-filter').forEach(function (cb) { 2542 cb.addEventListener('change', function (e) { 2543 var value = e.target.value; 2544 if (e.target.checked) state.filters.producers.push(value); 2545 else state.filters.producers = state.filters.producers.filter(function (name) { return name !== value; }); 2546 debouncedFetch(); 2547 }); 2548 }); 2549 2550 var minSlider = root.querySelector('#shoper-range-min'); 2551 var maxSlider = root.querySelector('#shoper-range-max'); 2552 var minInput = root.querySelector('#shoper-price-min-input'); 2553 var maxInput = root.querySelector('#shoper-price-max-input'); 2554 if (minSlider && maxSlider && minInput && maxInput) { 2555 minSlider.addEventListener('input', handlePriceChange('min-slider', root)); 2556 maxSlider.addEventListener('input', handlePriceChange('max-slider', root)); 2557 minInput.addEventListener('input', handlePriceChange('min-input', root)); 2558 maxInput.addEventListener('input', handlePriceChange('max-input', root)); 2559 minInput.addEventListener('change', handlePriceChange('min-input', root)); 2560 maxInput.addEventListener('change', handlePriceChange('max-input', root)); 2561 minInput.addEventListener('blur', handlePriceChange('min-input', root)); 2562 maxInput.addEventListener('blur', handlePriceChange('max-input', root)); 2563 updateVisuals('init', root); 2564 } 2565 } 2566 2567 function updateVisuals(source, root) { 2568 var currentRoot = root || getSidebarEl(); 2569 if (!currentRoot) return { minVal: 0, maxVal: 0 }; 2570 var minSlider = currentRoot.querySelector('#shoper-range-min'); 2571 var maxSlider = currentRoot.querySelector('#shoper-range-max'); 2572 var minInput = currentRoot.querySelector('#shoper-price-min-input'); 2573 var maxInput = currentRoot.querySelector('#shoper-price-max-input'); 2574 var highlight = currentRoot.querySelector('#shoper-price-highlight'); 2575 var rangeMax = state.maxPriceInResults || 500; 2576 if (!minSlider || !maxSlider || !minInput || !maxInput) return { minVal: 0, maxVal: 0 }; 2577 var minVal = parseInt(minSlider.value, 10) || 0; 2578 var maxVal = parseInt(maxSlider.value, 10) || rangeMax; 2579 minVal = Math.max(0, Math.min(minVal, rangeMax)); 2580 maxVal = Math.max(0, Math.min(maxVal, rangeMax)); 2581 if (minVal > maxVal) { 2582 if (source === 'min-slider' || source === 'min-input') minVal = maxVal; 2583 else maxVal = minVal; 2584 } 2585 minSlider.value = minVal; 2586 maxSlider.value = maxVal; 2587 minInput.value = minVal; 2588 maxInput.value = maxVal; 2589 var percentMin = (minVal / rangeMax) * 100; 2590 var percentMax = (maxVal / rangeMax) * 100; 2591 if (highlight) { 2592 highlight.style.left = percentMin + '%'; 2593 highlight.style.width = (percentMax - percentMin) + '%'; 2594 } 2595 return { minVal: minVal, maxVal: maxVal }; 2596 } 2597 2598 function handlePriceChange(source, root) { 2599 return function () { 2600 var values = updateVisuals(source, root); 2601 state.filters.minPrice = values.minVal; 2602 state.filters.maxPrice = values.maxVal; 2603 debouncedFetch(); 2604 }; 2605 } 2606 2607 function debounce(func, wait) { 2608 var timeout; 2609 return function () { 2610 var args = arguments; 2611 clearTimeout(timeout); 2612 timeout = setTimeout(function () { 2613 func.apply(this, args); 2614 }, wait); 2615 }; 2616 } 2617 2618 var debouncedFetch = debounce(function () { 2619 state.page = 1; 2620 state.results = []; 2621 state.hasMore = true; 2622 state.filteredResults = []; 2623 state.relatedProducts = []; 2624 state.allRelatedBatches = []; 2625 state.hasRelatedProducts = false; 2626 state.previousThreshold = null; 2627 clearSearchFallbackTimer(); 2628 state.renderedFallbackSearchId = null; 2629 fetchProducts(false); 2630 updateURLState(); 2631 }, 500); 2632 2633 function resetResultState() { 2634 state.page = 1; 2635 state.results = []; 2636 state.hasMore = true; 2637 state.filteredResults = []; 2638 state.relatedProducts = []; 2639 state.allRelatedBatches = []; 2640 state.hasRelatedProducts = false; 2641 state.previousThreshold = null; 2642 clearSearchFallbackTimer(); 2643 state.renderedFallbackSearchId = null; 2644 } 2645 2646 function performSearch(query) { 2647 if (query === undefined || query === null) { 2648 state.loading = false; 2649 clearSearchFallbackTimer(); 2650 state.renderedFallbackSearchId = null; 2651 renderEmptyState('Type at least 2 characters...'); 2652 return; 2653 } 2654 query = String(query).trim(); 2655 if (!query && isPreviewMode()) { 2656 state.query = ''; 2657 renderTopProducts(); 2658 updateURLState(); 2659 return; 2660 } 2661 state.searchId = null; 2662 state.query = query; 2663 resetResultState(); 2664 state.categoryCounts = {}; 2665 state.maxPriceInResults = 0; 2666 state.filters = { minPrice: 0, maxPrice: null, categories: [], producers: [] }; 2667 state.categoryTree = {}; 2668 state.expandedNodes.clear(); 2669 state.matchedCategories = []; 2670 clearSearchFallbackTimer(); 2671 state.renderedFallbackSearchId = null; 2672 updateURLState(); 2673 if (!query || query.length < 2) { 2674 state.loading = false; 2675 if (!isPreviewMode()) renderEmptyState('Type at least 2 characters...'); 2676 return; 2677 } 2678 state.searchId = shared.generateSearchId(); 2679 fetchProducts(false); 2680 } 2681 2682 function loadNextPage() { 2683 state.page++; 2684 fetchProducts(true); 2685 } 2686 2687 async function fetchProducts(append) { 2688 var CONFIG = getConfigSnapshot(); 2689 if (append === undefined) append = false;
2690 if (state.searchAbortController) state.searchAbortController.abort(); 2691 if (state.filterAbortController) state.filterAbortController.abort(); 2692 state.searchAbortController = new AbortController(); 2693 var signal = state.searchAbortController.signal; 2694 var activeQuery = state.query; 2695 var activeSearchId = state.searchId; 2696 var fallbackPromise = null; 2697 var allowFallbackRender = !append; 2698 if (append) { 2699 state.isLoadingMore = true; 2700 } else { 2701 state.loading = true; 2702 clearSearchFallbackTimer(); 2703 state.renderedFallbackSearchId = null; 2704 renderLoading(); 2705 state.searchFallbackTimer = setTimeout(function () { 2706 if (!allowFallbackRender || !isSearchStillActive(activeQuery, activeSearchId, signal)) { 2707 return; 2708 } 2709 2710 fallbackPromise = fetchShoperFallbackResults(activeQuery, activeSearchId, signal).then(function (fallbackData) { 2711 if (!fallbackData || !allowFallbackRender || !isSearchStillActive(activeQuery, activeSearchId, signal)) { 2712 return fallbackData; 2713 } 2714 2715 state.renderedFallbackSearchId = activeSearchId; 2716 return handleSearchResults(fallbackData, false).then(function () { 2717 return fallbackData; 2718 }); 2719 }); 2720 }, SEARCH_FALLBACK_DELAY_MS); 2721 } 2722 var payload = buildBasePayload({ 2723 query: state.query, 2724 limit: CONFIG.limit || 30, 2725 shopUrl: CONFIG.shopUrl, 2726 page: state.page, 2727 producers: state.filters.producers, 2728 categories: state.filters.categories, 2729 showUnavailableProducts: CONFIG.showUnavailable, 2730 isFullscreen: true 2731 }); 2732 if (state.searchId) payload.searchId = state.searchId; 2733 if (state.filters.minPrice > 0) payload.priceMin = state.filters.minPrice; 2734 if (state.filters.maxPrice !== null && state.filters.maxPrice < state.maxPriceInResults) payload.priceMax = state.filters.maxPrice; 2735 triggerShoperComparisonSearch(state.query, state.searchId); 2736 try { 2737 var response = await postBeekingJson(CONFIG.endpoint, payload, { signal: signal }); 2738 if (!response.ok) throw new Error('Search failed'); 2739 var data = await response.json(); 2740 if (!isSearchStillActive(activeQuery, activeSearchId, signal)) return; 2741 2742 clearSearchFallbackTimer(); 2743 2744 var hasResults = !!(data && data.results && typeof data.results === 'object' && Object.keys(data.results).length > 0); 2745 if (hasResults) { 2746 allowFallbackRender = false; 2747 state.renderedFallbackSearchId = null; 2748 await handleSearchResults(data, append); 2749 return; 2750 } 2751 2752 if (!append) { 2753 if (state.renderedFallbackSearchId === activeSearchId) { 2754 return; 2755 } 2756 2757 var emptyFallbackData = await (fallbackPromise || fetchShoperFallbackResults(activeQuery, activeSearchId, signal)); 2758 if (emptyFallbackData && isSearchStillActive(activeQuery, activeSearchId, signal)) { 2759 state.renderedFallbackSearchId = activeSearchId; 2760 await handleSearchResults(emptyFallbackData, false); 2761 return; 2762 } 2763 } 2764 2765 await handleSearchResults(data, append); 2766 } catch (error) { 2767 clearSearchFallbackTimer(); 2768 if (error.name === 'AbortError') return; 2769 if (!append) { 2770 if (state.renderedFallbackSearchId === activeSearchId) { 2771 return; 2772 } 2773 2774 var errorFallbackData = await (fallbackPromise || fetchShoperFallbackResults(activeQuery, activeSearchId, signal));
2775 if (errorFallbackData && isSearchStillActive(activeQuery, activeSearchId, signal)) { 2776 state.renderedFallbackSearchId = activeSearchId; 2777 await handleSearchResults(errorFallbackData, false); 2778 return; 2779 } 2780 2781 renderError(); 2782 } 2783 } finally { 2784 clearSearchFallbackTimer(); 2785 state.loading = false; 2786 state.isLoadingMore = false; 2787 hideLoadMoreSpinner(); 2788 } 2789 } 2790 2791 async function filterProducts(products, append) { 2792 var CONFIG = getConfigSnapshot(); 2793 if (append === undefined) append = false; 2794 if (state.query.length < CONFIG.minQueryLengthForFilter) return { filtered: products, related: [] }; 2795 if (state.filterAbortController) state.filterAbortController.abort(); 2796 state.filterAbortController = new AbortController(); 2797 var signal = state.filterAbortController.signal; 2798 state.isFiltering = true; 2799 try { 2800 var mappedProducts = products.map(function (product) { 2801 var categoryName = ''; 2802 if (product.category) categoryName = typeof product.category === 'object' ? (product.category.name || '') : product.category; 2803 else if (product.category_name) categoryName = product.category_name; 2804 var brand = product.producer_name || ''; 2805 if (!brand && product.attributes && product.attributes.producer_name) brand = product.attributes.producer_name; 2806 var attributesString = ''; 2807 if (product.attributes && typeof product.attributes === 'object') { 2808 attributesString = Object.entries(product.attributes) 2809 .filter(function (entry) { return entry[1] !== undefined && entry[1] !== null; }) 2810 .map(function (entry) { return Array.isArray(entry[1]) ? entry[0] + ':' + entry[1].join('|') : entry[0] + ':' + entry[1]; }) 2811 .join(','); 2812 } 2813 var result = { 2814 id: String(product.id || product.product_id || ''), 2815 nazwa: product.name || '', 2816 kategoria: categoryName, 2817 brand: brand, 2818 tags: product.tags || '', 2819 price: product.price || '', 2820 regular_price: product.price || '', 2821 sale_price: product.promotion_price || '', 2822 attributes: attributesString, 2823 sku: product.product_code || product.sku || product.code || '', 2824 semantic_summary: product.semantic_summary || '', 2825 sparse_keywords: product.sparse_keywords || '', 2826 use_context: product.use_context || '', 2827 colors: product.colors || [], 2828 materials: product.materials || [] 2829 }; 2830 if (product.description && product.description.trim() !== '') result.description = product.description; 2831 return result; 2832 }); 2833 var payload = buildBasePayload({ 2834 query: state.query, 2835 products: mappedProducts, 2836 language: 'pl', 2837 isFullscreen: true 2838 }); 2839 if (state.matchedCategories.length > 0) payload.matched_categories = state.matchedCategories; 2840 if (state.previousThreshold !== null) payload.previousThreshold = state.previousThreshold; 2841 var response = await postBeekingJson(CONFIG.filterEndpoint, payload, { signal: signal }); 2842 if (!response.ok) return { filtered: products, related: [] }; 2843 var normalization = normalizeAIResponse(await response.json()); 2844 var data = normalization.result; 2845 var productMap = new Map();
2846 products.forEach(function (product) { 2847 productMap.set(String(product.id || product.product_id), product); 2848 }); 2849 var filtered = (data.filteredProducts || []).map(function (product) { 2850 return productMap.get(String(product.id)); 2851 }).filter(function (product) { 2852 return product !== undefined; 2853 }); 2854 var related = (data.relatedProducts || []).map(function (product) { 2855 return productMap.get(String(product.id)); 2856 }).filter(function (product) { 2857 return product !== undefined; 2858 }); 2859 if (data.matched_categories && data.matched_categories.length > 0) state.matchedCategories = data.matched_categories; 2860 if (data.threshold !== undefined && state.previousThreshold === null) state.previousThreshold = data.threshold; 2861 if (related.length > 0 && !state.hasRelatedProducts) state.hasRelatedProducts = true; 2862 if (related.length > filtered.length) state.hasMore = false; 2863 return { 2864 filtered: filtered, 2865 related: related, 2866 shouldShowEmptyState: normalization.shouldShowEmptyState 2867 }; 2868 } catch (error) { 2869 if (error.name === 'AbortError') return null; 2870 return { filtered: products, related: [] }; 2871 } finally { 2872 state.isFiltering = false; 2873 } 2874 } 2875 2876 async function handleSearchResults(data, append) { 2877 var products = []; 2878 var sidebarEl = getSidebarEl(); 2879 var isShoperFallback = data && data.isShoperFallback === true; 2880 if (Array.isArray(data.results)) products = data.results; 2881 else if (data.results && typeof data.results === 'object') products = Object.values(data.results); 2882 if (data.matched_categories && data.matched_categories.length > 0 && !append) { 2883 state.matchedCategories = data.matched_categories; 2884 if (isPreviewMode()) renderPreviewSidebar(false); 2885 } 2886 if (products.length === 0) { 2887 state.hasMore = false; 2888 if (!append && state.page === 1) { 2889 renderEmptyState('No products found matching your query.'); 2890 state.categoryCounts = {}; 2891 if (sidebarEl) renderSidebar(); 2892 } 2893 return; 2894 } 2895 if (!append) state.categoryCounts = {}; 2896 products.forEach(function (product) { 2897 var price = parsePrice(product.price); 2898 if (price > state.maxPriceInResults) state.maxPriceInResults = Math.ceil(price); 2899 var catId = product.category_id || product.main_category_id; 2900 if (!catId && product.category && typeof product.category === 'object') catId = product.category.id; 2901 if (catId) { 2902 var strId = String(catId); 2903 state.categoryCounts[strId] = (state.categoryCounts[strId] || 0) + 1; 2904 } 2905 }); 2906 if (sidebarEl) renderSidebar(); 2907 if (products.length < (getConfigSnapshot().limit || 30)) state.hasMore = false; 2908 if (append) state.results = state.results.concat(products); 2909 else state.results = products; 2910 if (!append && isShoperFallback) { 2911 state.filteredResults = []; 2912 state.relatedProducts = []; 2913 state.allRelatedBatches = []; 2914 state.hasRelatedProducts = false; 2915 } 2916 renderResults(products, append); 2917 if (isShoperFallback) { 2918 return; 2919 } 2920 if (state.query.length >= getConfigSnapshot().minQueryLengthForFilter) { 2921 var filterResult = await filterProducts(products, append); 2922 if (filterResult === null) return; 2923 if (filterResult.shouldShowEmptyState) { 2924 state.filteredResults = []; 2925 state.relatedProducts = []; 2926 state.allRelatedBatches = []; 2927 state.hasRelatedProducts = false; 2928 renderEmptyState('No products found matching your query.'); 2929 return; 2930 } 2931 var filtered = filterResult.filtered; 2932 var related = filterResult.related; 2933 var maxRelatedPerBatch = 5; 2934 var isFirstBatch = state.allRelatedBatches.length === 0; 2935 if (append) state.filteredResults = state.filteredResults.concat(filtered); 2936 else { 2937 state.filteredResults = filtered; 2938 state.allRelatedBatches = []; 2939 } 2940 var batchRelated = isFirstBatch || !append ? related : related.slice(0, maxRelatedPerBatch); 2941 if (batchRelated.length > 0) state.allRelatedBatches.push(batchRelated); 2942 if (!state.hasMore) state.relatedProducts = state.allRelatedBatches.flat(); 2943 else state.relatedProducts = state.allRelatedBatches.flat().slice(0, maxRelatedPerBatch); 2944 animateReorder(filtered, related, append); 2945 if (isPreviewMode() && state.matchedCategories.length > 0) renderPreviewSidebar(false); 2946 } 2947 } 2948 2949 return { 2950 attachSidebarListeners: attachSidebarListeners, 2951 fetchFilters: fetchFilters, 2952 fetchProducts: fetchProducts, 2953 fetchTopData: fetchTopData, 2954 handleScroll: handleScroll, 2955 loadNextPage: loadNextPage, 2956 performSearch: performSearch, 2957 renderEmptyState: renderEmptyState, 2958 renderPreviewSidebar: renderPreviewSidebar, 2959 renderSidebar: renderSidebar, 2960 renderTopProducts: renderTopProducts, 2961 trackClick: trackClick, 2962 trackFullscreenOpen: trackFullscreenOpen, 2963 trackPreviewOpen: trackPreviewOpen 2964 }; 2965 } 2966 2967 window.BeekingWidgetLogic = { 2968 version: 1,
2969 createRuntimeMethods: createRuntimeMethods 2970 }; 2971 2972 dispatchReadyEvent(); 2973 })(); 2974</script>
vendor: 1 bytes, line 2974
2974
2975<script> 2976 // ========================================== 2977 // File: widget-runtime-snippet.html 2978 // Role: RWD Widget Runtime 2979 // ========================================== 2980 (function bootstrapWidgetRuntime() { 2981 if (window.BeekingWidgetRuntime && window.BeekingWidgetRuntime.version === 1) { 2982 dispatchReadyEvent(); 2983 return; 2984 } 2985 2986 var REQUIRED_SHARED_METHODS = [ 2987 'createWidgetConfig', 2988 'generateClientSessionId', 2989 'generateSearchId', 2990 'getWidgetLanguage', 2991 'extractShoperSearchSummary', 2992 'getDisableWidgetFromConfig', 2993 'resolveSearchMotionMode' 2994 ]; 2995 var REQUIRED_LOGIC_METHODS = ['createRuntimeMethods']; 2996 2997 function hasRequiredSharedApi(shared) { 2998 if (!shared) return false; 2999 for (var i = 0; i < REQUIRED_SHARED_METHODS.length; i++) { 3000 if (typeof shared[REQUIRED_SHARED_METHODS[i]] !== 'function') return false; 3001 } 3002 return true; 3003 } 3004 3005 function hasRequiredLogicApi(logic) { 3006 if (!logic) return false; 3007 for (var i = 0; i < REQUIRED_LOGIC_METHODS.length; i++) { 3008 if (typeof logic[REQUIRED_LOGIC_METHODS[i]] !== 'function') return false; 3009 } 3010 return true; 3011 } 3012 3013 function dispatchReadyEvent() { 3014 try { 3015 window.dispatchEvent(new CustomEvent('beeking:widget-runtime-ready')); 3016 } catch (error) { 3017 var event = document.createEvent('Event'); 3018 event.initEvent('beeking:widget-runtime-ready', true, true); 3019 window.dispatchEvent(event); 3020 } 3021 } 3022 3023 function boot(shared, rawConfig) { 3024 var logic = window.BeekingWidgetLogic; 3025 if (!hasRequiredSharedApi(shared)) { 3026 if (shared) { 3027 console.error('BeekingWidgetShared is missing required methods:', REQUIRED_SHARED_METHODS.filter(function (key) { 3028 return typeof shared[key] !== 'function'; 3029 })); 3030 } 3031 return; 3032 } 3033 if (!hasRequiredLogicApi(logic)) { 3034 if (logic) { 3035 console.error('BeekingWidgetLogic is missing required methods:', REQUIRED_LOGIC_METHODS.filter(function (key) { 3036 return typeof logic[key] !== 'function'; 3037 })); 3038 } 3039 return; 3040 } 3041 if (boot.started) return; 3042 boot.started = true; 3043 3044 var resolvedConfig = shared.createWidgetConfig(rawConfig); 3045 var CONFIG = resolvedConfig.config; 3046 var isWidgetDisabled = resolvedConfig.isWidgetDisabled; 3047 var resolvedMotionMode = shared.resolveSearchMotionMode(CONFIG); 3048 3049 if (isWidgetDisabled) { 3050 window.BeekingShoperSearchWidget = window.BeekingShoperSearchWidget || { 3051 open: function () { }, 3052 setConfig: function () { } 3053 }; 3054 return; 3055 } 3056 3057 function closeOverlayImmediate() { 3058 if (!overlayEl) return; 3059 clearOverlayTimers(); 3060 overlayEl.style.visibility = 'hidden'; 3061 overlayEl.style.opacity = '0'; 3062 overlayEl.style.backdropFilter = 'none'; 3063 overlayEl.style.webkitBackdropFilter = 'none'; 3064 shadowHost.classList.remove('preview-mode'); 3065 isOverlayOpen = false; 3066 isOverlayClosing = false; 3067 isPreviewMode = false; 3068 document.body.style.overflow = ''; 3069 } 3070 3071 console.log('Beeking Widget Config:', resolvedConfig.debug); 3072 3073 var state = { 3074 query: '', 3075 clientSessionId: shared.generateClientSessionId(), 3076 searchId: null, 3077 results: [], 3078 categories: [], 3079 matched_categories: [], 3080 loading: false, 3081 filters: { minPrice: 0, maxPrice: null, categories: [], producers: [] }, 3082 categoryTree: {}, 3083 expandedNodes: new Set(), 3084 page: 1, 3085 hasMore: true, 3086 isLoadingMore: false, 3087 maxPriceInResults: 0, 3088 filteredResults: [], 3089 relatedProducts: [], 3090 allRelatedBatches: [], 3091 hasRelatedProducts: false, 3092 matchedCategories: [], 3093 isFiltering: false, 3094 previousThreshold: null, 3095 filtersLoaded: false, 3096 allCategories: null, 3097 allProducers: [], 3098 categoryCounts: {}, 3099 categoryMap: {}, 3100 topProducts: [], 3101 topCategories: [], 3102 topQueries: [], 3103 topDataLoaded: false, 3104 topDataLoading: false, 3105 searchAbortController: null, 3106 filterAbortController: null, 3107 shoperComparisonAbortController: null, 3108 searchFallbackTimer: null, 3109 renderedFallbackSearchId: null, 3110 loadingFilters: false 3111 }; 3112 3113 var overlayEl; 3114 var shadowHost; 3115 var shadowRoot; 3116 var inputEl; 3117 var resultsEl; 3118 var sidebarEl; 3119 var compactViewBtn; 3120 var largeViewBtn; 3121 var xlargeViewBtn; 3122 var isInitialized = false; 3123 var isOverlayInputFocused = false; 3124 var isPreviewMode = false; 3125 var isOverlayOpen = false; 3126 var isOverlayClosing = false; 3127 var overlayFocusTimer = null; 3128 var overlayCloseTimer = null; 3129 var overlayTransitionToken = 0; 3130 var cardViewMode = 'large'; 3131 var OVERLAY_TRANSITION_MS = 220; 3132 3133 function isMobile() { return window.innerWidth <= 768; } 3134 function isEnhancedMotion() { return resolvedMotionMode === 'enhanced'; } 3135 function getClosedModalTransform() { return isEnhancedMotion() ? 'scale(0.985)' : 'translateY(4px)'; } 3136 3137 function applyMotionModeState() { 3138 if (shadowHost) shadowHost.setAttribute('data-motion-mode', resolvedMotionMode); 3139 if (overlayEl) overlayEl.setAttribute('data-motion-mode', resolvedMotionMode); 3140 } 3141 3142 function applyOverlaySurface(mode) { 3143 if (!overlayEl) return; 3144 var isPreviewSurface = mode === 'preview'; 3145 overlayEl.style.background = isPreviewSurface ? 'rgba(0, 0, 0, 0.3)' : 'rgba(0, 0, 0, 0.5)'; 3146 if (isEnhancedMotion()) { 3147 overlayEl.style.backdropFilter = isPreviewSurface ? 'blur(4px)' : 'blur(8px)'; 3148 overlayEl.style.webkitBackdropFilter = isPreviewSurface ? 'blur(4px)' : 'blur(8px)'; 3149 } else { 3150 overlayEl.style.backdropFilter = 'none'; 3151 overlayEl.style.webkitBackdropFilter = 'none'; 3152 } 3153 } 3154 3155 function syncMotionMode() { 3156 resolvedMotionMode = shared.resolveSearchMotionMode(CONFIG); 3157 applyMotionModeState(); 3158 applyOverlaySurface(isPreviewMode ? 'preview' : 'fullscreen'); 3159 } 3160 3161 function setModalVisible(isVisible) { 3162 var modal = shadowRoot && shadowRoot.querySelector('.shoper-search-modal'); 3163 if (!modal) return; 3164 modal.style.transform = isVisible ? 'none' : getClosedModalTransform(); 3165 modal.style.opacity = isVisible ? '1' : '0'; 3166 } 3167 3168 function getClientSessionId() { 3169 if (!state.clientSessionId) state.clientSessionId = shared.generateClientSessionId(); 3170 return state.clientSessionId; 3171 } 3172 3173 function buildBasePayload(extra) { 3174 return Object.assign({ 3175 uniqueId: CONFIG.uniqueId, 3176 clientSessionId: getClientSessionId() 3177 }, extra || {}); 3178 } 3179 3180 function postJson(url, payload, options) { 3181 var requestInit = { 3182 method: 'POST', 3183 headers: { 'Content-Type': 'application/json' }, 3184 body: JSON.stringify(payload) 3185 }; 3186 if (options && options.keepalive) requestInit.keepalive = true; 3187 if (options && options.signal) requestInit.signal = options.signal; 3188 return fetch(url, requestInit); 3189 } 3190
3191 function postBeekingJson(endpoint, payload, options) { 3192 return postJson(CONFIG.apiUrl + endpoint, payload, options); 3193 } 3194 3195 function clearOverlayTimers() { 3196 if (overlayFocusTimer) { 3197 clearTimeout(overlayFocusTimer); 3198 overlayFocusTimer = null; 3199 } 3200 if (overlayCloseTimer) { 3201 clearTimeout(overlayCloseTimer); 3202 overlayCloseTimer = null; 3203 } 3204 } 3205 3206 function syncOriginalInputs() { 3207 document.querySelectorAll(CONFIG.selectors.input).forEach(function (input) { 3208 input.value = inputEl ? inputEl.value : input.value; 3209 }); 3210 } 3211 3212 function applyCardViewMode() { 3213 if (!shadowHost) return; 3214 var isLarge = cardViewMode === 'large'; 3215 var isXLarge = cardViewMode === 'xlarge'; 3216 var isCompact = !isLarge && !isXLarge; 3217 shadowHost.classList.toggle('card-view-large', isLarge); 3218 shadowHost.classList.toggle('card-view-xlarge', isXLarge); 3219 shadowHost.classList.toggle('card-view-compact', isCompact); 3220 if (compactViewBtn) { 3221 compactViewBtn.classList.toggle('is-active', isCompact); 3222 compactViewBtn.setAttribute('aria-pressed', String(isCompact)); 3223 } 3224 if (largeViewBtn) { 3225 largeViewBtn.classList.toggle('is-active', isLarge); 3226 largeViewBtn.setAttribute('aria-pressed', String(isLarge)); 3227 } 3228 if (xlargeViewBtn) { 3229 xlargeViewBtn.classList.toggle('is-active', isXLarge); 3230 xlargeViewBtn.setAttribute('aria-pressed', String(isXLarge)); 3231 } 3232 } 3233 3234 function setCardViewMode(mode) { 3235 cardViewMode = mode === 'large' || mode === 'xlarge' ? mode : 'compact'; 3236 applyCardViewMode(); 3237 } 3238 3239 function applyUrlState(params) { 3240 if (params.has('bk_q')) { 3241 state.query = params.get('bk_q'); 3242 if (inputEl) inputEl.value = state.query; 3243 } else { 3244 state.query = ''; 3245 if (inputEl) inputEl.value = ''; 3246 } 3247 state.filters.categories = params.has('bk_c') ? params.get('bk_c').split(',').filter(Boolean) : []; 3248 state.filters.producers = params.has('bk_p') ? params.get('bk_p').split(',').filter(Boolean) : []; 3249 state.filters.minPrice = params.has('bk_min') ? (parseInt(params.get('bk_min'), 10) || 0) : 0; 3250 if (params.has('bk_max')) { 3251 var maxValue = parseInt(params.get('bk_max'), 10); 3252 state.filters.maxPrice = isNaN(maxValue) ? null : maxValue; 3253 } else { 3254 state.filters.maxPrice = null; 3255 } 3256 } 3257 3258 function updateURLState() { 3259 if (!isInitialized) return; 3260 var isOverlayVisible = overlayEl && overlayEl.style.visibility === 'visible'; 3261 if (!isOverlayVisible && !isPreviewMode) return; 3262 var url = new URL(window.location.href); 3263 var params = url.searchParams; 3264 var keysToRemove = []; 3265 for (var key of params.keys()) { 3266 if (key.startsWith('bk_')) keysToRemove.push(key); 3267 } 3268 keysToRemove.forEach(function (keyToRemove) { params.delete(keyToRemove); }); 3269 if (state.query) params.set('bk_q', state.query); 3270 if (state.filters.categories && state.filters.categories.length > 0) params.set('bk_c', state.filters.categories.join(',')); 3271 if (state.filters.producers && state.filters.producers.length > 0) params.set('bk_p', state.filters.producers.join(',')); 3272 if (state.filters.minPrice > 0) params.set('bk_min', state.filters.minPrice); 3273 if (state.filters.maxPrice !== null && state.filters.maxPrice < (state.maxPriceInResults || 500)) params.set('bk_max', state.filters.maxPrice); 3274 window.history.replaceState({ shoperSearch: true }, '', url.toString()); 3275 } 3276 3277 function clearURLState() { 3278 var url = new URL(window.location.href); 3279 var params = url.searchParams; 3280 var changed = false; 3281 var keysToRemove = []; 3282 for (var key of params.keys()) { 3283 if (key.startsWith('bk_')) { 3284 keysToRemove.push(key); 3285 changed = true; 3286 } 3287 } 3288 keysToRemove.forEach(function (keyToRemove) { params.delete(keyToRemove); }); 3289 if (changed) window.history.replaceState({ shoperSearch: true }, '', url.toString()); 3290 } 3291 3292 function getRefs() { 3293 return { 3294 inputEl: inputEl, 3295 overlayEl: overlayEl, 3296 resultsEl: resultsEl, 3297 shadowHost: shadowHost, 3298 shadowRoot: shadowRoot, 3299 sidebarEl: sidebarEl 3300 }; 3301 } 3302
3303 var runtimeMethods = logic.createRuntimeMethods({ 3304 buildBasePayload: buildBasePayload, 3305 getClientSessionId: getClientSessionId, 3306 getConfig: function () { return CONFIG; }, 3307 getRefs: getRefs, 3308 getState: function () { return state; }, 3309 isEnhancedMotion: isEnhancedMotion, 3310 isPreviewMode: function () { return isPreviewMode; }, 3311 postBeekingJson: postBeekingJson, 3312 shared: shared, 3313 updateURLState: updateURLState 3314 }); 3315 3316 function init() { 3317 if (isInitialized) return; 3318 if (!window.BeekingWidgetRender) { 3319 setTimeout(init, 50); 3320 return; 3321 } 3322 createOverlay(); 3323 attachListeners(); 3324 isInitialized = true; 3325 runtimeMethods.fetchTopData(); 3326 runtimeMethods.fetchFilters(); 3327 var urlParams = new URLSearchParams(window.location.search); 3328 var hasBeekingParams = Array.from(urlParams.keys()).some(function (key) { return key.startsWith('bk_'); }); 3329 if (hasBeekingParams) { 3330 var canOpenOverlay = isMobile() || !CONFIG.disableFullpage; 3331 if (canOpenOverlay) { 3332 applyUrlState(urlParams); 3333 var hasFilters = state.filters.categories.length > 0 || 3334 state.filters.producers.length > 0 || 3335 state.filters.minPrice > 0 || 3336 state.filters.maxPrice !== null; 3337 if (hasFilters || isMobile()) openOverlay(); 3338 else openPreviewMode(); 3339 if (state.query || hasFilters) runtimeMethods.fetchProducts(false); 3340 } 3341 } 3342 window.addEventListener('popstate', function () { 3343 if (!isInitialized) return; 3344 var popParams = new URLSearchParams(window.location.search); 3345 var hasBkParams = Array.from(popParams.keys()).some(function (key) { return key.startsWith('bk_'); }); 3346 if (hasBkParams) { 3347 var popCanOpen = isMobile() || !CONFIG.disableFullpage; 3348 if (popCanOpen) { 3349 applyUrlState(popParams); 3350 var isVisible = overlayEl && overlayEl.style.visibility === 'visible'; 3351 if (sidebarEl) runtimeMethods.renderSidebar(); 3352 if (typeof window.updateMobileFilterBadge === 'function') window.updateMobileFilterBadge(); 3353 if (!isVisible && !isPreviewMode) { 3354 var hasPopFilters = state.filters.categories.length > 0 || 3355 state.filters.producers.length > 0 || 3356 state.filters.minPrice > 0 || 3357 state.filters.maxPrice !== null; 3358 if (hasPopFilters || isMobile()) openOverlay(); 3359 else openPreviewMode(); 3360 } 3361 if (state.query || state.filters.categories.length > 0 || state.filters.producers.length > 0) { 3362 runtimeMethods.fetchProducts(false); 3363 } else { 3364 state.results = []; 3365 if (isPreviewMode) runtimeMethods.renderTopProducts(); 3366 else runtimeMethods.renderEmptyState('Type at least 2 characters...'); 3367 } 3368 } 3369 } else { 3370 var overlayVisible = overlayEl && overlayEl.style.visibility === 'visible'; 3371 if (overlayVisible || isPreviewMode) closeOverlay(true); 3372 } 3373 }); 3374 } 3375 3376 function createOverlay() { 3377 var existingOverlay = document.querySelector('.shoper-search-overlay'); 3378 if (existingOverlay) existingOverlay.remove(); 3379 overlayEl = document.createElement('div'); 3380 overlayEl.className = 'shoper-search-overlay'; 3381 Object.assign(overlayEl.style, { 3382 position: 'fixed', 3383 top: '0', 3384 left: '0', 3385 width: '100vw', 3386 height: '100vh', 3387 background: 'rgba(0, 0, 0, 0.5)', 3388 backdropFilter: 'none', 3389 WebkitBackdropFilter: 'none', 3390 zIndex: '9999', 3391 display: 'flex', 3392 visibility: 'hidden', 3393 opacity: '0', 3394 transition: 'opacity 0.22s ease', 3395 justifyContent: 'center', 3396 alignItems: 'center', 3397 padding: '0', 3398 boxSizing: 'border-box', 3399 fontFamily: "'Inter', system-ui, -apple-system, sans-serif", 3400 color: '#333' 3401 }); 3402 shadowHost = document.createElement('div'); 3403 shadowHost.style.width = '100%'; 3404 shadowHost.style.height = '100%'; 3405 shadowRoot = shadowHost.attachShadow({ mode: 'open' }); 3406 var style = document.createElement('style'); 3407 style.textContent = window.SHOPER_SEARCH_STYLES || ''; 3408 shadowRoot.appendChild(style); 3409 var modalContent = document.createElement('div'); 3410 modalContent.className = 'shoper-search-modal'; 3411 modalContent.innerHTML = window.BeekingWidgetRender.getOverlayHTML(CONFIG); 3412 shadowRoot.appendChild(modalContent); 3413 overlayEl.appendChild(shadowHost); 3414 document.body.appendChild(overlayEl); 3415 applyMotionModeState(); 3416 applyOverlaySurface('fullscreen'); 3417 setModalVisible(false); 3418 inputEl = shadowRoot.querySelector('.shoper-search-main-input'); 3419 resultsEl = shadowRoot.querySelector('.shoper-search-results'); 3420 sidebarEl = shadowRoot.querySelector('.shoper-search-sidebar'); 3421 compactViewBtn = shadowRoot.querySelector('.shoper-card-view-btn[data-view="compact"]'); 3422 largeViewBtn = shadowRoot.querySelector('.shoper-card-view-btn[data-view="large"]'); 3423 xlargeViewBtn = shadowRoot.querySelector('.shoper-card-view-btn[data-view="xlarge"]'); 3424 inputEl.addEventListener('focus', function () { isOverlayInputFocused = true; }); 3425 inputEl.addEventListener('blur', function () { isOverlayInputFocused = false; }); 3426 if (compactViewBtn) compactViewBtn.addEventListener('click', function () { setCardViewMode('compact'); }); 3427 if (largeViewBtn) largeViewBtn.addEventListener('click', function () { setCardViewMode('large'); }); 3428 if (xlargeViewBtn) xlargeViewBtn.addEventListener('click', function () { setCardViewMode('xlarge'); }); 3429 applyCardViewMode(); 3430 3431 var mobileFilterBtn = shadowRoot.querySelector('.shoper-mobile-filter-btn'); 3432 var mobileFilterOverlay = shadowRoot.querySelector('.shoper-mobile-filter-overlay'); 3433 var mobileFilterContent = shadowRoot.querySelector('.shoper-mobile-filter-content'); 3434 var mobileFilterClose = shadowRoot.querySelector('.shoper-mobile-filter-close'); 3435 var mobileFilterApply = shadowRoot.querySelector('.shoper-mobile-filter-appl
3435y'); 3436 var filterCountBadge = shadowRoot.querySelector('.shoper-filter-count-badge'); 3437 3438 function populateMobileFilters() { 3439 mobileFilterContent.innerHTML = sidebarEl.innerHTML; 3440 mobileFilterContent.querySelectorAll('.category-filter').forEach(function (cb) { 3441 cb.checked = state.filters.categories.includes(cb.value); 3442 }); 3443 mobileFilterContent.querySelectorAll('.producer-filter').forEach(function (cb) { 3444 cb.checked = state.filters.producers.includes(cb.value); 3445 }); 3446 var minSlider = mobileFilterContent.querySelector('#shoper-range-min'); 3447 var maxSlider = mobileFilterContent.querySelector('#shoper-range-max'); 3448 var minInput = mobileFilterContent.querySelector('#shoper-price-min-input'); 3449 var maxInput = mobileFilterContent.querySelector('#shoper-price-max-input'); 3450 var rangeMax = state.maxPriceInResults || 500; 3451 if (minSlider) minSlider.value = state.filters.minPrice || 0; 3452 if (maxSlider) maxSlider.value = state.filters.maxPrice || rangeMax; 3453 if (minInput) minInput.value = state.filters.minPrice || 0; 3454 if (maxInput) maxInput.value = state.filters.maxPrice || rangeMax; 3455 mobileFilterContent.querySelectorAll('.shoper-filter-group').forEach(function (group) { 3456 group.classList.add('collapsed'); 3457 var title = group.querySelector('.shoper-filter-title'); 3458 if (!title) return; 3459 var content = document.createElement('div'); 3460 content.className = 'shoper-filter-group-content'; 3461 var contentInner = document.createElement('div'); 3462 contentInner.className = 'shoper-filter-group-content-inner'; 3463 while (title.nextSibling) contentInner.appendChild(title.nextSibling); 3464 content.appendChild(contentInner); 3465 group.appendChild(content); 3466 title.addEventListener('click', function () { 3467 group.classList.toggle('collapsed'); 3468 }); 3469 }); 3470 runtimeMethods.attachSidebarListeners(state.maxPriceInResults || 500, mobileFilterContent); 3471 } 3472 3473 window.onFiltersLoaded = function () { 3474 if (mobileFilterOverlay.classList.contains('active')) populateMobileFilters(); 3475 }; 3476 3477 mobileFilterBtn.addEventListener('click', function () { 3478 if (!state.filtersLoaded) { 3479 mobileFilterContent.innerHTML = '<div style="display: flex; align-items: center; justify-content: center; height: 100%; color: #6b7280;">Åadowanie filtrów...</div>'; 3480 } else { 3481 populateMobileFilters(); 3482 } 3483 mobileFilterOverlay.classList.add('active'); 3484 }); 3485 mobileFilterClose.addEventListener('click', function () { 3486 mobileFilterOverlay.classList.remove('active'); 3487 }); 3488 mobileFilterApply.addEventListener('click', function () { 3489 mobileFilterOverlay.classList.remove('active'); 3490 }); 3491 3492 window.updateMobileFilterBadge = function () { 3493 var count = state.filters.categories.length + 3494 state.filters.producers.length + 3495 (state.filters.minPrice > 0 ? 1 : 0) + 3496 (state.filters.maxPrice !== null && state.filters.maxPrice < state.maxPriceInResults ? 1 : 0); 3497 if (count > 0) { 3498 filterCountBadge.textContent = count; 3499 filterCountBadge.style.display = 'flex'; 3500 } else { 3501 filterCountBadge.style.display = 'none'; 3502 } 3503 }; 3504 3505 shadowRoot.querySelector('.shoper-search-close').addEventListener('click', closeOverlay); 3506 inputEl.addEventListener('keydown', function (e) { 3507 if (e.key === 'Enter' && isPreviewMode && !isMobile()) { 3508 expandToFullMode(); 3509 } else if (e.key === 'Escape') { 3510 e.preventDefault(); 3511 closeOverlay(); 3512 } 3513 }); 3514 document.addEventListener('keydown', function (e) { 3515 if (e.key === 'Enter' && isPreviewMode && !isMobile() && overlayEl && overlayEl.style.visibility === 'visible') { 3516 expandToFullMode(); 3517 } else if (e.key === 'Escape' && overlayEl && overlayEl.style.visibility === 'visible') { 3518 e.preventDefault(); 3519 closeOverlay(); 3520 } 3521 }); 3522 3523 var debouncedSearch = (function debounce(func, wait) { 3524 var timeout; 3525 return function () { 3526 var args = arguments; 3527 clearTimeout(timeout); 3528 timeout = setTimeout(function () { 3529 func.apply(this, args); 3530 }, wait); 3531 }; 3532 })(function (value) { 3533 if (value && value.length >= 2) { 3534 if (isPreviewMode && sidebarEl) runtimeMethods.renderPreviewSidebar(false); 3535 runtimeMethods.performSearch(value); 3536 } else if (!value || value.length === 0) { 3537 if (isPreviewMode) runtimeMethods.renderTopProducts(); 3538 else runtimeMethods.renderEmptyState('Type at least 2 characters...'); 3539 } else { 3540 if (isPreviewMode && sidebarEl) runtimeMethods.renderPreviewSidebar(false); 3541 runtimeMethods.renderEmptyState('Wpisz jeszcze ' + (2 - value.length) + ' znak(i)...'); 3542 } 3543 }, 300); 3544 3545 inputEl.addEventListener('input', function (e) { 3546 debouncedSearch(e.target.value); 3547 }); 3548 3549 overlayEl.addEventListener('click', function (e) { 3550 var path = e.composedPath(); 3551 var clickedInsideModal = path.some(function (node) { 3552 return node.classList && node.classList.contains('shoper-search-modal'); 3553 }); 3554 if (!clickedInsideModal) closeOverlay(); 3555 }); 3556 resultsEl.addEventListener('scroll', runtimeMethods.handleScroll); 3557 resultsEl.addEventListener('click', function (e) { 3558 var card = e.target.closest('.shoper-product-card'); 3559 if (!card) return; 3560 var productId = card.getAttribute('data-product-id'); 3561 var product = state.results.find(function (item) { 3562 return String(item.id || item.product_id) === String(productId); 3563 }); 3564 if (!product) { 3565 product = state.relatedProducts.find(function (item) { 3566 return String(item.id || item.product_id) === String(productId); 3567 }); 3568 } 3569 if (product) runtimeMethods.trackClick(product); 3570 }); 3571 } 3572 3573 function attachListeners() { 3574 document.addEventListener('focusin', function (e) { 3575 if (e.target.matches(CONFIG.selectors.input) && !isOverlayInputFocused && !isOverlayOpen && !isOverlayClosing && isMobile()) { 3576 openOverlay(); 3577 if (e.target.value) { 3578 inputEl.value = e.target.value; 3579 runtimeMethods.performSearch(e.target.value); 3580 } 3581 } 3582 }); 3583 if (CONFIG.disableFullpage) return; 3584 document.addEventListener('focusin', function (e) { 3585 if (e.target.matches(CONFIG.selectors.input) && !isOverlayInputFocused && !isOverlayOpen && !isOverlayClosing && !isMobile()) { 3586 openPreviewMode(); 3587 if (e.target.value) { 3588 inputEl.value = e.target.value; 3589 runtimeMethods.performSearch(e.target.value); 3590 } 3591 } 3592 }); 3593 window.addEventListener('resize', (function debounce(func, wait) { 3594 var timeout; 3595 return function () { 3596 clearTimeout(timeout); 3597 timeout = setTimeout(func, wait); 3598 }; 3599 })(function () { 3600 if (isPreviewMode && isMobile()) expandToFullMode(); 3601 }, 150)); 3602 document.addEventListener('keydown', function (e) { 3603 if (e.key === 'Enter' && !isMobile() && e.target.matches(CONFIG.selectors.input) && !isOverlayInputFocused) { 3604 e.preventDefault(); 3605 if (isPreviewMode) expandToFullMode(); 3606 else openOverlay(); 3607 if (e.target.value) { 3608 inputEl.value = e.target.value; 3609 runtimeMethods.performSearch(e.target.value); 3610 } 3611 } 3612 }); 3613 document.addEventListener('submit', function (e) { 3614 var form = e.target; 3615 var searchInput = form.querySelector(CONFIG.selectors.input); 3616 if (searchInput && !isOverlayInputFocused && !isMobile()) { 3617 e.preventDefault(); 3618 if (isPreviewMode) expandToFullMode(); 3619 else openOverlay(); 3620 if (searchInput.value) { 3621 inputEl.value = searchInput.value; 3622 runtimeMethods.performSearch(searchInput.value); 3623 } 3624 } 3625 }); 3626 } 3627 3628 function focusOverlayInput() { 3629 clearTimeout(overlayFocusTimer); 3630 var token = overlayTransitionToken; 3631 overlayFocusTimer = setTimeout(function () { 3632 overlayFocusTimer = null; 3633 if (!inputEl || !isOverlayOpen || isOverlayClosing || token !== overlayTransitionToken) return; 3634 inputEl.focus(); 3635 }, 50); 3636 } 3637 3638 function revealOverlay(mode) { 3639 applyMotionModeState(); 3640 applyOverlaySurface(mode); 3641 overlayEl.style.visibility = 'visible'; 3642 setModalVisible(false); 3643 requestAnimationFrame(function () { 3644 if (!overlayEl || !isOverlayOpen || isOverlayClosing) return; 3645 overlayEl.style.opacity = '1'; 3646 setModalVisible(true); 3647 }); 3648 } 3649 3650 function openPreviewMode() { 3651 if (!overlayEl) return; 3652 if (isMobile()) { 3653 openOverlay(); 3654 return; 3655 } 3656 clearOverlayTimers(); 3657 overlayTransitionToken++; 3658 isOverlayOpen = true; 3659 isOverlayClosing = false; 3660 isPreviewMode = true; 3661 revealOverlay('preview'); 3662 runtimeMethods.trackPreviewOpen(inputEl ? inputEl.value : ''); 3663 shadowHost.classList.add('preview-mode'); 3664 updateURLState(); 3665 var currentValue = inputEl ? inputEl.value.trim() : ''; 3666 if (!currentValue) { 3667 state.query = ''; 3668 state.results = []; 3669 if (state.topDataLoaded) runtimeMethods.renderTopProducts(); 3670 else if (!state.topDataLoading) runtimeMethods.fetchTopData(); 3671 else runtimeMethods.renderTopProducts(); 3672 } else if (state.topDataLoaded) { 3673 runtimeMethods.renderPreviewSidebar(false); 3674 } 3675 focusOverlayInput(); 3676 document.body.style.overflow = 'hidden'; 3677 } 3678 3679 function expandToFullMode() { 3680 if (!overlayEl) return; 3681 isPreviewMode = false; 3682 isOverlayOpen = true; 3683 isOverlayClosing = false; 3684 shadowHost.classList.remove('preview-mode'); 3685 applyOverlaySurface('fullscreen'); 3686 if (!state.filtersLoaded && !state.loadingFilters) { 3687 if (sidebarEl) { 3688 sidebarEl.innerHTML = '<div class="shoper-sidebar-loading"><div class="shoper-loading-spinner"></div><span>Åadowanie filtrów...</span></div>'; 3689 } 3690 runtimeMethods.fetchFilters(); 3691 } else if (state.filtersLoaded && sidebarEl) { 3692 runtimeMethods.renderSidebar(); 3693 } 3694 runtimeMethods.trackFullscreenOpen(state.query || (inputEl ? inputEl.value : '')); 3695 } 3696 3697 function openOverlay() { 3698 if (!overlayEl) return; 3699 clearOverlayTimers(); 3700 overlayTransitionToken++; 3701 isOverlayOpen = true; 3702 isOverlayClosing = false; 3703 isPreviewMode = false; 3704 shadowHost.classList.remove('preview-mode'); 3705 revealOverlay('fullscreen'); 3706 if (!state.filtersLoaded && !state.loadingFilters) runtimeMethods.fetchFilters(); 3707 runtimeMethods.trackFullscreenOpen(state.query || (inputEl ? inputEl.value : '')); 3708 updateURLState(); 3709 focusOverlayInput(); 3710 document.body.style.overflow = 'hidden'; 3711 } 3712 3713 function closeOverlay(skipUrlClear) { 3714 if (!overlayEl || (!isOverlayOpen && overlayEl.style.visibility !== 'visible' && !isPreviewMode)) return; 3715 clearOverlayTimers(); 3716 overlayTransitionToken++; 3717 var closeToken = overlayTransitionToken; 3718 isOverlayOpen = false; 3719 isOverlayClosing = true; 3720 isOverlayInputFocused = false; 3721 if (inputEl && document.activeElement === inputEl) inputEl.blur(); 3722 setModalVisible(false); 3723 overlayEl.style.opacity = '0'; 3724 applyOverlaySurface('fullscreen'); 3725 isPreviewMode = false; 3726 document.body.style.overflow = ''; 3727 overlayCloseTimer = setTimeout(function () { 3728 overlayCloseTimer = null; 3729 if (closeToken !== overlayTransitionToken || isOverlayOpen) return; 3730 overlayEl.style.visibility = 'hidden'; 3731 shadowHost.classList.remove('preview-mode'); 3732 isOverlayClosing = false; 3733 }, OVERLAY_TRANSITION_MS); 3734 syncOriginalInputs(); 3735 document.querySelectorAll(CONFIG.selectors.input).forEach(function (input) { input.blur(); }); 3736 if (skipUrlClear !== true) clearURLState(); 3737 } 3738 3739 if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', init); 3740 else init(); 3741 3742 window.BeekingShoperSearchWidget = { 3743 open: function (query) { 3744 if (CONFIG.disableWidget) return; 3745 if (!isInitialize
3745d) init(); 3746 if (query) { 3747 if (inputEl) inputEl.value = query; 3748 runtimeMethods.performSearch(query); 3749 } 3750 openOverlay(); 3751 }, 3752 setConfig: function (newConfig) { 3753 if (!newConfig || typeof newConfig !== 'object') return; 3754 CONFIG = Object.assign({}, CONFIG, newConfig); 3755 if (newConfig.searchMotionMode) CONFIG.searchMotionMode = newConfig.searchMotionMode; 3756 CONFIG.disableWidget = shared.getDisableWidgetFromConfig(CONFIG); 3757 syncMotionMode(); 3758 if (CONFIG.disableWidget) closeOverlayImmediate(); 3759 } 3760 }; 3761 } 3762 3763 window.BeekingWidgetRuntime = { 3764 version: 1, 3765 boot: boot 3766 }; 3767 3768 dispatchReadyEvent(); 3769 })(); 3770</script>
vendor: 1 bytes, line 3770
3770
3771<script> 3772 // ========================================== 3773 // File: widget-shared-snippet.html 3774 // Role: RWD Widget Shared Runtime 3775 // ========================================== 3776 (function () { 3777 if (window.BeekingWidgetShared && window.BeekingWidgetShared.version === 1) { 3778 dispatchReadyEvent(); 3779 return; 3780 } 3781 3782 function dispatchReadyEvent() { 3783 try { 3784 window.dispatchEvent(new CustomEvent('beeking:widget-shared-ready')); 3785 } catch (error) { 3786 var event = document.createEvent('Event'); 3787 event.initEvent('beeking:widget-shared-ready', true, true); 3788 window.dispatchEvent(event); 3789 } 3790 } 3791 3792 function toBoolean(value) { 3793 if (typeof value === 'boolean') return value; 3794 if (value == null) return false; 3795 var normalized = String(value).trim().toLowerCase(); 3796 return normalized === 'true' || normalized === '1'; 3797 } 3798 3799 function getDisableWidgetFromConfig(config) { 3800 if (!config || typeof config !== 'object') return false; 3801 return toBoolean(config.disableWidget) || 3802 toBoolean(config.disable_search) || 3803 toBoolean(config.disableSearch) || 3804 toBoolean(config.disable_fullpage) || 3805 toBoolean(config.disableFullpage); 3806 } 3807 3808 function generateRandomId() { 3809 return Math.random().toString(36).slice(2, 11); 3810 } 3811 3812 function generateClientSessionId() { 3813 return 'session_' + Date.now().toString(36) + '_' + generateRandomId(); 3814 } 3815 3816 function generateSearchId() { 3817 return 'search_' + Date.now().toString(36) + '_' + generateRandomId(); 3818 } 3819 3820 function getWidgetLanguage() { 3821 var lang = document.documentElement.lang || 'pl-PL'; 3822 return lang.replace('-', '_'); 3823 } 3824 3825 function normalizeSearchMotionMode(value) { 3826 var normalized = String(value || 'auto').trim().toLowerCase(); 3827 if (normalized === 'safe' || normalized === 'enhanced') return normalized; 3828 return 'auto'; 3829 } 3830 3831 function prefersReducedMotion() { 3832 try { 3833 return !!(window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches); 3834 } catch (error) { 3835 return false; 3836 } 3837 } 3838 3839 var cachedAutoSearchMotionMode = null; 3840 var labelsMap = new Map(); 3841 3842 function probeEnhancedMotionSupport() { 3843 if (cachedAutoSearchMotionMode) return cachedAutoSearchMotionMode; 3844 3845 var resolvedMode = 'safe'; 3846 3847 try { 3848 if (window.WebGLRenderingContext || window.WebGL2RenderingContext) { 3849 var canvas = document.createElement('canvas'); 3850 var contextOptions = { 3851 failIfMajorPerformanceCaveat: true, 3852 powerPreference: 'high-performance' 3853 }; 3854 var context = canvas.getContext('webgl', contextOptions) || 3855 canvas.getContext('experimental-webgl', contextOptions); 3856 3857 if (context) { 3858 resolvedMode = 'enhanced'; 3859 var loseContext = context.getExtension && context.getExtension('WEBGL_lose_context'); 3860 if (loseContext && typeof loseContext.loseContext === 'function') loseContext.loseContext(); 3861 } 3862 } 3863 } catch (error) { 3864 resolvedMode = 'safe'; 3865 } 3866 3867 cachedAutoSearchMotionMode = resolvedMode; 3868 return resolvedMode; 3869 } 3870 3871 function resolveSearchMotionMode(config) { 3872 var explicitMode = normalizeSearchMotionMode(config && config.searchMotionMode); 3873 if (explicitMode === 'safe' || explicitMode === 'enhanced') return explicitMode; 3874 if (prefersReducedMotion()) return 'safe'; 3875 return probeEnhancedMotionSupport(); 3876 } 3877 3878 function fetchLabels(config) { 3879 if (!config || !config.uniqueId) return Promise.resolve(); 3880 var url = config.apiUrl + '/api/products/labels-shoper?uniqueId=' + encodeURIComponent(config.uniqueId); 3881 return fetch(url) 3882 .then(function (res) { return res.json(); }) 3883 .then(function (data) { 3884 if (data && Array.isArray(data.labels)) {
3885 data.labels.forEach(function (label) { 3886 if (Array.isArray(label.productIds)) { 3887 label.productIds.forEach(function (pid) { 3888 var id = String(pid); 3889 var list = labelsMap.get(id) || []; 3890 list.push({ 3891 text: label.text, 3892 background: label.backgroundColor, 3893 color: label.textColor, 3894 position: label.position, 3895 fontSize: label.fontSize, 3896 padding: label.padding, 3897 borderColor: label.borderColor, 3898 borderRadius: label.borderRadius 3899 }); 3900 labelsMap.set(id, list); 3901 }); 3902 } 3903 }); 3904 } 3905 }) 3906 .catch(function (err) { 3907 console.error('[Beeking] Failed to fetch labels:', err); 3908 }); 3909 } 3910 3911 function createWidgetConfig(rawConfig) { 3912 var raw = rawConfig || {}; 3913 var runtimeConfig = window.SHOPER_SEARCH_CONFIG; 3914 var isWidgetDisabled = toBoolean(raw.disableSearch) || 3915 toBoolean(raw.legacyDisableWidget) || 3916 getDisableWidgetFromConfig(runtimeConfig); 3917 3918 var config = { 3919 uniqueId: (runtimeConfig && runtimeConfig.uniqueId) || raw.beekingShopId, 3920 disableWidget: isWidgetDisabled, 3921 shopUrl: (runtimeConfig && runtimeConfig.shopUrl) || window.location.origin, 3922 apiUrl: (runtimeConfig && runtimeConfig.apiUrl) || 'https://beeking.io', 3923 endpoint: '/api/products/search-shoper', 3924 filterEndpoint: '/api/products/filter-results', 3925 trackEndpoint: '/api/products/track-click', 3926 trackShoperSearchEndpoint: '/api/products/track-shoper-search', 3927 trackFullscreenOpenEndpoint: '/api/products/track-fullscreen-open', 3928 trackPreviewOpenEndpoint: '/api/products/track-preview-open', 3929 categoriesEndpoint: '/api/products/shoper-categories', 3930 producersEndpoint: '/api/products/shoper-producers', 3931 topDataEndpoint: '/api/shoper/top-data', 3932 limit: 30, 3933 minQueryLengthForFilter: 5, 3934 showUnavailable: toBoolean(raw.showUnavailable), 3935 showStockInResults: toBoolean(raw.showStockInResults), 3936 disableFullpage: toBoolean(raw.disableFullpage), 3937 searchMotionMode: normalizeSearchMotionMode((runtimeConfig && runtimeConfig.searchMotionMode) || raw.searchMotionMode), 3938 selectors: { input: 'input[name="search"]' } 3939 }; 3940 3941 fetchLabels(config); 3942 3943 return { 3944 isWidgetDisabled: isWidgetDisabled, 3945 config: config, 3946 debug: { 3947 disableSearchRaw: raw.disableSearch, 3948 legacyDisableWidgetRaw: raw.legacyDisableWidget, 3949 disableWidgetFromConfig: { 3950 disableWidget: runtimeConfig && runtimeConfig.disableWidget, 3951 disable_search: runtimeConfig && runtimeConfig.disable_search, 3952 disableSearch: runtimeConfig && runtimeConfig.disableSearch, 3953 disable_fullpage: runtimeConfig && runtimeConfig.disable_fullpage, 3954 disableFullpage: runtimeConfig && runtimeConfig.disableFullpage 3955 }, 3956 disableWidgetParsed: isWidgetDisabled, 3957 disableFullpageRaw: raw.disableFullpage, 3958 disableFullpageParsed: toBoolean(raw.disableFullpage), 3959 } 3960 }; 3961 } 3962 3963 function normalizeShoperCollection(value) { 3964 if (!value) return []; 3965 if (Array.isArray(value)) return value; 3966 if (value.list && Array.isArray(value.list)) return value.list; 3967 if (typeof value === 'object') return Object.values(value); 3968 return []; 3969 } 3970 3971 function pushUniqueEntity(target, seen, entity) { 3972 if (!entity || (entity.id == null && !entity.name)) return; 3973 var id = entity.id != null ? String(entity.id).trim() : ''; 3974 var name = entity.name != null ? String(entity.name).trim() : ''; 3975 var key = id || name; 3976 if (!key || seen.has(key)) return; 3977 seen.add(key); 3978 target.push({ id: id, name: name }); 3979 } 3980 3981 function extractShoperSearchSummary(data) { 3982 var rawProducts = []; 3983 if (data && data.products && data.products.list && Array.isArray(data.products.list)) rawProducts = data.products.list; 3984 else if (Array.isArray(data)) rawProducts = data; 3985 else if (data && data.products) rawProducts = normalizeShoperCollection(data.products); 3986 else if (data && data.results) rawProducts = normalizeShoperCollection(data.results); 3987 else if (data && data.items) rawProducts = normalizeShoperCollection(data.items); 3988 3989 var products = []; 3990 var productSeen = new Set();
3991 rawProducts.forEach(function (product) { 3992 if (!product || typeof product !== 'object') return; 3993 var productId = product.product_id != null ? product.product_id : product.id; 3994 if (productId == null) return; 3995 var normalizedId = String(productId).trim(); 3996 if (!normalizedId || productSeen.has(normalizedId)) return; 3997 productSeen.add(normalizedId); 3998 products.push({ id: normalizedId, product_id: normalizedId, title: String(product.name || product.title || '').trim() }); 3999 }); 4000 4001 var categories = []; 4002 var categorySeen = new Set(); 4003 normalizeShoperCollection(data && data.categories).forEach(function (category) { 4004 if (!category || typeof category !== 'object') return; 4005 pushUniqueEntity(categories, categorySeen, { 4006 id: category.category_id != null ? category.category_id : category.id, 4007 name: category.name || category.title 4008 }); 4009 }); 4010 4011 var producers = []; 4012 var producerSeen = new Set(); 4013 normalizeShoperCollection(data && data.producers).forEach(function (producer) { 4014 if (!producer || typeof producer !== 'object') return; 4015 pushUniqueEntity(producers, producerSeen, { 4016 id: producer.producer_id != null ? producer.producer_id : producer.id, 4017 name: producer.name || producer.title 4018 }); 4019 }); 4020 4021 return { 4022 products: products, 4023 categories: categories, 4024 producers: producers, 4025 productsCount: products.length, 4026 categoriesCount: categories.length, 4027 producersCount: producers.length 4028 }; 4029 } 4030 4031 window.BeekingWidgetShared = { 4032 version: 1, 4033 labelsMap: labelsMap, 4034 toBoolean: toBoolean, 4035 getDisableWidgetFromConfig: getDisableWidgetFromConfig, 4036 generateClientSessionId: generateClientSessionId, 4037 generateSearchId: generateSearchId, 4038 getWidgetLanguage: getWidgetLanguage, 4039 normalizeSearchMotionMode: normalizeSearchMotionMode, 4040 resolveSearchMotionMode: resolveSearchMotionMode, 4041 createWidgetConfig: createWidgetConfig, 4042 extractShoperSearchSummary: extractShoperSearchSummary 4043 }; 4044 4045 dispatchReadyEvent(); 4046 })(); 4047</script>
vendor: 1 bytes, line 4047
4047
4048<script> 4049 // ========================================== 4050 // File: snippet-render.html 4051 // Role: RWD Search Renderer 4052 // ========================================== 4053 (function () { 4054 // Poczekaj na BeekingCore 4055 function waitForCore(callback) { 4056 if (window.BeekingCore) { 4057 callback(); 4058 } else { 4059 setTimeout(function () { waitForCore(callback); }, 10); 4060 } 4061 } 4062 4063 waitForCore(function () { 4064 var Core = window.BeekingCore; 4065 4066 function setupClickTracking(searchContent) { 4067 var productLinks = searchContent.querySelectorAll('.beeking-product-link'); 4068 productLinks.forEach(function (link) { 4069 link.addEventListener('click', function (event) { 4070 try { 4071 var productItem = link.closest('.beeking-product-item'); 4072 if (!productItem) return; 4073 4074 var trackingDataStr = productItem.getAttribute('data-beeking-tracking'); 4075 if (!trackingDataStr) return; 4076 4077 var trackingData = JSON.parse(trackingDataStr.replace(/'/g, "'")); 4078 4079 // Zbierz top 10 ID z aktywnych wynikow wyszukiwania 4080 var top10Ids = []; 4081 var allItems = searchContent.querySelectorAll('.beeking-product-item'); 4082 for (var i = 0; i < allItems.length && top10Ids.length < 10; i++) { 4083 var itemStr = allItems[i].getAttribute('data-beeking-tracking'); 4084 if (itemStr) { 4085 var itemData = JSON.parse(itemStr.replace(/'/g, "'")); 4086 if (itemData && itemData.product && itemData.product.id) { 4087 top10Ids.push(String(itemData.product.id)); 4088 } 4089 } 4090 } 4091 4092 Core.trackProductClick(trackingData.query, trackingData.product, { 4093 shopUrl: Core.currentShopUrl(), 4094 topResultsProductIds: top10Ids, 4095 searchId: trackingData.searchId || '' 4096 }); 4097 } catch (err) { 4098 console.warn('[Beeking] Click tracking error:', err); 4099 } 4100 }); 4101 }); 4102 4103 var categoryPills = searchContent.querySelectorAll('.beeking-category-pill'); 4104 categoryPills.forEach(function (pill) { 4105 pill.addEventListener('click', function (event) { 4106 try { 4107 var categoryId = pill.getAttribute('data-category-id'); 4108 var categoryName = pill.getAttribute('data-category-name'); 4109 4110 if (categoryId || categoryName) { 4111 var query = ''; 4112 var searchInput = searchContent.closest('.search'); 4113 if (searchInput) { 4114 var input = searchInput.querySelector('.search__input[name="search"]'); 4115 if (input) { 4116 query = Core.normalizePhrase(input.value); 4117 } 4118 } 4119 4120 Core.trackCategoryClick(query, { 4121 id: categoryId || '', 4122 name: categoryName || '' 4123 }, { 4124 shopUrl: Core.currentShopUrl(), 4125 searchId: (Core.findInputContextBySearchContent(searchContent) || {}).searchId || '' 4126 }); 4127 } 4128 } catch (err) { 4129 console.warn('[Beeking] Category click tracking error:', err); 4130 } 4131 }); 4132 }); 4133 } 4134 4135 function calculateDiscountPercent(regularPrice, promotionPrice) { 4136 try { 4137 var regular = parseFloat(regularPrice); 4138 var promotion = parseFloat(promotionPrice); 4139 if (isNaN(regular) || isNaN(promotion) || regular <= 0 || promotion >= regular) { 4140 return null; 4141 } 4142 var discount = Math.round(((regular - promotion) / regular) * 100); 4143 return discount > 0 ? discount : null; 4144 } catch (e) { 4145 return null; 4146 } 4147 } 4148 4149 function formatPrice(price) { 4150 if (!price) return ''; 4151 if (typeof price === 'string') { 4152 return price; 4153 } 4154 if (typeof price === 'number') { 4155 return price.toFixed(2).replace('.', ',') + ' zÅ'; 4156 } 4157 return String(price); 4158 } 4159 4160 function createProductHTML(product, query, hideStock, searchId) { 4161 var productId = Core.generateProductId(product); 4162 var trackingData = JSON.stringify({ 4163 query: query, 4164 product: { 4165 id: product.id || productId, 4166 product_id: product.product_id || product.id || productId, 4167 title: product.name || product.title 4168 }, 4169 searchId: searchId || '' 4170 }); 4171 4172 var promotionPrice = product.promotionPrice || product.promotion_price || null; 4173 var regularPrice = product.price || ''; 4174 var hasPromotion = promotionPrice && promotionPrice !== regularPrice && promotionPrice !== ''; 4175 4176 var discountBadgeHTML = ''; 4177 var priceHTML = ''; 4178 4179 if (hasPromotion) { 4180 var discountPercent = calculateDiscountPercent(regularPrice, promotionPrice); 4181 if (discountPercent) { 4182 discountBadgeHTML = '<span class="beeking-product-price__badge">-' + discountPercent + '%</span>'; 4183 } else { 4184 discountBadgeHTML = '<span class="beeking-product-price__badge">Promocja</span>'; 4185 } 4186 4187 priceHTML = 4188 '<span class="beeking-product-price__previous" style="text-decoration: line-through; color: #9ca3af; font-size: 0.85em; font-weight: 500; margin-right: 6px;"><s>' + formatPrice(regularPrice) + '</s></span> ' + 4189 '<span class="search__result-item_active beeking-product-price__current" style="color: #dc2626; font-weight: 700; font-size: 1.1em;">' + formatPrice(promotionPrice) + '</span>'; 4190 } else { 4191 priceHTML = '<span class="search__result-item_active beeking-product-price__current" style="color: #333; font-weight: 700; font-size: 1rem;">' + formatPrice(regularPrice) + '</span>'; 4192 } 4193 4194 var availabilityHTML = ''; 4195 if (product.availability_status && Core.shouldShowStockInfo && !hideStock) { 4196 availabilityHTML = '<span class="search__result-note-item beeking-product-availability">' + product.availability_status + '</span>'; 4197 } 4198 4199 var labelsHTML = ''; 4200 var containerStyle = ''; 4201 if (Core.labelsMap) { 4202 var productLabels = Core.labelsMap.get(String(product.id)) || []; 4203 var displayLabels = productLabels.slice(0, 3); 4204 4205 // Use first label as source of truth for unified styles (except colors) 4206 var normalizeCssValue = function (value, defaultValue, unit) { 4207 if (value === undefined || value === null || value === '') return defaultValue || ''; 4208 if (typeof value === 'number') return value + (unit || ''); 4209 4210 var stringValue = String(value).trim(); 4211 if (!stringValue) return defaultValue || ''; 4212
4213 if (unit && /^-?\d+(\.\d+)?$/.test(stringValue)) { 4214 return stringValue + unit; 4215 } 4216 4217 return stringValue; 4218 }; 4219 4220 var firstLabel = displayLabels[0] || {}; 4221 var unifiedFS = normalizeCssValue(firstLabel.fontSize, '', 'px'); 4222 var unifiedPadding = normalizeCssValue(firstLabel.padding, '', 'px'); 4223 var unifiedBR = normalizeCssValue(firstLabel.borderRadius, '6px', 'px'); 4224 4225 displayLabels.forEach(function (label) { 4226 var itemStyle = ''; 4227 if (label.background) itemStyle += 'background-color:' + label.background + ';'; 4228 if (label.color) itemStyle += 'color:' + label.color + ';'; 4229 if (label.borderColor) itemStyle += 'border: 1px solid ' + label.borderColor + ';'; 4230 4231 // Unified styles 4232 if (unifiedFS) itemStyle += 'font-size:' + unifiedFS + ';'; 4233 if (unifiedPadding) itemStyle += 'padding:' + unifiedPadding + ';'; 4234 if (unifiedBR) itemStyle += 'border-radius:' + unifiedBR + ';'; 4235 4236 labelsHTML += '<span class="beeking-product-label-badge" style="' + itemStyle + '">' + label.text + '</span>'; 4237 }); 4238 4239 // Also update discount badge style if labels exist 4240 if (displayLabels.length > 0) { 4241 var discountStyle = 'box-sizing:border-box;'; 4242 if (unifiedFS) discountStyle += 'font-size:' + unifiedFS + ';'; 4243 if (unifiedPadding) discountStyle += 'padding:' + unifiedPadding + ';'; 4244 if (unifiedBR) discountStyle += 'border-radius:' + unifiedBR + ';'; 4245 4246 // Inject unified style into the existing discountBadgeHTML if it exists 4247 if (discountBadgeHTML) { 4248 discountBadgeHTML = discountBadgeHTML.replace('class="beeking-product-price__badge"', 'class="beeking-product-price__badge" style="' + discountStyle + '"'); 4249 } 4250 } 4251 } 4252 4253 return '<li class="search__list-item beeking-product-item" data-beeking-tracking=\'' + trackingData.replace(/'/g, ''') + '\'>' + 4254 '<div class="beeking-labels-container">' + 4255 discountBadgeHTML + 4256 labelsHTML + 4257 '</div>' + 4258 '<a data-search-result-type="Product" href="' + (product.url || '') + '" class="search__result-link js__search-result-link beeking-product-link">' + 4259 '<div class="search__result-icon">' + 4260 '<img src="' + (product.imgWebp || product.img || '') + '" alt="' + (product.name || '') + '">' + 4261 '</div>' + 4262 '<div class="search__result-content">' + 4263 '<div class="search__result-title">' + 4264 '<h5 class="search__result-title-item">' + (product.name || '') + '</h5>' + 4265 '</div>' + 4266 '<div class="search__result-note">' + 4267 '<div class="search__result-note-item beeking-product-price" style="display: flex; flex-wrap: wrap; align-items: baseline;">' + priceHTML + '</div>' + 4268 availabilityHTML + 4269 '</div>' + 4270 '</div>' + 4271 '</a>' + 4272 '</li>'; 4273 } 4274 4275 function createSectionHeader(phrase, aiState) { 4276 var aiIndicator = ''; 4277 4278 if (aiState === 'loading') { 4279 aiIndicator = '<span id="ai-filter-indicator" style="color: #6c757d; font-size: 11px; font-weight: normal; opacity: 0.7; margin-left: 8px;">' + 4280 '<span class="ai-spinner" style="display: inline-block; width: 10px; height: 10px; border: 1px solid #6c757d; border-top: 1px solid transparent; border-radius: 50%; animation: spin 1s linear infinite; margin-right: 3px;"></span>' + 4281 'AI...' + 4282 '</span>'; 4283 } else if (aiState === 'completed') { 4284 aiIndicator = '<span style="color: #28a745; font-size: 11px; font-weight: normal; opacity: 0.8; margin-left: 8px;">â AI</span>'; 4285 } 4286 4287 return '<h3 class="search__section-head search__section-head_sticky search__section-head_line">' + 4288 'Wyniki dla: ' + phrase + aiIndicator + 4289 '</h3>'; 4290 } 4291 4292 function createCategoriesHTML(categories, query, baseUrl) { 4293 if (!categories || !Array.isArray(categories) || categories.length === 0) { 4294 return ''; 4295 } 4296 4297 var langCode = Core.getCurrentLang().split('_')[0]; 4298 4299 var pills = categories.slice(0, 3).map(function (cat) { 4300 var name = cat.name || ''; 4301 var categoryId = cat.id || ''; 4302 var categoryPath = categoryId ? '/' + langCode + '/c/a/' + categoryId : Core.getSearchPageUrl(query); 4303 var url = cat.url || (baseUrl ? baseUrl + categoryPath : categoryPath); 4304 4305 var escapedName = name.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"'); 4306 var escapedCategoryId = (categoryId + '').replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"'); 4307 var escapedUrl = url.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"'); 4308 4309 return '<a href="' + escapedUrl + '" class="beeking-category-pill" data-category-id="' + escapedCategoryId + '" data-category-name="' + escapedName + '">' + 4310 '<svg class="beeking-category-pill__icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">' + 4311 '<path d="M2 4.5A2.5 2.5 0 014.5 2h2.879a2.5 2.5 0 011.767.732l.732.732A1.5 1.5 0 0010.939 4H15.5A2.5 2.5 0 0118 6.5v8a2.5 2.5 0 01-2.5 2.5h-11A2.5 2.5 0 012 14.5v-10z" />' + 4312 '</svg>' + 4313 '<span class="beeking-category-pill__text">' + escapedName + '</span>' + 4314 '<svg class="beeking-category-pill__arrow" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">' + 4315 '<path fill-rule="evenodd" d="M7.21 14.77a.75.75 0 01.02-1.06L11.168 10 7.23 6.29a.75.75 0 111.04-1.08l4.5 4.25a.75.75 0 010 1.08l-4.5 4.25a.75.75 0 01-1.06-.02z" clip-rule="evenodd" />' + 4316 '</svg>' + 4317 '</a>'; 4318 }).join(''); 4319 4320 return '<div class="beeking-matched-categories" data-role="matched-categories">' + 4321 '<div class="beeking-matched-categories__pills">' + pills + '</div>' + 4322 '</div>'; 4323 } 4324 4325 function mapProductsForAI(products) { 4326 if (!Array.isArray(products)) { 4327 return []; 4328 } 4329 return products.map(function (p) { 4330 var categoryName = ''; 4331 if (p.category) { 4332 categoryName = (typeof p.category === 'object') ? (p.category.name || '') : p.category; 4333 } else if (p.category_name) { 4334 categoryName = p.category_name; 4335 } 4336 4337 var brand = p.producer_name || ''; 4338 if (!brand && p.attributes && p.attributes.producer_name) { 4339 brand = p.attributes.producer_name; 4340 } 4341 4342 var attributesString = ''; 4343 if (p.attributes && typeof p.attributes === 'object') { 4344 try { 4345 var keys = Object.keys(p.attributes); 4346 var attrPairs = []; 4347 for (var i = 0; i < keys.length; i++) { 4348 var key = keys[i]; 4349 var value = p.attributes[key]; 4350 if (value !== undefined && value !== null) { 4351 if (Array.isArray(value)) { 4352 attrPairs.push(key + ':' + value.join('|')); 4353 } else { 4354 attrPairs.push(key + ':' + value); 4355 } 4356 } 4357 } 4358 attributesString = attrPairs.join(','); 4359 } catch (e) { 4360 attributesString = ''; 4361 } 4362 } 4363 4364 var id = String(p.id || p.product_id || ''); 4365 4366 var result = { 4367 id: id, 4368 nazwa: p.name || '', 4369 kategoria: categoryName, 4370 brand: brand, 4371 tags: p.tags || '', 4372 price: p.price || '', 4373 regular_price: p.price || '', 4374 sale_price: p.promotion_price || '', 4375 attributes: attributesString, 4376 sku: p.product_code || p.sku || p.code || '', 4377 semantic_summary: p.semantic_summary || '', 4378 sparse_keywords: p.sparse_keywords || '', 4379 use_context: p.use_context || '', 4380 colors: p.colors || [], 4381 materials: p.materials || [] 4382 }; 4383 4384 if (p.description && p.description.trim() !== '') { 4385 result.description = p.description; 4386 } 4387 4388 return result; 4389 }); 4390 } 4391 4392 function removeAIIndicator() { 4393 var indicator = document.getElementById('ai-filter-indicator'); 4394 if (indicator) indicator.style.display = 'none'; 4395 } 4396 4397 function parseAIResponseNumber(value) { 4398 if (typeof value === 'number' && isFinite(value)) { 4399 return value; 4400 } 4401 if (typeof value === 'string') { 4402 var parsed = parseFloat(value); 4403 if (isFinite(parsed)) { 4404 return parsed; 4405 } 4406 } 4407 return null; 4408 } 4409 4410 function getAIProductScore(product) { 4411 if (!product || typeof product !== 'object') { 4412 return null; 4413 } 4414 4415 var finalScore = parseAIResponseNumber(product.relevantScoreBreakdown && product.relevantScoreBreakdown.finalScore); 4416 if (finalScore !== null) { 4417 return finalScore; 4418 } 4419 4420 return parseAIResponseNumber(product.relevantScore); 4421 } 4422 4423 function normalizeAIResult(aiResult) { 4424 if (!aiResult || typeof aiResult !== 'object') { 4425 return aiResult; 4426 } 4427 4428 var normalized = Object.assign({}, aiResult); 4429 var filteredProducts = Array.isArray(aiResult.filteredProducts) ? aiResult.filteredProducts.slice() : []; 4430 var relatedProducts = Array.isArray(aiResult.relatedProducts) ? aiResult.relatedProducts.slice() : []; 4431 var hardCutoffThreshold = parseAIResponseNumber(aiResult.hard_cutoff_threshold); 4432 4433 if (hardCutoffThreshold !== null) { 4434 filteredProducts = filteredProducts.filter(function (product) { 4435 var score = getAIProductScore(product); 4436 return score === null || score >= hardCutoffThreshold; 4437 }); 4438 4439 relatedProducts = relatedProducts.filter(function (product) { 4440 var score = getAIProductScore(product); 4441 return score === null || score >= hardCutoffThreshold; 4442 }); 4443 } 4444 4445 normalized.filteredProducts = filteredProducts; 4446 normalized.relatedProducts = relatedProducts; 4447 return normalized; 4448 } 4449 4450 function shouldShowEmptyStateAfterAI(aiResult) { 4451 if (!aiResult || aiResult.success !== true) { 4452 return false; 4453 } 4454 4455 return Array.isArray(aiResult.filteredProducts) && 4456 Array.isArray(aiResult.relatedProducts) && 4457 aiResult.filteredProducts.length === 0 && 4458 aiResult.relatedProducts.length === 0; 4459 } 4460 4461 function renderCachedResults(cached, phrase, searchContent) { 4462 if (!cached.aiResult || !cached.originalJson) { 4463 return; 4464 } 4465 4466 if (!searchContent) { 4467 searchContent = document.querySelector('.search__content'); 4468 } 4469 if (!searchContent) return; 4470 4471 var normalizedAIResult = normalizeAIResult(cached.aiResult); 4472 if (shouldShowEmptyStateAfterAI(normalizedAIResult)) { 4473 showNoResultsMessage(phrase, searchContent); 4474 checkAndFixOverflow(searchContent); 4475 return; 4476 } 4477 4478 var beekingSection = searchContent.querySelector('[data-beeking-section="true"]'); 4479 4480 if (!beekingSection) { 4481 renderFilteredResults(normalizedAIResult, cached.originalJson, phrase, searchContent); 4482 var inputContext = Core.findInputContextBySearchContent(searchContent); 4483 if (inputContext) { 4484 inputContext.hasBeekingResults = true; 4485 inputContext.hasRenderedFallback = false; 4486 } 4487 return; 4488 } 4489 4490 var filteredProducts = normalizedAIResult.filteredProducts || []; 4491 var relatedProducts = normalizedAIResult.relatedProducts || []; 4492 var originalProducts = Object.values(cached.originalJson.results || {}); 4493 var isFallback = cached.originalJson.isFallback === true; 4494 4495 var aiMatchedCategories = Array.isArray(normalizedAIResult.matched_categories) ? normalizedAIResult.matched_categories : []; 4496 var originalMatchedCategories = Array.isArray(cached.originalJson.matched_categories) ? cached.originalJson.matched_categories : []; 4497 var matchedCategories = aiMatchedCategories.length > 0 ? aiMatchedCategories : originalMatchedCategories; 4498 4499 var productsList = ''; 4500 var divider = ''; 4501 var relatedProductsList = ''; 4502 var remainingProductsList = ''; 4503 var inputContext = Core.findInputContextBySearchContent(searchContent); 4504 var searchId = inputContext && inputContext.searchId ? inputContext.searchId : ''; 4505 4506 if (filteredProducts.length === 0) { 4507 var displayedIds = new Set(); 4508 4509 if (Array.isArray(relatedProducts) && relatedProducts.length > 0) {
4510 relatedProducts.forEach(function (rp) { 4511 var originalProduct = originalProducts.find(function (op) { return op.id === rp.id; }); 4512 if (originalProduct) { 4513 relatedProductsList += createProductHTML(originalProduct, phrase, isFallback, searchId); 4514 displayedIds.add(rp.id); 4515 } 4516 }); 4517 } 4518 4519 originalProducts.forEach(function (op) { 4520 if (!displayedIds.has(op.id)) { 4521 remainingProductsList += createProductHTML(op, phrase, isFallback, searchId); 4522 } 4523 }); 4524 4525 if (relatedProductsList && remainingProductsList) { 4526 divider = '<li class="search__list-item" style="border-top: 1px solid #e0e0e0; margin: 10px 0; padding: 0;"></li>'; 4527 } 4528 4529 productsList = relatedProductsList + divider + remainingProductsList; 4530 } else { 4531 filteredProducts.forEach(function (fp) { 4532 var originalProduct = originalProducts.find(function (op) { return op.id === fp.id; }); 4533 if (originalProduct) { 4534 productsList += createProductHTML(originalProduct, phrase, isFallback, searchId); 4535 } 4536 }); 4537 4538 if (filteredProducts.length > 0 && relatedProducts.length > 0) { 4539 divider = '<li class="search__list-item" style="border-top: 1px solid #e0e0e0; margin: 10px 0; padding: 0;"></li>'; 4540 4541 relatedProducts.forEach(function (rp) { 4542 var originalProduct = originalProducts.find(function (op) { return op.id === rp.id; }); 4543 if (originalProduct) { 4544 relatedProductsList += createProductHTML(originalProduct, phrase, isFallback, searchId); 4545 } 4546 }); 4547 } 4548 } 4549 4550 var finalContent = productsList; 4551 if (filteredProducts.length > 0 && relatedProducts.length > 0) { 4552 finalContent = productsList + divider + relatedProductsList; 4553 } 4554 4555 beekingSection.innerHTML = createSectionHeader(phrase, 'completed') + '<ul class="search__list">' + finalContent + '</ul>'; 4556 4557 if (matchedCategories.length > 0) { 4558 var baseUrl = ''; 4559 var firstProductWithUrl = originalProducts.find(function (p) { return p.url; }); 4560 if (firstProductWithUrl && firstProductWithUrl.url) { 4561 try { 4562 var urlObj = new URL(firstProductWithUrl.url); 4563 baseUrl = urlObj.origin; 4564 } catch (e) { 4565 baseUrl = ''; 4566 } 4567 } 4568 4569 var existingCategoriesSection = searchContent.querySelector('[data-role="matched-categories"]'); 4570 var newCategoriesHTML = createCategoriesHTML(matchedCategories, phrase, baseUrl); 4571 4572 if (existingCategoriesSection) { 4573 var tempDiv = document.createElement('div'); 4574 tempDiv.innerHTML = newCategoriesHTML; 4575 var newSection = tempDiv.firstElementChild; 4576 if (newSection) { 4577 existingCategoriesSection.parentNode.replaceChild(newSection, existingCategoriesSection); 4578 } 4579 } else if (newCategoriesHTML) { 4580 var searchItemContent = searchContent.querySelector('.search__item_content'); 4581 if (searchItemContent) { 4582 var tempDiv = document.createElement('div'); 4583 tempDiv.innerHTML = newCategoriesHTML; 4584 var newSection = tempDiv.firstElementChild; 4585 if (newSection) { 4586 searchContent.insertBefore(newSection, searchItemContent); 4587 } 4588 } 4589 } 4590 } 4591 4592 if (inputContext) { 4593 inputContext.hasBeekingResults = true; 4594 inputContext.hasRenderedFallback = false; 4595 } 4596 setupClickTracking(searchContent); 4597 checkAndFixOverflow(searchContent); 4598 } 4599 4600 function handleAIFiltering(phrase, products, originalJson, queryId, inputContext) { 4601 if (!inputContext) { 4602 inputContext = { 4603 queryId: Core.getActiveQueryId(), 4604 searchContent: document.querySelector('.search__content') 4605 }; 4606 } 4607 4608 var productsForAI = mapProductsForAI(products); 4609 4610 var matchedCategories = Array.isArray(originalJson && originalJson.matched_categories) 4611 ? originalJson.matched_categories.map(function (cat) { 4612 return { id: cat.id || '', name: cat.name || '' }; 4613 }) 4614 : []; 4615
4616 Core.callAIFilter(phrase, productsForAI, { 4617 shopUrl: Core.currentShopUrl(), 4618 queryId: queryId, 4619 matched_categories: matchedCategories 4620 }).then(function (response) { 4621 if (response.queryId !== inputContext.queryId) { 4622 return; 4623 } 4624 4625 if (response.aborted) { 4626 return; 4627 } 4628 4629 var aiResult = normalizeAIResult(response.result); 4630 4631 if (aiResult && aiResult.success) { 4632 renderFilteredResults(aiResult, originalJson, phrase, inputContext.searchContent); 4633 4634 var key = Core.beekingKey(phrase, Core.DEFAULT_LIMIT, Core.beekingShopId); 4635 Core.finalCache.set(key, { 4636 ts: Date.now(), 4637 originalJson: originalJson, 4638 aiResult: aiResult, 4639 phrase: phrase 4640 }); 4641 } else { 4642 removeAIIndicator(); 4643 } 4644 }).catch(function (err) { 4645 removeAIIndicator(); 4646 }); 4647 } 4648 4649 function showBeekingSpinner(searchContent) { 4650 if (!searchContent) { 4651 searchContent = document.querySelector('.search__content'); 4652 } 4653 if (!searchContent) return; 4654 4655 searchContent.innerHTML = 4656 '<div class="search__item_content">' + 4657 '<div class="search__loading" style="text-align: center; padding: 20px;">' + 4658 '<div class="search__spinner" style="display: inline-block; width: 20px; height: 20px; border: 2px solid #f3f3f3; border-top: 2px solid #3498db; border-radius: 50%; animation: spin 1s linear infinite;"></div>' + 4659 '<p style="margin: 10px 0 0 0; color: #666; font-size: 14px;">Szukam produktów...</p>' + 4660 '</div>' + 4661 '</div>' + 4662 '<style>' + 4663 '@keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } }' + 4664 '</style>'; 4665 checkAndFixOverflow(searchContent); 4666 } 4667 4668 function ensureBeekingSection(searchContent) { 4669 if (!searchContent) return null; 4670 var existing = searchContent.querySelector('[data-beeking-section="true"]'); 4671 if (existing) return existing; 4672 4673 searchContent.innerHTML = 4674 '<div class="search__item_content">' + 4675 '<div class="search__section" data-search-section-name="products" data-beeking-section="true"></div>' + 4676 '</div>'; 4677 4678 return searchContent.querySelector('[data-beeking-section="true"]'); 4679 } 4680 4681 function renderFilteredResults(filteredJson, originalJson, phrase, searchContent) { 4682 if (!searchContent) { 4683 searchContent = document.querySelector('.search__content'); 4684 } 4685 if (!searchContent) return; 4686 4687 var beekingSection = ensureBeekingSection(searchContent); 4688 if (!beekingSection) { 4689 removeAIIndicator(); 4690 return; 4691 } 4692 4693 if (!filteredJson || typeof filteredJson !== 'object' || !originalJson || !originalJson.results || typeof originalJson.results !== 'object') { 4694 removeAIIndicator(); 4695 return; 4696 } 4697 4698 var normalizedAIResult = normalizeAIResult(filteredJson); 4699 if (shouldShowEmptyStateAfterAI(normalizedAIResult)) { 4700 showNoResultsMessage(phrase, searchContent); 4701 checkAndFixOverflow(searchContent); 4702 return; 4703 } 4704 4705 var filteredProducts = (normalizedAIResult && normalizedAIResult.filteredProducts && Array.isArray(normalizedAIResult.filteredProducts)) ? normalizedAIResult.filteredProducts : []; 4706 var relatedProducts = (normalizedAIResult && normalizedAIResult.relatedProducts && Array.isArray(normalizedAIResult.relatedProducts)) ? normalizedAIResult.relatedProducts : []; 4707 4708 var aiMatchedCategories = Array.isArray(normalizedAIResult.matched_categories) ? normalizedAIResult.matched_categories : []; 4709 var originalMatchedCategories = Array.isArray(originalJson.matched_categories) ? originalJson.matched_categories : []; 4710 var matchedCategories = aiMatchedCategories.length > 0 ? aiMatchedCategories : originalMatchedCategories; 4711 var originalProducts = Object.values(originalJson.results || {}); 4712 var isFallback = originalJson.isFallback === true; 4713 var productsList = ''; 4714 var divider = ''; 4715 var relatedProductsList = ''; 4716 var remainingProductsList = ''; 4717 var inputContext = Core.findInputContextBySearchContent(searchContent); 4718 var searchId = inputContext && inputContext.searchId ? inputContext.searchId : ''; 4719 4720 if (!Array.isArray(filteredProducts) || filteredProducts.length === 0) { 4721 var displayedIds = new Set(); 4722 4723 if (Array.isArray(relatedProducts) && relatedProducts.length > 0) {
4724 relatedProducts.forEach(function (rp) { 4725 var originalProduct = Array.isArray(originalProducts) ? originalProducts.find(function (op) { return op.id === rp.id; }) : null; 4726 if (originalProduct) { 4727 relatedProductsList += createProductHTML(originalProduct, phrase, isFallback, searchId); 4728 displayedIds.add(rp.id); 4729 } 4730 }); 4731 } 4732 4733 if (Array.isArray(originalProducts)) { 4734 originalProducts.forEach(function (op) { 4735 if (!displayedIds.has(op.id)) { 4736 remainingProductsList += createProductHTML(op, phrase, isFallback, searchId); 4737 } 4738 }); 4739 } 4740 4741 if (relatedProductsList && remainingProductsList) { 4742 divider = '<li class="search__list-item" style="border-top: 1px solid #e0e0e0; margin: 10px 0; padding: 0;"></li>'; 4743 } 4744 4745 productsList = relatedProductsList + divider + remainingProductsList; 4746 } else { 4747 if (Array.isArray(filteredProducts)) { 4748 filteredProducts.forEach(function (fp) { 4749 var originalProduct = Array.isArray(originalProducts) ? originalProducts.find(function (op) { return op.id === fp.id; }) : null; 4750 if (originalProduct) { 4751 productsList += createProductHTML(originalProduct, phrase, isFallback, searchId); 4752 } 4753 }); 4754 } 4755 4756 if (filteredProducts.length > 0 && relatedProducts.length > 0) { 4757 divider = '<li class="search__list-item" style="border-top: 1px solid #e0e0e0; margin: 10px 0; padding: 0;"></li>'; 4758 4759 if (Array.isArray(relatedProducts)) { 4760 relatedProducts.forEach(function (rp) { 4761 var originalProduct = Array.isArray(originalProducts) ? originalProducts.find(function (op) { return op.id === rp.id; }) : null; 4762 if (originalProduct) { 4763 relatedProductsList += createProductHTML(originalProduct, phrase, isFallback, searchId); 4764 } 4765 }); 4766 } 4767 } 4768 } 4769 4770 var finalContent = productsList; 4771 if (filteredProducts.length > 0 && relatedProducts.length > 0) { 4772 finalContent = productsList + divider + relatedProductsList; 4773 } 4774 4775 beekingSection.innerHTML = createSectionHeader(phrase, 'completed') + '<ul class="search__list">' + finalContent + '</ul>'; 4776 4777 if (matchedCategories.length > 0) { 4778 var baseUrl = ''; 4779 var firstProductWithUrl = originalProducts.find(function (p) { return p.url; }); 4780 if (firstProductWithUrl && firstProductWithUrl.url) { 4781 try { 4782 var urlObj = new URL(firstProductWithUrl.url); 4783 baseUrl = urlObj.origin; 4784 } catch (e) { 4785 baseUrl = ''; 4786 } 4787 } 4788 4789 var existingCategoriesSection = searchContent.querySelector('[data-role="matched-categories"]'); 4790 var newCategoriesHTML = createCategoriesHTML(matchedCategories, phrase, baseUrl); 4791 4792 if (existingCategoriesSection) { 4793 var tempDiv = document.createElement('div'); 4794 tempDiv.innerHTML = newCategoriesHTML; 4795 var newSection = tempDiv.firstElementChild; 4796 if (newSection) { 4797 existingCategoriesSection.parentNode.replaceChild(newSection, existingCategoriesSection); 4798 } 4799 } else if (newCategoriesHTML) { 4800 var searchItemContent = searchContent.querySelector('.search__item_content'); 4801 if (searchItemContent) { 4802 var tempDiv = document.createElement('div'); 4803 tempDiv.innerHTML = newCategoriesHTML; 4804 var newSection = tempDiv.firstElementChild; 4805 if (newSection) { 4806 searchContent.insertBefore(newSection, searchItemContent); 4807 } 4808 } 4809 } 4810 } 4811 4812 var inputContextForResult = Core.findInputContextBySearchContent(searchContent); 4813 if (inputContextForResult) { 4814 inputContextForResult.hasRenderedFallback = false; 4815 } 4816 4817 setupClickTracking(searchContent); 4818 } 4819 4820 function showNoResultsMessage(phrase, searchContent) { 4821 var searchPageUrl = Core.getSearchPageUrl(phrase); 4822
4823 var productCountSelectors = [ 4824 '.search__result-count', 4825 '.search-result-count', 4826 '[data-product-count]', 4827 '.search__count', 4828 '.search-count' 4829 ]; 4830 4831 productCountSelectors.forEach(function (selector) { 4832 var elements = searchContent.querySelectorAll(selector); 4833 elements.forEach(function (el) { 4834 el.style.display = 'none'; 4835 }); 4836 }); 4837 4838 if (searchContent && searchContent.parentElement) { 4839 productCountSelectors.forEach(function (selector) { 4840 var elements = searchContent.parentElement.querySelectorAll(selector); 4841 elements.forEach(function (el) { 4842 el.style.display = 'none'; 4843 }); 4844 }); 4845 } 4846 4847 var noResultsHTML = 4848 '<div class="search__item_content">' + 4849 '<div class="search__section" data-search-section-name="products" data-beeking-section="true">' + 4850 '<h3 class="search__section-head search__section-head_sticky search__section-head_line">' + 4851 'Wyniki dla: ' + phrase + 4852 '</h3>' + 4853 '<ul class="search__list">' + 4854 '<li class="search__list-item">' + 4855 '<div style="padding: 20px; text-align: center;">' + 4856 '<p style="margin: 0 0 15px 0; color: #6c757d; font-size: 14px;">Nie znaleziono produktów dla zapytania "' + phrase + '"</p>' + 4857 '<a href="' + searchPageUrl + '" style="display: inline-block; padding: 10px 20px; background-color: #007bff; color: white; text-decoration: none; border-radius: 4px; font-size: 14px; transition: background-color 0.2s;">' + 4858 'Zobacz wszystkie wyniki wyszukiwania' + 4859 '</a>' + 4860 '</div>' + 4861 '</li>' + 4862 '</ul>' + 4863 '</div>' + 4864 '</div>'; 4865 4866 searchContent.innerHTML = noResultsHTML; 4867 var inputContext = Core.findInputContextBySearchContent(searchContent); 4868 if (inputContext) { 4869 inputContext.hasBeekingResults = true; 4870 inputContext.hasRenderedFallback = false; 4871 } 4872 } 4873 4874 function checkAndFixOverflow(searchContent) { 4875 if (!searchContent) return; 4876 4877 requestAnimationFrame(function () { 4878 var rect = searchContent.getBoundingClientRect(); 4879 var viewportWidth = window.innerWidth || document.documentElement.clientWidth; 4880 4881 if (rect.right > viewportWidth - 10) { 4882 searchContent.classList.add('search__content_right'); 4883 } 4884 }); 4885 } 4886 4887 function renderBeekingResults(response, phrase, inputContext) { 4888 if (response.aborted) { 4889 return; 4890 } 4891 4892 if (!inputContext) { 4893 inputContext = { 4894 queryId: Core.getActiveQueryId(), 4895 searchContent: document.querySelector('.search__content') 4896 }; 4897 } 4898 4899 if (response.queryId !== inputContext.queryId) { 4900 return; 4901 } 4902 4903 var json = response.results; 4904 var searchContent = inputContext.searchContent; 4905 if (!searchContent) return; 4906 4907 if (json && json.error) { 4908 if (inputContext && inputContext.hasRenderedFallback) { 4909 return; 4910 } 4911 showNoResultsMessage(phrase, searchContent); 4912 checkAndFixOverflow(searchContent); 4913 return; 4914 } 4915 4916 if (!json || !json.results || typeof json.results !== 'object' || Object.keys(json.results || {}).length === 0) { 4917 if (inputContext && inputContext.hasRenderedFallback) { 4918 return; 4919 } 4920 if (json && json.isFallback) { 4921 showNoResultsMessage(phrase, searchContent); 4922 checkAndFixOverflow(searchContent); 4923 return; 4924 } 4925 Core.callShoperFallback(phrase, inputContext.queryId, { 4926 cacheKey: Core.beekingKey(phrase, Core.DEFAULT_LIMIT, Core.beekingShopId), 4927 errorMessage: 'Brak wyników z Beeking - próbujÄ fallback' 4928 }).then(function (fallbackResponse) { 4929 renderBeekingResults(fallbackResponse, phrase, inputContext); 4930 }); 4931 return; 4932 } 4933 4934 var arr = Object.values(json.results || {}); 4935 var productsList = ''; 4936 var isFallback = json.isFallback === true; 4937 var searchId = inputContext && inputContext.searchId ? inputContext.searchId : ''; 4938 4939 var matchedCategories = Array.isArray(json.matched_categories) ? json.matched_categories : []; 4940 4941 var baseUrl = ''; 4942 var firstProductWithUrl = arr.find(function (p) { return p.url; });
4943 if (firstProductWithUrl && firstProductWithUrl.url) { 4944 try { 4945 var urlObj = new URL(firstProductWithUrl.url); 4946 baseUrl = urlObj.origin; 4947 } catch (e) { 4948 baseUrl = ''; 4949 } 4950 } 4951 4952 if (Array.isArray(arr)) { 4953 arr.forEach(function (p) { 4954 productsList += createProductHTML(p, phrase, isFallback, searchId); 4955 }); 4956 } 4957 4958 var shouldUseAI = phrase.length >= 3 && !isFallback; 4959 4960 var categoriesHTML = createCategoriesHTML(matchedCategories, phrase, baseUrl); 4961 4962 var productsSection = 4963 '<div class="search__item_content">' + 4964 categoriesHTML + 4965 '<div class="search__section" data-search-section-name="products" data-beeking-section="true">' + 4966 createSectionHeader(phrase, shouldUseAI ? 'loading' : 'none') + 4967 '<ul class="search__list">' + productsList + '</ul>' + 4968 '</div>' + 4969 '</div>'; 4970 4971 searchContent.innerHTML = productsSection; 4972 checkAndFixOverflow(searchContent); 4973 4974 if (inputContext) { 4975 inputContext.hasBeekingResults = true; 4976 inputContext.hasRenderedFallback = isFallback; 4977 } 4978 setupClickTracking(searchContent); 4979 4980 if (shouldUseAI) { 4981 handleAIFiltering(phrase, arr, json, response.queryId, inputContext); 4982 } 4983 } 4984 4985 // Wrapper dla callBeeking - automatyczne renderowanie wyników 4986 var origCallBeeking = Core.callBeeking; 4987 Core.callBeeking = function (query, opts) { 4988 var inputContext = (opts && opts.inputContext) || null; 4989 if (opts) { 4990 opts.onFallbackResponse = function (fallbackResponse) { 4991 renderBeekingResults(fallbackResponse, query, inputContext); 4992 }; 4993 } 4994 return origCallBeeking(query, opts).then(function (response) { 4995 renderBeekingResults(response, query, inputContext); 4996 return response; 4997 }).catch(function (err) { 4998 return null; 4999 }); 5000 }; 5001 5002 // Eksportuj funkcje renderowania 5003 window.BeekingRender = { 5004 renderCachedResults: renderCachedResults, 5005 showBeekingSpinner: showBeekingSpinner, 5006 checkAndFixOverflow: checkAndFixOverflow, 5007 renderBeekingResults: renderBeekingResults, 5008 renderFilteredResults: renderFilteredResults 5009 }; 5010 5011 }); 5012 5013 })(); 5014 5015</script>
5015 5016 5017<style> 5018 /* Beeking Search Override - prosty spinner animation */ 5019 @keyframes spin { 5020 0% { 5021 transform: rotate(0deg); 5022 } 5023 5024 100% { 5025 transform: rotate(360deg); 5026 } 5027 } 5028 5029 /* Matched Categories Pills */ 5030 .beeking-matched-categories { 5031 padding: 8px 12px; 5032 border-bottom: 1px solid #e5e7eb; 5033 background: #fafafa; 5034 } 5035 5036 .beeking-matched-categories__pills { 5037 display: flex; 5038 flex-wrap: wrap; 5039 gap: 8px; 5040 } 5041 5042 .beeking-category-pill { 5043 display: inline-flex; 5044 align-items: center; 5045 gap: 6px; 5046 padding: 6px 12px; 5047 background: white; 5048 border: 1px solid #e5e7eb; 5049 border-radius: 20px; 5050 font-size: 13px; 5051 color: #374151; 5052 text-decoration: none; 5053 transition: all 0.2s ease; 5054 white-space: nowrap; 5055 } 5056 5057 .beeking-category-pill:hover { 5058 background: #f3f4f6; 5059 border-color: #d1d5db; 5060 color: #111827; 5061 } 5062 5063 .beeking-category-pill__icon { 5064 width: 14px; 5065 height: 14px; 5066 color: #9ca3af; 5067 flex-shrink: 0; 5068 } 5069 5070 .beeking-category-pill__text { 5071 flex: 1; 5072 overflow: hidden; 5073 text-overflow: ellipsis; 5074 } 5075 5076 .beeking-category-pill__arrow { 5077 width: 14px; 5078 height: 14px; 5079 color: #9ca3af; 5080 flex-shrink: 0; 5081 transition: transform 0.2s ease; 5082 } 5083 5084 .beeking-category-pill:hover .beeking-category-pill__arrow { 5085 transform: translateX(2px); 5086 } 5087 5088 /* Price badge for promotions */ 5089 .beeking-product-price__badge { 5090 display: inline-block; 5091 background: #dc2626; 5092 color: white; 5093 font-size: 11px; 5094 font-weight: 600; 5095 padding: 2px 6px; 5096 border-radius: 4px; 5097 margin-right: 6px; 5098 } 5099</style>
5100<script> 5101 // ========================================== 5102 // File: widget-render-snippet.html 5103 // Role: RWD Widget Renderer 5104 // ========================================== 5105 (function () { 5106 function calculateDiscountPercent(regularPrice, promotionPrice) { 5107 try { 5108 // Remove 'zÅ', commas to dots, spaces 5109 var cleanRegular = String(regularPrice).replace(/[^0-9.,]/g, '').replace(',', '.'); 5110 var cleanPromo = String(promotionPrice).replace(/[^0-9.,]/g, '').replace(',', '.'); 5111 5112 var regular = parseFloat(cleanRegular); 5113 var promotion = parseFloat(cleanPromo); 5114 5115 if (isNaN(regular) || isNaN(promotion) || regular <= 0 || promotion >= regular) { 5116 return null; 5117 } 5118 var discount = Math.round(((regular - promotion) / regular) * 100); 5119 return discount > 0 ? discount : null; 5120 } catch (e) { 5121 return null; 5122 } 5123 } 5124 5125 function createProductCardHtml(product, showStockInResults) { 5126 var availClass = product.availability_status === 'unavailable' ? 'unavailable' : ''; 5127 var productId = product.id || product.product_id || ''; 5128 var availHtml = ''; 5129 5130 // Promo logic 5131 var promoPrice = product.promotion_price || product.promotionPrice || product.promo_price || null; 5132 var regularPrice = product.price; 5133 5134 // Simple check if promo differs from regular 5135 var isPromo = !!promoPrice && String(promoPrice) !== String(regularPrice); 5136 var priceHtml = ''; 5137 var badgeHtml = ''; 5138 5139 if (isPromo) { 5140 var discount = calculateDiscountPercent(regularPrice, promoPrice); 5141 if (discount) { 5142 badgeHtml = '<div class="shoper-promo-badge">-' + discount + '%</div>'; 5143 } else { 5144 badgeHtml = '<div class="shoper-promo-badge">Promocja</div>'; 5145 } 5146 5147 priceHtml = '<div class="shoper-product-price">' + 5148 '<span class="shoper-price-regular">' + regularPrice + '</span>' + 5149 '<span class="shoper-price-promo">' + promoPrice + '</span>' + 5150 '</div>'; 5151 } else { 5152 priceHtml = '<div class="shoper-product-price">' + regularPrice + '</div>'; 5153 } 5154 5155 if (showStockInResults && product.availability_status) { 5156 availHtml = '<div class="shoper-product-availability ' + availClass + '">' + product.availability_status + '</div>'; 5157 } 5158 5159 var url = product.url || ''; 5160 var hrefAttr = url ? ' href="' + url + '"' : ''; 5161 5162 var labelsHTML = ''; 5163 var shared = window.BeekingWidgetShared; 5164 if (shared && shared.labelsMap) { 5165 var productLabels = shared.labelsMap.get(String(productId)) || []; 5166 var displayLabels = productLabels.slice(0, 3); 5167 5168 // Use first label as source of truth for unified styles (except colors) 5169 var normalizeCssValue = function (value, defaultValue, unit) { 5170 if (value === undefined || value === null || value === '') return defaultValue || ''; 5171 if (typeof value === 'number') return value + (unit || ''); 5172 5173 var stringValue = String(value).trim(); 5174 if (!stringValue) return defaultValue || ''; 5175 5176 if (unit && /^-?\d+(\.\d+)?$/.test(stringValue)) { 5177 return stringValue + unit; 5178 } 5179 5180 return stringValue; 5181 }; 5182 5183 var firstLabel = displayLabels[0] || {}; 5184 var unifiedFS = normalizeCssValue(firstLabel.fontSize, '', 'px'); 5185 var unifiedPadding = normalizeCssValue(firstLabel.padding, '', 'px'); 5186 var unifiedBR = normalizeCssValue(firstLabel.borderRadius, '6px', 'px'); 5187
5188 displayLabels.forEach(function (label) { 5189 var itemStyle = ''; 5190 if (label.background) itemStyle += 'background-color:' + label.background + ';'; 5191 if (label.color) itemStyle += 'color:' + label.color + ';'; 5192 if (label.borderColor) itemStyle += 'border: 1px solid ' + label.borderColor + ';'; 5193 5194 // Unified styles 5195 if (unifiedFS) itemStyle += 'font-size:' + unifiedFS + ';'; 5196 if (unifiedPadding) itemStyle += 'padding:' + unifiedPadding + ';'; 5197 if (unifiedBR) itemStyle += 'border-radius:' + unifiedBR + ';'; 5198 5199 labelsHTML += '<span class="beeking-product-label-badge" style="' + itemStyle + '">' + label.text + '</span>'; 5200 }); 5201 5202 // Also update discount badge style if labels exist 5203 if (displayLabels.length > 0 && badgeHtml) { 5204 var discountStyle = 'box-sizing:border-box;'; 5205 if (unifiedFS) discountStyle += 'font-size:' + unifiedFS + ';'; 5206 if (unifiedPadding) discountStyle += 'padding:' + unifiedPadding + ';'; 5207 if (unifiedBR) discountStyle += 'border-radius:' + unifiedBR + ';'; 5208 5209 badgeHtml = badgeHtml.replace('class="shoper-promo-badge"', 'class="shoper-promo-badge" style="' + discountStyle + '"'); 5210 } 5211 } 5212 5213 return '<a' + hrefAttr + ' class="shoper-product-card" data-product-url="' + url + '" data-product-id="' + productId + '">' + 5214 '<div class="beeking-labels-container">' + 5215 badgeHtml + 5216 labelsHTML + 5217 '</div>' + 5218 '<img src="' + (product.img || '') + '" alt="' + (product.name || '') + '" class="shoper-product-image">' + 5219 '<div class="shoper-product-title">' + (product.name || '') + '</div>' + 5220 availHtml + 5221 '<div class="shoper-product-footer" style="margin-top: auto; display: flex; justify-content: space-between; align-items: center; width: 100%;">' + 5222 priceHtml + 5223 '</div>' + 5224 '</a>'; 5225 } 5226 5227 function renderCategoryTreeHTML(tree, level, state) { 5228 if (!tree) return { html: '', hasChecked: false }; 5229 const keys = Object.keys(tree).sort(); 5230 if (keys.length === 0) return { html: '', hasChecked: false }; 5231 5232 const isRoot = level === 0; 5233 const ulClass = isRoot ? 'shoper-category-tree' : ''; 5234 5235 let htmlParts = []; 5236 let anyChildChecked = false; 5237 5238 keys.forEach(key => { 5239 const node = tree[key]; 5240 5241 const childResult = renderCategoryTreeHTML(node.children, level
5241+ 1, state); 5242 const childrenHtml = childResult.html; 5243 const childrenHaveChecked = childResult.hasChecked; 5244 5245 const isSelfChecked = state.filters.categories.includes(String(node.value)); 5246 const isManuallyExpanded = state.expandedNodes.has(key); 5247 const shouldExpand = isManuallyExpanded || childrenHaveChecked; 5248 5249 const isCheckedOrDescendant = isSelfChecked || childrenHaveChecked; 5250 anyChildChecked = anyChildChecked || isCheckedOrDescendant; 5251 5252 const hasChildren = childrenHtml.length > 0; 5253 5254 var itemHtml = '<li>'; 5255 itemHtml += '<div class="shoper-tree-item">'; 5256 5257 var expandedClass = shouldExpand ? 'expanded' : ''; 5258 5259 if (hasChildren) { 5260 itemHtml += '<span class="shoper-tree-toggle ' + expandedClass + '" data-node-id="' + key + '">â¶</span>'; 5261 } else { 5262 itemHtml += '<span class="shoper-tree-spacer"></span>'; 5263 } 5264 5265 itemHtml += '<label>'; 5266 itemHtml += '<input type="checkbox" class="shoper-filter-checkbox category-filter" value="' + node.value + '"' + (isSelfChecked ? ' checked' : '') + '>'; 5267 itemHtml += node.name; 5268 itemHtml += '</label>'; 5269 itemHtml += '</div>'; 5270 5271 if (hasChildren) { 5272 itemHtml += '<ul class="' + (shouldExpand ? 'expanded' : '') + '">'; 5273 itemHtml += childrenHtml; 5274 itemHtml += '</ul>'; 5275 } 5276 5277 itemHtml += '</li>'; 5278 htmlParts.push(itemHtml); 5279 }); 5280 5281 if (isRoot) { 5282 return { html: '<ul class="' + ulClass + '">' + htmlParts.join('') + '</ul>', hasChecked: anyChildChecked }; 5283 } 5284 5285 return { html: htmlParts.join(''), hasChecked: anyChildChecked }; 5286 } 5287 5288 function getSidebarHTML(state) { 5289 var producers = state.allProducers || []; 5290 var content = []; 5291 var tree = state.allCategories || {}; 5292 var hasCategories = Object.keys(tree).length > 0; 5293 5294 if (hasCategories) { 5295 var sortedCounts = Object.entries(state.categoryCounts || {}) 5296 .sort(function (a, b) { return b[1] - a[1]; }) 5297 .slice(0, 10); 5298 5299 var topCategoriesHtml = ''; 5300 if (sortedCounts.length > 0) { 5301 var listItems = sortedCounts.map(function (entry) { 5302 var id = entry[0]; 5303 var count = entry[1]; 5304 var node = state.categoryMap[id]; 5305 if (!node) return ''; 5306 5307 var isChecked = state.filters.categories.includes(String(id)); 5308 return '<div class="shoper-filter-item"><label>' + 5309 '<input type="checkbox" class="shoper-filter-checkbox category-filter" value="' + id + '"' + 5310 (isChecked ? ' checked' : '') + '>' + 5311 node.name + ' <span style="font-size: 0.8em; color: #999;">(' + count + ')</span>' + 5312 '</label></div>'; 5313 }).join(''); 5314 5315 if (listItems) { 5316 topCategoriesHtml = '<div class="shoper-top-categories">' + listItems + '</div>' + 5317 '<div class="shoper-category-separator">Wszystkie kategorie</div>'; 5318 } 5319 } 5320 5321 var treeResult = renderCategoryTreeHTML(tree, 0, state); 5322 content.push( 5323 '<div class="shoper-filter-group">' + 5324 '<div class="shoper-filter-title">Kategorie</div>' + 5325 '<div class="shoper-scrollable-categories">' + 5326 topCategoriesHtml + 5327 '<div class="shoper-full-tree">' + treeResult.html + '</div>' + 5328 '</div>' + 5329 '</div>' 5330 ); 5331 } 5332 5333 if (producers.length) { 5334 var producersHtml = producers.map(function (prod) { 5335 var name = prod.name || prod; 5336 var isChecked = state.filters.producers.includes(String(name)); 5337 return '<label class="shoper-filter-item">' + 5338 '<input type="checkbox" class="shoper-filter-checkbox producer-filter" value="' + name + '"' + (isChecked ? ' checked' : '') + '>
5338' + 5339 name + 5340 '</label>'; 5341 }).join(''); 5342 5343 content.push( 5344 '<div class="shoper-filter-group">' + 5345 '<div class="shoper-filter-title">Producenci</div>' + 5346 '<input type="text" class="shoper-producer-search" placeholder="Szukaj producenta...">' + 5347 '<div class="shoper-producer-list">' + producersHtml + '</div>' + 5348 '</div>' 5349 ); 5350 } 5351 5352 var rangeMax = state.maxPriceInResults || 500; 5353 var currentMin = state.filters.minPrice || 0; 5354 var currentMax = state.filters.maxPrice || rangeMax; 5355 5356 content.push( 5357 '<div class="shoper-filter-group">' + 5358 '<div class="shoper-filter-title">Cena</div>' + 5359 '<div class="shoper-price-slider-container">' + 5360 '<div class="shoper-slider-track"></div>' + 5361 '<div class="shoper-slider-range-highlight" id="shoper-price-highlight"></div>' + 5362 '<input type="range" class="shoper-range-slider" id="shoper-range-min" min="0" max="' + rangeMax + '" value="' + currentMin + '" step="1">' + 5363 '<input type="range" class="shoper-range-slider" id="shoper-range-max" min="0" max="' + rangeMax + '" value="' + currentMax + '" step="1">' + 5364 '</div>' + 5365 '<div class="shoper-price-inputs">' + 5366 '<div class="shoper-price-input-wrapper">' + 5367 '<input type="number" class="shoper-price-input" id="shoper-price-min-input" value="' + currentMin + '" min="0" max="' + rangeMax + '">' + 5368 '<span class="shoper-price-currency">zÅ</span>' + 5369 '</div>' + 5370 '<span class="shoper-price-separator">â</span>' + 5371 '<div class="shoper-price-input-wrapper">' + 5372 '<input type="number" class="shoper-price-input" id="shoper-price-max-input" value="' + currentMax + '" min="0" max="' + rangeMax + '">' + 5373 '<span class="shoper-price-currency">zÅ</span>' + 5374 '</div>' + 5375 '</div>' + 5376 '</div>' + 5377 '<button class="shoper-reset-filters-btn">WyczyÅÄ filtry</button>' 5378 ); 5379 5380 return content.join(''); 5381 } 5382 5383 function getOverlayHTML(config) { 5384 return '<div class="shoper-search-header">' + 5385 ' <div class="shoper-search-input-wrapper">' + 5386 ' <span class="shoper-search-icon">' + 5387 ' <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">' + 5388 ' <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" />' + 5389 ' </svg>' + 5390 ' </span>' + 5391 ' <input type="text" class="shoper-search-main-input" placeholder="Szukaj produktów..." autofocus>' + 5392 ' </div>' + 5393 ' <div class="shoper-search-actions">' + 5394 ' <div class="shoper-card-view-toggle" role="group" aria-label="Rozmiar kafelków">' + 5395 ' <button class="shoper-card-view-btn" type="button" data-view="compact" aria-label="MaÅe kafelki" aria-pressed="false" title="MaÅe kafelki">' + 5396 ' <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor">' + 5397 ' <rect x="3" y="3" width="4" height="4" rx="1" stroke-width="1.6"></rect>' + 5398 ' <rect x="10" y="3" width="4" height="4" rx="1" stroke-width="1.6"></rect>' + 5399 ' <rect x="17" y="3" width="4" height="4" rx="1" stroke-width="1.6"></rect>' + 5400 ' <rect x="3" y="10" width="4" height="4" rx="1" stroke-width="1.6"></rect>' + 5401 ' <rect x="10" y="10" width="4" height="4" rx="1" stroke-width="1.6"></rect>' + 5402 ' <rect x="17" y="10" width="4" height="4" rx="1" stroke-width="1.6"></rect>' + 5403 ' <rect x="3" y="17" width="4" height="4" rx="1" stroke-width="1.6"></rect>' + 5404 ' <rect x="10" y="17" width="4" height="4" rx="1" stroke-width="1.6"></rect>' + 5405 ' <rect x="17" y="17" width="4" height="4" rx="1" stroke-width="1.6"></rect>' + 5406 ' </svg>' + 5407 ' </button>' + 5408 ' <button class="shoper-card-view-btn is-active" type="button" data-view="large" aria-label="Duże kafelki" aria-pressed="true" title="Duże kafelki">' + 5409 ' <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor">' + 5410 ' <rect x="4" y="4" width="7" height="7" rx="1.6" stroke-width="1.8"></rect>' + 5411 ' <rect x="13" y="4" width="7" height="7" rx="1.6" stroke-width="1.8"></rect>' + 5412 ' <rect x="4" y="13" width="7" height="7" rx="1.6" stroke-width="1.8"></rect>' + 5413 ' <rect x="13" y="13" width="7" height="7" rx="1.6" stroke-width="1.8"></rect>' + 5414 ' </svg>' + 5415 ' </button>' + 5416 ' <button class="shoper-card-view-btn" type="button" data-view="xlarge" aria-label="NajwiÄksze kafelki" aria-pressed="false" title="NajwiÄksze kafelki">' + 5417 ' <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor">' + 5418 ' <rect x="5" y="5" width="14" height="14" rx="2.4" stroke-width="1.8"></rect>' + 5419 ' </svg>' + 5420 ' </button>' + 5421 ' </div>' + 5422 ' <button class="shoper-search-close" type="button" title="Zamknij">' + 5423 ' <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">' + 5424 ' <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />' + 5425 ' </svg>' + 5426 ' </button>' + 5427 ' </div>' + 5428 '</div>' + 5429 '<div class="shoper-search-content">' + 5430 ' <button class="shoper-mobile-filter-btn">' + 5431 ' <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">' + 5432 ' <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 4a1 1 0 011-1h16a1 1 0 011 1v2.586a1 1 0 01-.293.707l-6.414 6.414a1 1 0 00-.293.707V17l-4 4v-6.586a1 1 0 00-.293-.707L3.293 7.293A1 1 0 013 6.586V4z" />' + 5433 ' </svg>' +
5434 ' <span>Filtry</span>' + 5435 ' <span class="shoper-filter-count-badge" style="display: none;">0</span>' + 5436 ' </button>' + 5437 ' <div class="shoper-search-sidebar"></div>' + 5438 ' <div class="shoper-search-results"></div>' + 5439 '</div>' + 5440 '<div class="shoper-mobile-filter-overlay">' + 5441 ' <div class="shoper-mobile-filter-header">' + 5442 ' <span class="shoper-mobile-filter-title">Filtry</span>' + 5443 ' <button class="shoper-mobile-filter-close">' + 5444 ' <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">' + 5445 ' <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />' + 5446 ' </svg>' + 5447 ' </button>' + 5448 ' </div>' + 5449 ' <div class="shoper-mobile-filter-content"></div>' + 5450 ' <div class="shoper-mobile-filter-footer">' + 5451 ' <button class="shoper-mobile-filter-apply">Zastosuj filtry</button>' + 5452 ' </div>' + 5453 '</div>' + 5454 '<div class="shoper-preview-expand-hint">NaciÅnij <strong>Enter</strong> aby otworzyÄ peÅny widok z filtrami</div>' + 5455 '<div class="shoper-search-footer">' + 5456 ' <a href="https://beeking.io/pl?uniqueId=' + config.uniqueId + '" target="_blank" rel="noopener noreferrer" style="display: flex; align-items: center; gap: 8px; text-decoration: none;">' + 5457 ' <img src="https://swnyolatcdwnkfwwvrzp.supabase.co/storage/v1/object/public/emails/5477-logo.png" alt="Beeking">' + 5458 ' <span>Beeking Search</span>' + 5459 ' </a>' + 5460 '</div>'; 5461 } 5462 5463 function getTopProductsHTML(products, showStockInResults) { 5464 var headerHtml = '<div class="shoper-top-products-header">' + 5465 '<span>Popularne produkty</span>' + 5466 '</div>'; 5467 var productsHtml = products.map(function (product) { 5468 return createProductCardHtml(product, showStockInResults); 5469 }).join(''); 5470 return headerHtml + productsHtml; 5471 } 5472 5473 function getPreviewSidebarHTML(topQueries, topCategories, matchedCategories) { 5474 var queriesHtml = ''; 5475 if (topQueries && topQueries.length > 0) { 5476 var queriesToShow = topQueries.slice(0, 5); 5477 var pillsHtml = queriesToShow.map(function (query) { 5478 var queryText = typeof query === 'string' ? query : (query.query || query.text || ''); 5479 if (!queryText) return ''; 5480 return '<button class="shoper-query-pill" data-query="' + queryText.replace(/"/g, '"') + '">' + queryText + '</button>'; 5481 }).join(''); 5482 queriesHtml = '<div class="shoper-preview-section"><div class="shoper-preview-section-title">Popularne wyszukiwania</div><div class="shoper-query-pills">' + pillsHtml + '</div></div>'; 5483 } 5484 5485 var categoriesHtml = ''; 5486 var langAttr = document.documentElement.lang || 'pl-PL'; 5487 var langCode = langAttr.split('-')[0]; 5488 var MAX_CATEGORIES = 7; 5489 5490 // Build mixed categories: matched first, then fill with popular (no duplicates) 5491 var finalCategories = []; 5492 var seenNames = {}; 5493 5494 // Helper to check if ID is valid (not 0, not "0", not empty) 5495 function isValidId(id) { 5496 if (id === null || id === undefined || id === '') return false; 5497 var strId = String(id); 5498 return strId !== '' && strId !== '0'; 5499 } 5500 5501 // Helper to normalize category object 5502 function normalizeCat(cat) { 5503 if (typeof cat === 'string') { 5504 return { name: cat, id: '', url: '' }; 5505 } 5506 var rawId = cat.id || cat.category_id || ''; 5507 return { 5508 name: cat.name || cat.category_name || '', 5509 id: isValidId(rawId) ? String(rawId) : '', 5510 url: cat.url || '' 5511 }; 5512 } 5513 5514 // Add matched categories first (if any) 5515 if (matchedCategories && matchedCategories.length > 0) {
5516 matchedCategories.forEach(function(cat) { 5517 if (finalCategories.length >= MAX_CATEGORIES) return; 5518 var norm = normalizeCat(cat); 5519 // Skip categories without valid ID or URL (they won't link anywhere) 5520 if (!norm.id && !norm.url) return; 5521 // Use name as key to avoid duplicates 5522 var key = norm.name.toLowerCase(); 5523 if (key && !seenNames[key]) { 5524 seenNames[key] = true; 5525 finalCategories.push(norm); 5526 } 5527 }); 5528 } 5529 5530 // Fill remaining slots with popular categories 5531 if (topCategories && topCategories.length > 0 && finalCategories.length < MAX_CATEGORIES) { 5532 topCategories.forEach(function(cat) { 5533 if (finalCategories.length >= MAX_CATEGORIES) return; 5534 var norm = normalizeCat(cat); 5535 // Skip categories without valid ID or URL 5536 if (!norm.id && !norm.url) return; 5537 var key = norm.name.toLowerCase(); 5538 if (key && !seenNames[key]) { 5539 seenNames[key] = true; 5540 finalCategories.push(norm); 5541 } 5542 }); 5543 } 5544 5545 if (finalCategories.length > 0) { 5546 var hasMatched = matchedCategories && matchedCategories.length > 0; 5547 var title = hasMatched ? 'PowiÄ zane kategorie' : 'Popularne kategorie'; 5548 5549 var listHtml = finalCategories.map(function (cat) { 5550 var catUrl = ''; 5551 if (cat.url) { catUrl = cat.url; } 5552 else if (cat.id) { catUrl = '/' + langCode + '/c/a/' + cat.id; } 5553 else { return ''; } // Skip if no valid URL 5554 if (!cat.name) return ''; 5555 return '<a href="' + catUrl + '" class="shoper-category-link">' + cat.name + '</a>'; 5556 }).join(''); 5557 categoriesHtml = '<div class="shoper-preview-section shoper-preview-categories"><div class="shoper-preview-section-title">' + title + '</div><div class="shoper-category-links">' + listHtml + '</div></div>'; 5558 } 5559 5560 if (!queriesHtml && !categoriesHtml) return ''; 5561 return '<div class="shoper-preview-sidebar-content">' + queriesHtml + categoriesHtml + '</div>'; 5562 } 5563 5564 window.BeekingWidgetRender = { 5565 createProductCardHtml: createProductCardHtml, 5566 calculateDiscountPercent: calculateDiscountPercent, 5567 getSidebarHTML: getSidebarHTML, 5568 getOverlayHTML: getOverlayHTML, 5569 getTopProductsHTML: getTopProductsHTML, 5570 getPreviewSidebarHTML: getPreviewSidebarHTML 5571 }; 5572 5573 })(); 5574</script>
vendor: 1 bytes, line 5574
5574
5575<script> 5576 // ========================================== 5577 // File: widget-styles-snippet.html 5578 // Role: RWD Widget Styles Runtime 5579 // ========================================== 5580 (function () { 5581 function toBoolean(value) { 5582 if (typeof value === 'boolean') return value; 5583 if (value == null) return false; 5584 var normalized = String(value).trim().toLowerCase(); 5585 return normalized === 'true' || normalized === '1'; 5586 } 5587 5588 function getDisableWidgetFromConfig(config) { 5589 if (!config || typeof config !== 'object') return false; 5590 return toBoolean(config.disableWidget) || 5591 toBoolean(config.disable_search) || 5592 toBoolean(config.disableSearch) || 5593 toBoolean(config.disable_fullpage) || 5594 toBoolean(config.disableFullpage); 5595 } 5596 5597 var disableSearch = ''; 5598 var legacyDisableWidget = ''; 5599 if (toBoolean(disableSearch) || toBoolean(legacyDisableWidget) || getDisableWidgetFromConfig(window.SHOPER_SEARCH_CONFIG)) { 5600 return; 5601 } 5602 5603 var beekingRwdPrimaryColor = '#ef4444'; 5604 var hasCustomColor = beekingRwdPrimaryColor !== '' && beekingRwdPrimaryColor.indexOf('{') !== 0; 5605 var resolvedPrimaryColor = hasCustomColor ? beekingRwdPrimaryColor : 'var(--primaryColors400, #f59e0b)'; 5606 var resolvedPrimaryHoverColor = hasCustomColor ? 'color-mix(in srgb, ' + beekingRwdPrimaryColor + ' 80%, black)' : 'var(--primaryColors600, #d97706)'; 5607 5608 var styles = ` 5609 :host { 5610 display: flex; 5611 align-items: center; 5612 justify-content: center; 5613 width: 100%; 5614 height: 100%; 5615 padding-top: 0; 5616 5617 /* Dynamic Theming - Map Shoper Variables with Fallbacks */ 5618 --shoper-primary: __PRIMARY_COLOR__; /* Yellow/Amber 500 */ 5619 --shoper-primary-hover: __PRIMARY_HOVER_COLOR__; /* Yellow/Amber 600 */ 5620 --shoper-text: var(--globalFontColor, #1e2124); 5621 --shoper-text-secondary: var(--globalFontColorSecondary, #4d5866); 5622 --shoper-border-radius: 12px; 5623 } 5624 * { 5625 box-sizing: border-box; 5626 } 5627 .shoper-search-overlay { 5628 position: fixed; 5629 top: 0; 5630 left: 0; 5631 width: 100vw; 5632 height: 100vh; 5633 background: rgba(0, 0, 0, 0.5); 5634 z-index: 9999; 5635 display: flex; /* Always flex, using visibility/opacity for show/hide */ 5636 visibility: hidden; 5637 opacity: 0; 5638 transition: opacity 0.22s ease; 5639 justify-content: center; 5640 align-items: center; 5641 padding: 0; 5642 box-sizing: border-box; 5643 font-family: 'Inter', system-ui, -apple-system, sans-serif; 5644 color: var(--shoper-text); 5645 } 5646 .shoper-search-modal { 5647 background: white; 5648 width: 95vw; /* Wider on desktop */ 5649 height: 95vh; /* Taller on desktop */ 5650 max-width: none; /* Full width with 5% padding on each side */ 5651 margin-top: 1.5vh; 5652 border-radius: 12px; 5653 display: flex; 5654 flex-direction: column; 5655 overflow: hidden; 5656 box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25); 5657 transform: translateY(4px); 5658 opacity: 0; 5659 transition: opacity 0.18s ease; 5660 } 5661 :host([data-motion-mode="enhanced"]) .shoper-search-modal { 5662 transform: scale(0.985); 5663 transition: transform 0.24s cubic-bezier(0.16, 1, 0.3, 1), opacity 0.24s ease; 5664 } 5665 .shoper-search-header { 5666 padding: 1rem 2rem; 5667 border-bottom: 1px solid #eee; 5668 display: flex; 5669 align-items: center; 5670 justify-content: center; /* Center content */ 5671 gap: 1rem; 5672 background: white; 5673 flex-shrink: 0; 5674 position: relative; /* For absolute positioning of close button if needed, but flex is better */ 5675 padding-right: 12.5rem; 5676 } 5677 .shoper-search-actions { 5678 position: absolute; 5679 right: 2rem; 5680 top: 50%; 5681 transform: translateY(-50%); 5682 display: flex; 5683 align-items: center; 5684 gap: 0.65rem; 5685 z-index: 20; 5686 } 5687 .shoper-card-view-toggle { 5688 display: inline-flex; 5689 align-items: center; 5690 gap: 0.2rem; 5691 padding: 0.2rem; 5692 border-radius: 999px; 5693 background: #f3f4f6; 5694 border: 1px solid #e5e7eb; 5695 box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.85); 5696 } 5697 .shoper-card-view-btn { 5698 width: 34px; 5699 height: 34px; 5700 border: none; 5701 border-radius: 999px; 5702 background: transparent; 5703 color: #6b7280; 5704 display: flex; 5705 align-items: center; 5706 justify-content: center; 5707 cursor: pointer; 5708 transition: background-color 0.2s ease, color 0.2s ease, transform 0.2s ease; 5709 } 5710 .shoper-card-view-btn:hover { 5711 color: #111827; 5712 transform: translateY(-1px); 5713 } 5714 .shoper-card-view-btn.is-active { 5715 background: white; 5716 color: var(--shoper-primary); 5717 box-shadow: 0 4px 12px rgba(15, 23, 42, 0.12); 5718 } 5719 .shoper-card-view-btn svg { 5720 width: 18px;
5721 height: 18px; 5722 stroke-width: 1.8; 5723 } 5724 .shoper-search-close { 5725 background: #f3f4f6; 5726 border: none; 5727 width: 36px; 5728 height: 36px; 5729 border-radius: 50%; 5730 display: flex; 5731 align-items: center; 5732 justify-content: center; 5733 cursor: pointer; 5734 color: #6b7280; 5735 margin-left: 0; 5736 transition: background-color 0.2s ease, color 0.2s ease, transform 0.2s ease; 5737 } 5738 .shoper-search-close:hover { 5739 background: #e5e7eb; 5740 color: #1f2937; 5741 transform: translateY(-1px); 5742 } 5743 .shoper-search-close svg { 5744 width: 20px; 5745 height: 20px; 5746 stroke-width: 2; 5747 } 5748 .shoper-search-input-wrapper { 5749 flex: 1; 5750 position: relative; 5751 max-width: 600px; /* Limit input width */ 5752 border-bottom: 2px solid #e2e8f0; 5753 transition: border-color 0.2s ease; 5754 } 5755 .shoper-search-input-wrapper:focus-within { 5756 border-bottom-color: var(--shoper-primary); 5757 } 5758 .shoper-search-main-input { 5759 width: 100%; 5760 padding: 0.75rem 0.75rem 0.75rem 2.5rem; /* Adjusted padding */ 5761 font-size: 1.1rem; 5762 border: none; /* Border handled by wrapper */ 5763 outline: none; 5764 background: transparent; 5765 } 5766 .shoper-search-icon { 5767 position: absolute; 5768 left: 0; /* Align icon left */ 5769 top: 50%; 5770 transform: translateY(-50%); 5771 color: #9ca3af; 5772 display: flex; 5773 align-items: center; 5774 } 5775 .shoper-search-icon svg { 5776 width: 20px; 5777 height: 20px; 5778 } 5779 .shoper-search-content { 5780 display: flex; 5781 flex: 1; 5782 overflow: hidden; 5783 padding: 0; /* Remove padding from container, move to children */ 5784 gap: 0; /* Remove gap, handled by padding/border */ 5785 background: #f8f9fa; 5786 min-height: 0; 5787 } 5788 .shoper-search-sidebar { 5789 width: 280px; /* Slightly wider */ 5790 overflow-y: auto; 5791 padding: 1.5rem; /* More internal padding */ 5792 margin-right: 0; 5793 flex-shrink: 0; 5794 background: #ffffff; /* Explicit white background */ 5795 border-right: 1px solid #e5e7eb; /* Separation border */ 5796 border-radius: 12px 0 0 12px; /* Rounded corners on left */ 5797 /* Optional: subtle shadow for depth */ 5798 box-shadow: 2px 0 8px rgba(0,0,0,0.02); 5799 opacity: 1; 5800 transform: translateX(0); 5801 transition: opacity 0.2s ease; 5802 } 5803 .shoper-search-results { 5804 flex: 1; 5805 overflow-y: auto; 5806 overflow-x: hidden; 5807 display: grid; 5808 grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); 5809 gap: 0.75rem; 5810 align-content: start; 5811 padding: 1.25rem; 5812 } 5813 :host(.card-view-large) .shoper-search-results { 5814 grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); 5815 gap: 1rem; 5816 } 5817 :host(.card-view-xlarge) .shoper-search-results { 5818 grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); 5819 gap: 1.25rem; 5820 } 5821 5822 /* Product Card Styles - Compact for desktop */ 5823 .shoper-product-card { 5824 background: white; 5825 border: 1px solid #e8e8e8; 5826 border-radius: 8px; 5827 padding: 0.65rem; 5828 display: flex; 5829 flex-direction: column; 5830 transition: transform 0.25s ease, border-color 0.25s ease; 5831 cursor: pointer; 5832 box-shadow: 0 2px 6px rgba(0,0,0,0.05); 5833 position: relative; 5834 color: inherit; 5835 text-decoration: none; 5836 } 5837 .beeking-labels-container { 5838 position: absolute; 5839 top: 6px; 5840 left: 6px; 5841 z-index: 5; 5842 display: flex; 5843 flex-wrap: wrap; 5844 gap: 6px; 5845 pointer-events: none; 5846 max-width: calc(100% - 12px); 5847 align-items: flex-start; 5848 transform-origin: top left; 5849 transform: scale(0.8); 5850 } 5851 .beeking-product-label-badge { 5852 position: relative; 5853 display: inline-flex; 5854 align-items: center; 5855 justify-content: center; 5856 padding: 4px 8px; 5857 font-size: 12px; 5858 line-height: 1; 5859 min-height: 28px; 5860 font-weight: 700; 5861 border-radius: 6px; 5862 background: #3b82f6; 5863 color: #fff; 5864 pointer-events: auto; 5865 box-shadow: 0 1px 3px rgba(0,0,0,0.2); 5866 white-space: nowrap; 5867 box-sizing: border-box; 5868 } 5869 .shoper-promo-badge { 5870 position: relative; 5871 display: inline-flex; 5872 align-items: center; 5873 align-content: center; 5874 justify-content: center; 5875 background: #dc2626; 5876 color: white; 5877 font-size: 12px; 5878 font-weight: 700; 5879 padding: 5px 8px 3px; 5880 border-radius: 6px; 5881 box-shadow: 0 2px 4px rgba(0,0,0,0.15); 5882 line-height: 1; 5883 height: 28px; 5884 min-height: 28px; 5885 pointer-events: auto; 5886 white-space: nowrap; 5887 box-sizing: border-box; 5888 } 5889 .shoper-product-card:visited { 5890 color: inherit; 5891 } 5892 :host(.card-view-large) .shoper-product-card { 5893 padding: 1rem; 5894 border-radius: 12px; 5895 } 5896 :host(.card-view-large) .beeking-labels-container { 5897 transform: scale(0.8); 5898 top: 6px; 5899 left: 6px; 5900 } 5901 :host(.card-view-xlarge) .shoper-product-card { 5902 padding: 1.2rem; 5903 border-radius: 14px; 5904 } 5905 :host(.card-view-xlarge) .beeking-labels-container { 5906 transform: scale(0.8); 5907 top: 6px; 5908 left: 6px; 5909 } 5910 .shoper-product-card:hover { 5911 transform: translateY(-2px); 5912 border-color: color-mix(in srgb, var(--shoper-primary) 30%, #e2e8f0); 5913 } 5914 .shoper-product-card:focus-visible { 5915 transform: translateY(-2px); 5916 border-color: color-mix(in srgb, var(--shoper-primary) 30%, #e2e8f0); 5917 outline: 2px solid color-mix(in srgb, var(--shoper-primary) 45%, transparent); 5918 outline-offset: 2px; 5919 } 5920 :host([data-motion-mode="enhanced"]) .shoper-product-card:hover, 5921 :host([data-motion-mode="enhanced"]) .shoper-product-card:focus-visible { 5922 box-shadow: 0 8px 20px -5px color-mix(in srgb, var(--shoper-primary) 15%, transparent), 0 6px 8px -6px color-mix(in srgb, var(--shoper-primary) 10%, transparent); 5923 transform: translateY(-3px); 5924 } 5925 .shoper-product-image { 5926 width: 100%; 5927 aspect-ratio: 1; 5928 object-fit: contain; 5929 margin-bottom: 0.6rem; 5930 transition: transform 0.25s ease; 5931 } 5932 :host(.card-view-large) .shoper-product-image { 5933 margin-bottom: 0.9rem; 5934 } 5935 :host(.card-view-xlarge) .shoper-product-image { 5936 margin-bottom: 1rem; 5937 } 5938 .shoper-product-card:hover .shoper-product-image { 5939 transform: scale(1.02); 5940 } 5941 .shoper-product-title { 5942 font-size: 0.8rem; 5943 font-weight: 500; 5944 line-height: 1.4; 5945 margin-bottom: 0.4rem; 5946 color: var(--shoper-text); 5947 flex-grow: 1; 5948 } 5949 :host(.card-view-large) .shoper-product-title { 5950 font-size: 0.95rem; 5951 line-height: 1.45; 5952 margin-bottom: 0.55rem; 5953 } 5954 :host(.card-view-xlarge) .shoper-product-title { 5955 font-size: 1.05rem; 5956 line-height: 1.5; 5957 margin-bottom: 0.65rem; 5958 } 5959 .shoper-product-availability { 5960 font-size: 0.6rem; 5961 color: var(--shoper-text-secondary); 5962 font-weight: 500; 5963 text-transform: uppercase; 5964 letter-spacing: 0.5px; 5965 margin-bottom: 0.4rem; 5966 } 5967 :host(.card-view-large) .shoper-product-availability { 5968 font-size: 0.68rem; 5969 margin-bottom: 0.55rem; 5970 } 5971 :host(.card-view-xlarge) .shoper-product-availability { 5972 font-size: 0.72rem; 5973 margin-bottom: 0.65rem; 5974 } 5975 .shoper-product-availability.unavailable { 5976 color: #ef4444; 5977 } 5978 .shoper-product-price { 5979 font-weight: 700; 5980 color: #333; 5981 font-size: 0.9rem; 5982 margin-top: auto; 5983 display: flex; 5984 flex-wrap: wrap; 5985 align-items: baseline; 5986 gap: 5px; 5987 } 5988 :host(.card-view-large) .shoper-product-price { 5989 font-size: 1.05rem; 5990 } 5991 :host(.card-view-xlarge) .shoper-product-price { 5992 font-size: 1.15rem; 5993 } 5994 5995 .shoper-price-regular { 5996 text-decoration: line-through; 5997 color: #999; 5998 font-size: 0.85em; 5999 font-weight: 400; 6000 } 6001 6002 .shoper-price-promo { 6003 color: #e53935; 6004 font-weight: 700; 6005 } 6006 /* Loading & Empty States */ 6007 .shoper-loading, .shoper-empty { 6008 grid-column: 1 / -1; 6009 text-align: center; 6010 padding: 3rem; 6011 color: #888; 6012 display: flex; 6013 flex-direction: column; 6014 align-items: center; 6015 justify-content: center; 6016 gap: 1rem; 6017 } 6018 .shoper-loading-spinner { 6019 width: 40px; 6020 height: 40px; 6021 border: 3px solid #e2e8f0; 6022 border-top-color: var(--shoper-primary); 6023 border-radius: 50%; 6024 animation: shoper-spin 0.8s linear infinite; 6025 } 6026 .shoper-sidebar-loading .shoper-loading-spinner { 6027 width: 32px; 6028 height: 32px; 6029 border-width: 2px; 6030 } 6031 6032 /* Top Products Header & Results Header */ 6033 .shoper-top-products-header, 6034 .shoper-results-header { 6035 grid-column: 1 / -1; 6036 display: flex; 6037 justify-content: space-between; 6038 align-items: center; 6039 font-size: 0.9rem; 6040 font-weight: 600; 6041 color: #6b7280; 6042 padding-bottom: 0.5rem; 6043 margin-bottom: 0.5rem; 6044 border-bottom: 1px solid #e5e7eb; 6045 } 6046 /* Hide results header in fullscreen mode (only show in preview) */ 6047 .shoper-results-header { 6048 display: none; 6049 } 6050 :host(.preview-mode) .shoper-results-header { 6051 display: flex; 6052 } 6053 .shoper-show-all-btn { 6054 background: none; 6055 border: none; 6056 color: var(--shoper-primary); 6057 font-size: 0.85rem; 6058 font-weight: 500; 6059 cursor: pointer; 6060 padding: 4px 8px; 6061 border-radius: 4px; 6062 transition: background 0.2s ease; 6063 } 6064 .shoper-show-all-btn:hover { 6065 background: rgba(0, 0, 0, 0.05); 6066 } 6067 6068 /* Infinite Scroll Loader */ 6069 .shoper-load-more { 6070 grid-column: 1 / -1; 6071 width: 100%; 6072 clear: both; 6073 display: flex; 6074 flex-direction: column; 6075 align-items: center; 6076 justify-content: center; 6077 padding: 2rem; 6078 color: #6b7280; 6079 font-size: 0.9rem; 6080 gap: 0.5rem; 6081 } 6082 .shoper-load-more-spinner { 6083 width: 32px; 6084 height: 32px; 6085 border: 3px solid #e2e8f0; 6086 border-top-color: var(--shoper-primary); 6087 border-radius: 50%; 6088 animation: shoper-spin 0.8s linear infinite; 6089 } 6090 .shoper-load-more-text { 6091 font-size: 0.85rem; 6092 color: #6b7280; 6093 } 6094 /* Related Products Separator */ 6095 .shoper-related-separator { 6096 grid-column: 1 / -1; 6097 display: flex; 6098 align-items: center; 6099 gap: 1rem; 6100 margin: 1.5rem 0 1rem; 6101 color: #6b7280; 6102 font-size: 0.85rem; 6103 font-weight: 500; 6104 } 6105 .shoper-related-separator::before, 6106 .shoper-related-separator::after { 6107 content: ''; 6108 flex: 1; 6109 height: 1px; 6110 background: #e5e7eb; 6111 } 6112 6113 /* Reorder Animation Styles */ 6114 .shoper-product-card.reordering { 6115 opacity: 0.4; 6116 transform: scale(0.95); 6117 transition: opacity 0.15s ease, transform 0.15s ease; 6118 } 6119 :host([data-motion-mode="enhanced"]) .shoper-product-card.reorder-enter { 6120 animation: reorderSlideIn 0.3s ease forwards; 6121 animation-delay: var(--reorder-delay, 0ms); 6122 } 6123 @keyframes reorderSlideIn { 6124 from { 6125 opacity: 0; 6126 transform: translateY(8px); 6127 } 6128 to { 6129 opacity: 1;
6130 transform: translateY(0); 6131 } 6132 } 6133 /* Filter Styles */ 6134 .shoper-filter-group { 6135 margin-bottom: 2rem; 6136 } 6137 .shoper-filter-title { 6138 font-weight: bold; 6139 margin-bottom: 1rem; 6140 display: flex; 6141 justify-content: space-between; 6142 cursor: pointer; 6143 } 6144 .shoper-filter-item { 6145 display: flex; 6146 align-items: center; 6147 margin-bottom: 0.5rem; 6148 font-size: 0.9rem; 6149 color: #555; 6150 cursor: pointer; 6151 } 6152 .shoper-filter-checkbox { 6153 margin-right: 0.5rem; 6154 width: 16px; 6155 height: 16px; 6156 accent-color: var(--shoper-primary); 6157 cursor: pointer; 6158 } 6159 /* Dual Range Slider Styles - Cross-browser compatible */ 6160 .shoper-price-slider-container { 6161 position: relative; 6162 width: 100%; 6163 height: 24px; 6164 margin-top: 10px; 6165 } 6166 .shoper-range-slider { 6167 -webkit-appearance: none; 6168 -moz-appearance: none; 6169 appearance: none; 6170 width: 100%; 6171 height: 24px; 6172 background: transparent; 6173 position: absolute; 6174 top: 0; 6175 left: 0; 6176 margin: 0; 6177 padding: 0; 6178 pointer-events: none; 6179 z-index: 10; 6180 } 6181 /* WebKit (Chrome, Safari) Thumb */ 6182 .shoper-range-slider::-webkit-slider-thumb { 6183 -webkit-appearance: none; 6184 height: 18px; 6185 width: 18px; 6186 border-radius: 50%; 6187 background: var(--shoper-primary); 6188 cursor: pointer; 6189 pointer-events: auto; 6190 box-shadow: 0 1px 3px rgba(0,0,0,0.3); 6191 border: 2px solid white; 6192 margin-top: -7px; 6193 position: relative; 6194 } 6195 /* WebKit Track */ 6196 .shoper-range-slider::-webkit-slider-runnable-track { 6197 width: 100%; 6198 height: 4px; 6199 background: transparent; 6200 cursor: pointer; 6201 } 6202 /* Firefox Thumb - must NOT have border-box sizing */ 6203 .shoper-range-slider::-moz-range-thumb { 6204 height: 14px; 6205 width: 14px; 6206 border-radius: 50%; 6207 background: var(--shoper-primary); 6208 cursor: pointer; 6209 pointer-events: auto; 6210 box-shadow: 0 1px 3px rgba(0,0,0,0.3); 6211 border: 2px solid white; 6212 } 6213 /* Firefox Track - positioned correctly */ 6214 .shoper-range-slider::-moz-range-track { 6215 width: 100%; 6216 height: 4px; 6217 background: transparent; 6218 cursor: pointer; 6219 } 6220 /* Track background - lower z-index */ 6221 .shoper-slider-track { 6222 width: 100%; 6223 height: 4px; 6224 background: #e2e8f0; 6225 position: absolute; 6226 z-index: 1; 6227 border-radius: 2px; 6228 top: 50%; 6229 transform: translateY(-50%); 6230 pointer-events: none; 6231 } 6232 /* Active range highlight */ 6233 .shoper-slider-range-highlight { 6234 height: 4px; 6235 background: var(--shoper-primary); 6236 position: absolute; 6237 z-index: 2; 6238 border-radius: 2px; 6239 top: 50%; 6240 transform: translateY(-50%); 6241 pointer-events: none; 6242 } 6243 /* Price text inputs */ 6244 .shoper-price-inputs { 6245 display: flex; 6246 justify-content: space-between; 6247 align-items: center; 6248 gap: 8px; 6249 margin-top: 12px; 6250 } 6251 .shoper-price-input-wrapper { 6252 display: flex; 6253 align-items: center; 6254 gap: 4px; 6255 } 6256 .shoper-price-input { 6257 width: 60px; 6258 padding: 6px 8px; 6259 font-size: 0.85rem; 6260 font-weight: 500; 6261 color: #4a5568; 6262 border: 1px solid #e2e8f0; 6263 border-radius: 6px; 6264 text-align: center; 6265 background: white; 6266 transition: border-color 0.2s ease, box-shadow 0.2s ease; 6267 } 6268 .shoper-price-input:focus { 6269 outline: none; 6270 border-color: var(--shoper-primary); 6271 box-shadow: 0 0 0 2px rgba(90, 103, 216, 0.2); 6272 } 6273 .shoper-price-input::-webkit-outer-spin-button, 6274 .shoper-price-input::-webkit-inner-spin-button { 6275 -webkit-appearance: none; 6276 margin: 0; 6277 } 6278 .shoper-price-input[type=number] { 6279 -moz-appearance: textfield; 6280 } 6281 .shoper-price-separator { 6282 color: #9ca3af; 6283 font-size: 0.85rem; 6284 } 6285 .shoper-price-currency { 6286 color: #6b7280; 6287 font-size: 0.8rem; 6288 font-weight: 500; 6289 } 6290 /* Category Tree Styles */ 6291 .shoper-category-tree, .shoper-category-tree ul { 6292 list-style: none !important; 6293 padding-left: 0; 6294 margin: 0; 6295 } 6296 .shoper-category-tree ul { 6297 padding-left: 1.2rem; 6298 display: none; /* Collapsed by default */ 6299 } 6300 .shoper-category-tree ul.expanded { 6301 display: block; 6302 } 6303 .shoper-tree-item { 6304 display: flex; 6305 align-items: center; 6306 padding: 2px 0; 6307 } 6308 .shoper-tree-toggle { 6309 cursor: pointer;
6310 width: 20px; 6311 height: 20px; 6312 display: flex; 6313 align-items: center; 6314 justify-content: center; 6315 color: #888; 6316 font-size: 0.7rem; 6317 margin-right: 4px; 6318 transition: transform 0.2s; 6319 } 6320 .shoper-tree-toggle.expanded { 6321 transform: rotate(90deg); 6322 } 6323 .shoper-tree-toggle:hover { 6324 color: var(--shoper-text); 6325 } 6326 .shoper-producer-search { 6327 width: 100%; 6328 padding: 8px; 6329 margin-bottom: 10px; 6330 border: 1px solid #ddd; 6331 border-radius: 4px; 6332 font-size: 0.9rem; 6333 outline: none; 6334 transition: border-color 0.2s; 6335 } 6336 .shoper-producer-search:focus { 6337 border-color: var(--shoper-primary); 6338 } 6339 .shoper-reset-filters-btn { 6340 display: block; 6341 width: 100%; 6342 padding: 10px; 6343 margin-top: 20px; 6344 background: #fff; 6345 border: 1px solid #ddd; 6346 border-radius: 6px; 6347 color: #333; 6348 font-size: 0.9rem; 6349 cursor: pointer; 6350 transition: background-color 0.2s ease, border-color 0.2s ease, color 0.2s ease; 6351 text-align: center; 6352 } 6353 .shoper-reset-filters-btn:hover { 6354 background: #f3f4f6; 6355 border-color: #ccc; 6356 } 6357 .shoper-producer-list { 6358 max-height: 300px; 6359 overflow-y: auto; 6360 overflow-x: hidden; 6361 padding-right: 5px; 6362 scrollbar-width: thin; 6363 } 6364 .shoper-producer-list::-webkit-scrollbar, 6365 .shoper-scrollable-categories::-webkit-scrollbar { 6366 width: 6px; 6367 } 6368 .shoper-producer-list::-webkit-scrollbar-thumb, 6369 .shoper-scrollable-categories::-webkit-scrollbar-thumb { 6370 background-color: #ccc; 6371 border-radius: 3px; 6372 } 6373 .shoper-tree-spacer { 6374 width: 24px; /* Matches toggle width + margin */ 6375 } 6376 .shoper-scrollable-categories { 6377 max-height: 400px; 6378 overflow-y: auto; 6379 overflow-x: hidden; 6380 padding-right: 5px; 6381 margin-bottom: 10px; 6382 scrollbar-width: thin; /* Firefox */ 6383 } 6384 .shoper-category-separator { 6385 border-top: 1px solid #eee; 6386 margin: 10px 0; 6387 padding-top: 10px; 6388 font-size: 0.75rem; 6389 color: #999; 6390 text-transform: uppercase; 6391 letter-spacing: 0.5px; 6392 font-weight: 600; 6393 } 6394 .shoper-top-categories { 6395 margin-bottom: 10px; 6396 } 6397 .shoper-category-tree label { 6398 cursor: pointer; 6399 display: flex; 6400 align-items: center; 6401 font-size: 0.9rem; 6402 color: #555; 6403 } 6404 .shoper-category-tree input { 6405 margin-right: 6px; 6406 width: 16px; 6407 height: 16px; 6408 min-width: 16px; 6409 min-height: 16px; 6410 flex-shrink: 0; 6411 } 6412 6413 /* Footer Styles */ 6414 .shoper-search-footer { 6415 display: flex; 6416 align-items: center; 6417 justify-content: center; 6418 gap: 8px; 6419 padding: 12px 16px; 6420 padding-bottom: calc(12px + env(safe-area-inset-bottom, 0px)); 6421 background: #f8f9fa; 6422 border-top: 1px solid #eee; 6423 flex-shrink: 0; 6424 } 6425 .shoper-search-footer img { 6426 height: 24px; 6427 width: auto; 6428 opacity: 1; 6429 } 6430 .shoper-search-footer span { 6431 font-size: 0.75rem; 6432 color: #9ca3af; 6433 font-weight: 400; 6434 } 6435 6436 /* Mobile filter elements - hidden on desktop */ 6437 .shoper-mobile-filter-btn, 6438 .shoper-mobile-filter-overlay { 6439 display: none; 6440 } 6441 6442 /* Preview Mode - Desktop only (using :host for Shadow DOM) */ 6443 :host(.preview-mode) { 6444 align-items: flex-start !important; 6445 padding-top: 40px; /* Added margin from top for desktop preview */ 6446 } 6447 :host(.preview-mode) .shoper-search-modal { 6448 width: 60vw; 6449 max-width: 900px; 6450 min-width: 600px; 6451 height: auto; 6452 max-height: 70vh; 6453 border-radius: 12px; 6454 } 6455 :host(.preview-mode) .shoper-search-sidebar { 6456 width: 260px; 6457 padding: 1.25rem; 6458 opacity: 1;
6459 transform: translateX(0); 6460 overflow-y: auto; 6461 border: none; 6462 border-right: 1px solid #e5e7eb; 6463 background: white; 6464 } 6465 :host(.preview-mode) .shoper-search-sidebar:empty { 6466 width: 0; 6467 padding: 0; 6468 border: none; 6469 } 6470 6471 /* Preview Sidebar Styles */ 6472 .shoper-preview-sidebar-content { 6473 display: flex; 6474 flex-direction: column; 6475 gap: 1.5rem; 6476 animation: shoper-fade-in 0.3s ease; 6477 } 6478 .shoper-preview-sidebar-loading { 6479 display: flex; 6480 align-items: center; 6481 justify-content: center; 6482 height: 100px; 6483 } 6484 .shoper-preview-sidebar-loading .shoper-loading-spinner { 6485 width: 24px; 6486 height: 24px; 6487 border-width: 2px; 6488 } 6489 /* Sidebar loading state for fullpage transition */ 6490 .shoper-sidebar-loading { 6491 display: flex; 6492 flex-direction: column; 6493 align-items: center; 6494 justify-content: center; 6495 height: 200px; 6496 gap: 1rem; 6497 color: #6b7280; 6498 font-size: 0.85rem; 6499 } 6500 /* Sidebar content fade-in animation */ 6501 .shoper-filter-group { 6502 opacity: 1; 6503 } 6504 :host([data-motion-mode="enhanced"]) .shoper-sidebar-loading { 6505 animation: shoper-fade-in 0.24s ease; 6506 } 6507 @keyframes shoper-fade-in { 6508 from { opacity: 0; } 6509 to { opacity: 1; } 6510 } 6511 :host([data-motion-mode="enhanced"]) .shoper-filter-group { 6512 animation: shoper-slide-fade-in 0.24s ease forwards; 6513 opacity: 0; 6514 } 6515 :host([data-motion-mode="enhanced"]) .shoper-filter-group:nth-child(1) { animation-delay: 0.02s; } 6516 :host([data-motion-mode="enhanced"]) .shoper-filter-group:nth-child(2) { animation-delay: 0.04s; } 6517 :host([data-motion-mode="enhanced"]) .shoper-filter-group:nth-child(3) { animation-delay: 0.06s; } 6518 @keyframes shoper-slide-fade-in { 6519 from { 6520 opacity: 0; 6521 transform: translateY(8px); 6522 } 6523 to { 6524 opacity: 1; 6525 transform: translateY(0); 6526 } 6527 } 6528 .shoper-preview-section { 6529 display: flex; 6530 flex-direction: column; 6531 gap: 0.75rem; 6532 } 6533 .shoper-preview-section-title { 6534 font-size: 0.75rem; 6535 font-weight: 600; 6536 color: #6b7280; 6537 text-transform: uppercase; 6538 letter-spacing: 0.5px; 6539 } 6540 .shoper-query-pills { 6541 display: flex; 6542 flex-wrap: wrap; 6543 gap: 0.5rem; 6544 } 6545 .shoper-query-pill { 6546 background: #f3f4f6; 6547 border: 1px solid #e5e7eb; 6548 border-radius: 16px; 6549 padding: 6px 12px; 6550 font-size: 0.8rem; 6551 color: var(--shoper-text); 6552 cursor: pointer; 6553 transition: background-color 0.2s ease, border-color 0.2s ease, color 0.2s ease; 6554 white-space: nowrap; 6555 } 6556 .shoper-query-pill:hover { 6557 background: var(--shoper-primary); 6558 border-color: var(--shoper-primary); 6559 color: white; 6560 } 6561 .shoper-category-links { 6562 display: flex; 6563 flex-direction: column; 6564 gap: 0.5rem; 6565 } 6566 .shoper-category-link { 6567 font-size: 0.85rem; 6568 color: var(--shoper-text); 6569 text-decoration: none; 6570 padding: 4px 0; 6571 transition: color 0.2s ease; 6572 } 6573 .shoper-category-link:hover { 6574 color: var(--shoper-primary); 6575 } 6576 .shoper-preview-categories { 6577 margin-top: auto; 6578 } 6579 :host(.preview-mode) .shoper-search-content { 6580 background: #f8f9fa; 6581 border-radius: 0 0 12px 12px; 6582 flex: 0 1 auto; 6583 } 6584 :host(.preview-mode) .shoper-card-view-toggle { 6585 display: none; 6586 } 6587 :host(.preview-mode) .shoper-search-results { 6588 padding: 0.75rem; 6589 max-height: 50vh; 6590 background: #f8f9fa; 6591 flex: 0 1 auto; 6592 grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); 6593 gap: 0.5rem; 6594 } 6595 :host(.preview-mode) .shoper-product-card { 6596 padding: 0.5rem; 6597 border-radius: 6px; 6598 } 6599 :host(.preview-mode) .shoper-product-image { 6600 margin-bottom: 0.5rem; 6601 } 6602 :host(.preview-mode) .shoper-product-title { 6603 font-size: 0.75rem; 6604 margin-bottom: 0.35rem; 6605 line-height: 1.3; 6606 } 6607 :host(.preview-mode) .shoper-product-availability { 6608 font-size: 0.55rem; 6609 margin-bottom: 0.3rem; 6610 } 6611 :host(.preview-mode) .shoper-product-price { 6612 font-size: 0.85rem; 6613 padding-top: 0.25rem; 6614 } 6615 :host(.preview-mode) .shoper-promo-badge { 6616 font-size: 0.6rem; 6617 padding: 2px 5px; 6618 } 6619 :host(.preview-mode) .shoper-search-footer { 6620 padding: 8px 12px; 6621 } 6622 :host(.preview-mode) .shoper-search-footer img { 6623 height: 18px; 6624 } 6625 :host(.preview-mode) .shoper-search-footer span { 6626 font-size: 0.7rem; 6627 } 6628 /* Hint to expand to full mode */ 6629 .shoper-preview-expand-hint { 6630 display: none; 6631 text-align: center; 6632 padding: 8px; 6633 font-size: 0.75rem; 6634 color: #9ca3af; 6635 border-top: 1px solid #eee; 6636 background: #f9fafb; 6637 } 6638 :host(.preview-mode) .shoper-preview-expand-hint { 6639 display: block; 6640 } 6641 6642 @media (max-width: 768px) { 6643 .shoper-search-modal { 6644 width: 100%; 6645 max-width: 100%; 6646 height: 100%; 6647 border-radius: 0; 6648 overflow: hidden; 6649 } 6650 .shoper-search-sidebar { 6651 display: none; 6652 } 6653 .shoper-search-content { 6654 gap: 0; 6655 padding: 0.5rem; 6656 position: relative; 6657 overflow-x: hidden; 6658 max-width: 100%; 6659 } 6660 .shoper-search-header { 6661 padding: 0.75rem 1rem; 6662 gap: 0.75rem; 6663 padding-right: 1rem; 6664 } 6665 .shoper-search-actions { 6666 position: static; 6667 transform: none; 6668 right: auto; 6669 top: auto; 6670 gap: 0.5rem; 6671 } 6672 .shoper-card-view-toggle { 6673 display: none; 6674 } 6675 .shoper-search-main-input { 6676 font-size: 1rem; 6677 padding: 0.6rem 0.6rem 0.6rem 2.2rem; 6678 } 6679 .shoper-search-close { 6680 width: 32px; 6681 height: 32px; 6682 } 6683 .shoper-search-close svg { 6684 width: 18px;
6685 height: 18px; 6686 } 6687 .shoper-search-input-wrapper { 6688 max-width: none; 6689 } 6690 .shoper-search-results { 6691 grid-template-columns: repeat(2, 1fr) !important; 6692 gap: 0.5rem; 6693 padding: 6px; 6694 max-width: 100%; 6695 width: 100%; 6696 overflow-x: hidden; 6697 box-sizing: border-box; 6698 } 6699 .shoper-product-card { 6700 padding: 0.5rem; 6701 border-radius: 8px; 6702 min-width: 0; 6703 max-width: 100%; 6704 box-sizing: border-box; 6705 } 6706 .shoper-product-image { 6707 margin-bottom: 0.5rem; 6708 max-width: 100%; 6709 } 6710 .shoper-product-title { 6711 font-size: 0.8rem; 6712 margin-bottom: 0.5rem; 6713 line-height: 1.3; 6714 word-break: break-word; 6715 overflow-wrap: break-word; 6716 hyphens: auto; 6717 } 6718 .shoper-product-availability { 6719 font-size: 0.6rem; 6720 margin-bottom: 0.5rem; 6721 } 6722 .shoper-product-price { 6723 font-size: 1rem; 6724 } 6725 .shoper-product-card:hover { 6726 transform: none; 6727 } 6728 6729 /* Mobile Filter Button */ 6730 .shoper-mobile-filter-btn { 6731 display: flex; 6732 align-items: center; 6733 gap: 6px; 6734 background: white; 6735 border: 1px solid #e2e8f0; 6736 border-radius: 20px; 6737 padding: 8px 14px; 6738 font-size: 0.85rem; 6739 font-weight: 500; 6740 color: var(--shoper-text); 6741 cursor: pointer; 6742 box-shadow: 0 2px 8px rgba(0,0,0,0.1); 6743 position: absolute; 6744 top: 8px; 6745 left: 8px; 6746 z-index: 10; 6747 } 6748 .shoper-mobile-filter-btn:active { 6749 background: #f3f4f6; 6750 } 6751 .shoper-mobile-filter-btn svg { 6752 width: 16px; 6753 height: 16px; 6754 } 6755 .shoper-filter-count-badge { 6756 background: var(--shoper-primary); 6757 color: white; 6758 font-size: 0.7rem; 6759 font-weight: 600; 6760 min-width: 18px; 6761 height: 18px; 6762 border-radius: 9px; 6763 display: flex; 6764 align-items: center; 6765 justify-content: center; 6766 padding: 0 5px; 6767 } 6768 6769 /* Mobile Filter Overlay */ 6770 .shoper-mobile-filter-overlay { 6771 position: fixed; 6772 top: 0; 6773 left: 0; 6774 width: 100%; 6775 height: 100%; 6776 height: 100dvh; 6777 background: white; 6778 z-index: 10000; 6779 display: flex; 6780 flex-direction: column; 6781 transform: translateX(-100%); 6782 } 6783 :host([data-motion-mode="enhanced"]) .shoper-mobile-filter-overlay { 6784 transition: transform 0.24s ease; 6785 } 6786 .shoper-mobile-filter-overlay.active { 6787 transform: translateX(0); 6788 } 6789 .shoper-mobile-filter-header { 6790 display: flex; 6791 align-items: center; 6792 justify-content: space-between; 6793 padding: 1rem; 6794 border-bottom: 1px solid #e5e7eb; 6795 flex-shrink: 0; 6796 } 6797 .shoper-mobile-filter-title { 6798 font-size: 1.1rem; 6799 font-weight: 600; 6800 color: var(--shoper-text); 6801 } 6802 .shoper-mobile-filter-close { 6803 background: #f3f4f6; 6804 border: none; 6805 width: 36px; 6806 height: 36px; 6807 border-radius: 50%; 6808 display: flex; 6809 align-items: center; 6810 justify-content: center; 6811 cursor: pointer; 6812 color: #6b7280; 6813 } 6814 .shoper-mobile-filter-close svg {
6815 width: 20px; 6816 height: 20px; 6817 } 6818 .shoper-mobile-filter-content { 6819 flex: 1; 6820 overflow-y: auto; 6821 padding: 0; 6822 } 6823 .shoper-mobile-filter-content .shoper-filter-group { 6824 margin-bottom: 0; 6825 border-bottom: 1px solid #e5e7eb; 6826 } 6827 .shoper-mobile-filter-content .shoper-filter-title { 6828 position: sticky; 6829 top: 0; 6830 background: white; 6831 padding: 1rem; 6832 margin: 0; 6833 z-index: 5; 6834 font-size: 1rem; 6835 cursor: pointer; 6836 display: flex; 6837 justify-content: space-between; 6838 align-items: center; 6839 } 6840 .shoper-mobile-filter-content .shoper-filter-title::after { 6841 content: ''; 6842 width: 8px; 6843 height: 8px; 6844 border-right: 2px solid #6b7280; 6845 border-bottom: 2px solid #6b7280; 6846 transform: rotate(45deg); 6847 } 6848 :host([data-motion-mode="enhanced"]) .shoper-mobile-filter-content .shoper-filter-title::after { 6849 transition: transform 0.2s ease; 6850 } 6851 .shoper-mobile-filter-content .shoper-filter-group.collapsed .shoper-filter-title::after { 6852 transform: rotate(-45deg); 6853 } 6854 .shoper-mobile-filter-content .shoper-filter-group-content { 6855 display: grid; 6856 grid-template-rows: 1fr; 6857 overflow: hidden; 6858 opacity: 1; 6859 } 6860 .shoper-mobile-filter-content .shoper-filter-group.collapsed .shoper-filter-group-content { 6861 grid-template-rows: 0fr; 6862 opacity: 0; 6863 } 6864 :host([data-motion-mode="enhanced"]) .shoper-mobile-filter-content .shoper-filter-group-content { 6865 transition: grid-template-rows 0.24s ease, opacity 0.2s ease; 6866 } 6867 .shoper-mobile-filter-content .shoper-filter-group-content-inner { 6868 overflow: hidden; 6869 min-height: 0; 6870 padding: 1rem; 6871 } 6872 .shoper-mobile-filter-content .shoper-scrollable-categories, 6873 .shoper-mobile-filter-content .shoper-producer-list { 6874 max-height: none; 6875 overflow-y: visible; 6876 padding: 0; 6877 } 6878 .shoper-mobile-filter-content .shoper-top-categories, 6879 .shoper-mobile-filter-content .shoper-category-separator, 6880 .shoper-mobile-filter-content .shoper-full-tree { 6881 padding: 0; 6882 } 6883 .shoper-mobile-filter-content .shoper-price-slider-container { 6884 margin-top: 0.5rem; 6885 } 6886 .shoper-mobile-filter-content .shoper-producer-search { 6887 margin: 0 0 1rem 0; 6888 width: 100%; 6889 } 6890 .shoper-mobile-filter-content .shoper-reset-filters-btn { 6891 margin: 1rem; 6892 width: calc(100% - 2rem); 6893 } 6894 .shoper-mobile-filter-footer { 6895 padding: 1rem; 6896 padding-bottom: calc(1rem + env(safe-area-inset-bottom, 20px)); 6897 border-top: 1px solid #e5e7eb; 6898 flex-shrink: 0; 6899 background: white; 6900 } 6901 .shoper-mobile-filter-apply { 6902 width: 100%; 6903 padding: 14px; 6904 background: var(--shoper-primary); 6905 color: white; 6906 border: none; 6907 border-radius: 8px; 6908 font-size: 1rem; 6909 font-weight: 600; 6910 cursor: pointer; 6911 } 6912 .shoper-mobile-filter-apply:active { 6913 background: var(--shoper-primary-hover); 6914 } 6915 } 6916 `; 6917 window.SHOPER_SEARCH_STYLES = styles 6918 .split('__PRIMARY_COLOR__').join(resolvedPrimaryColor) 6919 .split('__PRIMARY_HOVER_COLOR__').join(resolvedPrimaryHoverColor); 6920 })(); 6921</script>
vendor: 1 bytes, line 6921
6921
6922<script> 6923 // ========================================== 6924 // File: widget-snippet.html 6925 // Role: RWD Widget Bootstrap 6926 // ========================================== 6927 (function bootstrapWidget() { 6928 var started = false; 6929 var REQUIRED_SHARED_METHODS = [ 6930 'createWidgetConfig', 6931 'generateClientSessionId', 6932 'generateSearchId', 6933 'getWidgetLanguage', 6934 'extractShoperSearchSummary', 6935 'getDisableWidgetFromConfig', 6936 'resolveSearchMotionMode' 6937 ]; 6938 6939 function hasRequiredSharedApi(shared) { 6940 if (!shared) return false; 6941 for (var i = 0; i < REQUIRED_SHARED_METHODS.length; i++) { 6942 if (typeof shared[REQUIRED_SHARED_METHODS[i]] !== 'function') return false; 6943 } 6944 return true; 6945 } 6946 6947 function hasRequiredRuntimeApi(runtime) { 6948 return !!(runtime && typeof runtime.boot === 'function'); 6949 } 6950 6951 function hasRequiredLogicApi(logic) { 6952 return !!(logic && typeof logic.createRuntimeMethods === 'function'); 6953 } 6954 6955 function start() { 6956 if (started) return; 6957 var shared = window.BeekingWidgetShared; 6958 var runtime = window.BeekingWidgetRuntime; 6959 var logic = window.BeekingWidgetLogic; 6960 if (!hasRequiredSharedApi(shared) || !hasRequiredRuntimeApi(runtime) || !hasRequiredLogicApi(logic)) return; 6961 started = true; 6962 runtime.boot(shared, { 6963 beekingShopId: '516e9574-8b94-48cf-b578-b8e32f3c0e7d', 6964 showUnavailable: 'true', 6965 showStockInResults: '', 6966 disableSearch: '', 6967 legacyDisableWidget: '', 6968 disableFullpage: 'false' 6969 }); 6970 } 6971 6972 if (hasRequiredSharedApi(window.BeekingWidgetShared) && 6973 hasRequiredRuntimeApi(window.BeekingWidgetRuntime) && 6974 hasRequiredLogicApi(window.BeekingWidgetLogic)) { 6975 start(); 6976 return; 6977 } 6978 6979 window.addEventListener('beeking:widget-shared-ready', start); 6980 window.addEventListener('beeking:widget-logic-ready', start); 6981 window.addEventListener('beeking:widget-runtime-ready', start); 6982 })(); 6983</script>
vendor: 1 bytes, line 6983
6983
6984<script> 6985 // ========================================== 6986 // File: snippet-styles.html 6987 // Role: RWD Search Styles Runtime 6988 // ========================================== 6989 (function () { 6990 function toBoolean(value) { 6991 if (typeof value === 'boolean') return value; 6992 if (value == null) return false; 6993 var normalized = String(value).trim().toLowerCase(); 6994 return normalized === 'true' || normalized === '1'; 6995 } 6996 6997 function getDisableWidgetFromConfig(config) { 6998 if (!config || typeof config !== 'object') return false; 6999 return toBoolean(config.disableWidget) || 7000 toBoolean(config.disable_search) || 7001 toBoolean(config.disableSearch) || 7002 toBoolean(config.disable_fullpage) || 7003 toBoolean(config.disableFullpage); 7004 } 7005 7006 var disableSearch = ''; 7007 var legacyDisableWidget = ''; 7008 if (toBoolean(disableSearch) || toBoolean(legacyDisableWidget) || getDisableWidgetFromConfig(window.SHOPER_SEARCH_CONFIG)) { 7009 return; 7010 } 7011 7012 // Bezwarunkowe style kategorii - zawsze aplikowane 7013 var categoryStyles = '/* Beeking Matched Categories Pills */\n' + 7014 '.beeking-matched-categories {\n' + 7015 ' padding: 10px 14px 6px;\n' + 7016 '}\n\n' + 7017 '.beeking-matched-categories__pills {\n' + 7018 ' display: flex;\n' + 7019 ' flex-wrap: wrap;\n' + 7020 ' gap: 8px;\n' + 7021 '}\n\n' + 7022 '.beeking-category-pill {\n' + 7023 ' display: inline-flex;\n' + 7024 ' align-items: center;\n' + 7025 ' gap: 6px;\n' + 7026 ' padding: 8px 14px 8px 12px;\n' + 7027 ' font-size: 13px;\n' + 7028 ' font-weight: 600;\n' + 7029 ' letter-spacing: 0.01em;\n' + 7030 ' color: #4a4a4a;\n' + 7031 ' background: linear-gradient(135deg, rgba(245, 245, 245, 0.8) 0%, rgba(250, 250, 250, 0.9) 100%);\n' + 7032 ' border-radius: 100px;\n' + 7033 ' border: 1px solid rgba(180, 180, 180, 0.5);\n' + 7034 ' text-decoration: none;\n' + 7035 ' transition: all 0.22s cubic-bezier(0.4, 0, 0.2, 1);\n' + 7036 ' white-space: nowrap;\n' + 7037 ' cursor: pointer;\n' + 7038 ' box-shadow: 0 1px 2px rgba(0, 0, 0, 0.04);\n' + 7039 '}\n\n' + 7040 '.beeking-category-pill:hover,\n' + 7041 '.beeking-category-pill:focus-visible {\n' + 7042 ' color: #333;\n' + 7043 ' background: linear-gradient(135deg, rgba(235, 235, 235, 0.9) 0%, rgba(245, 245, 245, 1) 100%);\n' + 7044 ' border-color: #999;\n' + 7045 ' box-shadow: 0 4px 12px -3px rgba(0, 0, 0, 0.15), 0 1px 3px rgba(0, 0, 0, 0.08);\n' + 7046 ' transform: translateY(-2px);\n' + 7047 '}\n\n' + 7048 '.beeking-category-pill:active {\n' + 7049 ' transform: translateY(0);\n' + 7050 ' box-shadow: 0 1px 4px -1px rgba(0, 0, 0, 0.12);\n' + 7051 '}\n\n' + 7052 '.beeking-category-pill__icon {\n' + 7053 ' width: 15px;\n' + 7054 ' height: 15px;\n' + 7055 ' flex-shrink: 0;\n' + 7056 ' opacity: 0.7;\n' + 7057 ' transition: opacity 0.18s ease, transform 0.18s ease;\n' + 7058 '}\n\n' + 7059 '.beeking-category-pill:hover .beeking-category-pill__icon,\n' + 7060 '.beeking-category-pill:focus-visible .beeking-category-pill__icon {\n' + 7061 ' opacity: 1;\n' + 7062 ' transform: scale(1.1);\n' + 7063 '}\n\n' + 7064 '.beeking-category-pill__text {\n' + 7065 ' max-width: 180px;\n' + 7066 ' overflow: hidden;\n' + 7067 ' text-overflow: ellipsis;\n' + 7068 '}\n\n' + 7069 '.beeking-category-pill__arrow {\n' + 7070 ' width: 14px;\n' + 7071 ' height: 14px;\n' + 7072 ' flex-shrink: 0;\n' + 7073 ' opacity: 0.5;\n' + 7074 ' margin-left: -2px;\n' + 7075 ' margin-right: -4px;\n' + 7076 ' transition: opacity 0.18s ease, transform 0.18s ease;\n' + 7077 '}\n\n' + 7078 '.beeking-category-pill:hover .beeking-category-pill__arrow,\n' + 7079 '.beeking-category-pill:focus-visible .beeking-category-pill__arrow {\n' + 7080 ' opacity: 1;\n' + 7081 ' transform: translateX(2px);\n' + 7082 '}\n\n' + 7083 '/* Beeking Product Labels */\n' + 7084 '.beeking-product-item {\n' + 7085 ' position: relative;\n' + 7086 ' z-index: 0;\n' + 7087 '}\n\n' + 7088 '.beeking-labels-container {\n' + 7089 ' position: absolute;\n' + 7090 ' top: 6px;\n' + 7091 ' right: 6px;\n' + 7092 ' z-index: 5;\n' + 7093 ' display: flex;\n' + 7094 ' flex-wrap: wrap;\n' + 7095 ' flex-direction: row-reverse;\n' + 7096 ' gap: 5px;\n' + 7097 ' pointer-events: none;\n' + 7098 ' max-width: calc(100% - 12px);\n' + 7099 ' justify-content: flex-start;\n' + 7100 ' align-content: flex-start;\n' + 7101 ' align-items: flex-start;\n' + 7102 ' transform-origin: top right;\n' + 7103 '}\n\n' + 7104 '.beeking-product-label-badge {\n' + 7105 ' position: relative;\n' + 7106 ' z-index: 5;\n' + 7107 ' display: inline-flex;\n' + 7108 ' align-items: center;\n' + 7109 ' justify-content: center;\n' + 7110 ' padding: 4px 8px;\n' + 7111 ' font-size: 12px;\n' + 7112 ' line-height: 1;\n' + 7113 ' min-height: 28px;\n' + 7114 ' font-weight: 700;\n' + 7115 ' border-radius: 6px;\n' + 7116 ' background: #3b82f6;\n' + 7117 ' color: #fff;\n' + 7118 ' pointer-events: auto;\n' + 7119 ' box-shadow: 0 1px 2px rgba(0,0,0,0.15);\n' + 7120 ' white-space: nowrap;\n' + 7121 ' box-sizing: border-box;\n' + 7122 '}\n\n' + 7123 '/* Responsive - mobile categories */\n' + 7124 '@media (max-width: 575px) {\n' + 7125 ' .search__list {\n' + 7126 ' grid-template-columns: repeat(2, 1fr) !important;\n' + 7127 ' gap: 8px !important;\n' + 7128 ' padding: 8px 4px !important;\n' + 7129 ' }\n\n' + 7130 ' .beeking-labels-container {\n' + 7131 ' transform: scale(0.9);\n' + 7132 ' top: 4px;\n' + 7133 ' right: 4px;\n' + 7134 ' }\n\n' + 7135 ' .beeking-matched-categories__pills {\n' + 7136 ' gap: 8px;\n' + 7137 ' }\n\n' + 7138 ' .beeking-category-pill {\n' + 7139 ' padding: 9px 14px 9px 12px;\n' + 7140 ' font-size: 13px;\n' + 7141 ' }\n\n' + 7142 ' .beeking-category-pill__text {\n' + 7143 ' max-width: 140px;\n' + 7144 ' }\n\n' + 7145 ' .beeking-category-pill__icon {\n' + 7146 ' width: 15px;\n' + 7147 ' height: 15px;\n' + 7148 ' }\n\n' + 7149 ' .beeking-category-pill__arrow {\n' + 7150 ' width: 14px;\n' + 7151 ' height: 14px;\n' + 7152 ' }\n' + 7153 '}'; 7154 7155 // Aplikuj style kategorii bezwarunkowo 7156 var existingCategoryStyles = document.getElementById('beeking-category-styles'); 7157 if (!existingCategoryStyles) { 7158 var categoryStyleElement = document.createElement('style'); 7159 categoryStyleElement.id = 'beeking-category-styles'; 7160 categoryStyleElement.textContent = categoryStyles; 7161 document.head.appendChild(categoryStyleElement); 7162 } 7163 7164 // Sprawdź czy RWD styles sÄ wyÅÄ czone 7165 var disableRwdStyles = 'true'; 7166 if (disableRwdStyles === 'true') { 7167 return; 7168 } 7169 7170 var gridStyles = '/* Grid layout for products - optimized for density */\n' + 7171 '.search__content .search__list,\n' + 7172 '.beeking-results-list .search__list,\n' + 7173 '.search__list {\n' + 7174 ' display: grid !important;\n' + 7175 ' grid-template-columns: repeat(auto-fill, minmax(110px, 1fr)) !important;\n' + 7176 ' grid-auto-flow: row !important;\n' + 7177 ' gap: 10px !important;\n' + 7178 ' padding: 12px 0;\n' + 7179 ' list-style: none;\n' + 7180 ' margin: 0;\n' + 7181 ' width: 100%;\n' + 7182 ' position: relative;\n' + 7183 '}\n\n' + 7184 '/* Suggestions list - thin stacked list */\n' + 7185 '.search__content .search__list:has(> .search__list-item[data-search-sugest-value]),\n' + 7186 '.beeking-results-list .search__list:has(> .search__list-item[data-search-sugest-value]),\n' + 7187 '.search__list:has(> .search__list-item[data-search-sugest-value]) {\n' + 7188 ' display: block !important;\n' + 7189 ' padding: 0 !important;\n' + 7190 '}\n\n' + 7191 '.search__list-item[data-search-sugest-value] {\n' + 7192 ' grid-column: 1 / -1 !important;\n' + 7193 ' margin: 0 !important;\n' + 7194 ' padding: 0 !important;\n' + 7195 ' border: none !important;\n' + 7196 ' background: transparent !important;\n' + 7197 ' border-radius: 0 !important;\n' + 7198 ' box-shadow: none !important;\n' + 7199 '}\n\n' + 7200 '.search__list-item[data-search-sugest-value] .js__search-result-link {\n' + 7201 ' display: flex;\n' + 7202 ' align-items: center;\n' + 7203 ' justify-content: space-between;\n' + 7204 ' gap: 12px;\n' + 7205 ' padding: 10px 0;\n' + 7206 ' border-bottom: 1px solid #ebebeb;\n' + 7207 ' text-decoration: none;\n' + 7208 ' color: #2c3e50;\n' + 7209 ' font-size: 14px;\n' + 7210 ' font-weight: 500;\n' + 7211 '}\n\n' + 7212 '.search__list-item[data-search-sugest-value]:first-child .js__search-result-link {\n' + 7213 ' border-top: 1px solid #ebebeb;\n' + 7214 '}\n\n' + 7215 '.search__list-item[data-search-sugest-value]:last-child .js__search-result-link {\n' + 7216 ' border-bottom: none;\n' + 7217 '}\n\n' + 7218 '.search__list-item[data-search-sugest-value] .js__search-result-link:hover {\n' + 7219 ' color: #111;\n' + 7220 '}\n\n' + 7221 '/* Plain suggestion row (without link) */\n' + 7222 '.search__list-item[data-search-sugest-value]:not(:has(.js__search-result-link)) {\n' + 7223 ' display: flex;\n' + 7224 ' flex-direction: row;\n' + 7225 ' align-items: center;\n' + 7226 ' justify-content: space-between;\n' + 7227 ' gap: 12px;\n' + 7228 ' padding: 10px 0;\n' + 7229 ' border-bottom: 1px solid #ebebeb;\n' + 7230 '}\n\n' + 7231 '.search__list-item[data-search-sugest-value]:not(:has(.js__search-result-link)):first-child {\n' + 7232 ' border-top: 1px solid #ebebeb;\n' + 7233 '}\n\n' + 7234 '.search__list-item[data-search-sugest-value]:not(:has(.js__search-result-link)) .js__search-suggest-item {\n' + 7235 ' font-weight: 600;\n' + 7236 '}\n\n' + 7237 '.search__list-item[data-search-sugest-value]:not(:has(.js__search-result-link)) .search__list-item-action-btn {\n' + 7238 ' flex: none;\n' + 7239 ' display: inline-flex;\n' + 7240 ' align-items: center;\n' + 7241 ' justify-content: center;\n' + 7242 ' font-size: 16px;\n' + 7243 ' line-height: 1;\n' + 7244 ' color: #e74c3c;\n' + 7245 ' cursor: pointer;\n' + 7246 '}\n\n' + 7247 '.search__list-item[data-search-sugest-value]:not(:has(.js__search-result-link)):hover {\n' + 7248 ' color: #e74c3c;\n' + 7249 '}\n\n' + 7250 '.search__list-item[data-search-sugest-value] .js__search-suggest-item {\n' + 7251 ' flex: 1;\n' + 7252 ' white-space: nowrap;\n' + 7253 ' overflow: hidden;\n' + 7254 ' text-overflow: ellipsis;\n' + 7255 '}\n\n' + 7256 '.search__list-item[data-search-sugest-value] .search__result-category-title {\n' + 7257 ' font-size: 11px;\n' + 7258 ' text-transform: uppercase;\n' + 7259 ' letter-spacing: 0.04em;\n' + 7260 ' color: #7f8c8d;\n' + 7261 ' white-space: nowrap;\n' + 7262 '}\n\n' + 7263 '.search__list-item[data-search-sugest-value] .search__result-icon,\n' + 7264 '.search__list-item[data-search-sugest-value] .search__result-content,\n' + 7265 '.search__list-item[data-search-sugest-value] .search__result-note {\n' + 7266 ' display: none !important;\n' + 7267 '}\n\n' + 7268 '.search__list-item[data-search-sugest-value]:hover .js__search-result-link {\n' + 7269 ' padding-left: 4px;\n' + 7270 ' padding-right: 4px;\n' + 7271 ' color: #e74c3c;\n' + 7272 '}\n\n' + 7273 '/* Product tile - exclude divider */\n' + 7274 '.search__list-item:not([style*="border-top"]) {\n' + 7275 ' margin: 0 !important;\n' + 7276 ' padding: 0 !important;\n' + 7277 ' border: none !important;\n' + 7278 ' background: #fff;\n' + 7279 ' border-radius: 8px;\n' + 7280 ' overflow: hidden;\n' + 7281 ' box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);\n' + 7282 ' transition: transform 0.2s ease, box-shadow 0.2s ease;\n' + 7283 ' display: flex;\n' + 7284 ' flex-direction: column;\n' + 7285 ' width: 100%;\n' + 7286 ' max-width: 100%;\n' + 7287 ' grid-column: auto !important;\n' + 7288 ' grid-row: auto !important;\n' + 7289 ' position: relative;\n' + 7290 ' z-index: 0;\n' + 7291 '}\n\n' + 7292 '.search__list-item:not([style*="border-top"]):hover {\n' + 7293 ' transform: translateY(-2px);\n' + 7294 ' box-shadow: 0 6px 16px rgba(0, 0, 0, 0.12);\n' + 7295 '}\n\n' + 7296 '/* Product link */\n' + 7297 '.search__result-link {\n' + 7298 ' display: flex;\n' + 7299 ' flex-direction: column;\n' + 7300 ' height: 100%;\n' + 7301 ' text-decoration: none;\n' + 7302 ' color: inherit;\n' + 7303 '}\n\n' + 7304 '/* Image container */\n' + 7305 '.search__result-icon {\n' + 7306 ' width: 100% !important;\n' + 7307 ' aspect-ratio: 1 / 1;\n' + 7308 ' position: relative !important;\n' + 7309 ' z-index: 0 !important;\n' + 7310 ' overflow: hidden;\n' + 7311 ' background: #f8f9fa;\n' + 7312 ' border-radius: 8px 8px 0 0;\n' + 7313 ' min-height: 90px;\n' + 7314 ' display: flex !important;\n' + 7315 ' align-items: center !important;\n' + 7316 ' justify-content: center !important;\n' + 7317 '}\n\n' + 7318 '/* Product image - large, centered */\n' + 7319 '.search__result-icon img {\n' + 7320 ' max-width: 95% !important;\n' + 7321 ' max-height: 95% !important;\n' + 7322 ' width: auto !important;\n' + 7323 ' height: auto !important;\n' + 7324 ' object-fit: contain !important;\n' + 7325 ' transition: transform 0.3s ease;\n' + 7326 ' position: static !important;\n' + 7327 ' z-index: 0 !important;\n' + 7328 ' top: auto !important;\n' +
7329 ' left: auto !important;\n' + 7330 '}\n\n' + 7331 '.search__list-item:not([style*="border-top"]):hover .search__result-icon img {\n' + 7332 ' transform: scale(1.05);\n' + 7333 '}\n\n' + 7334 '/* Product content */\n' + 7335 '.search__result-content {\n' + 7336 ' padding: 8px;\n' + 7337 ' flex: 1;\n' + 7338 ' display: flex;\n' + 7339 ' flex-direction: column;\n' + 7340 ' gap: 4px;\n' + 7341 '}\n\n' + 7342 '/* Title */\n' + 7343 '.search__result-title {\n' + 7344 ' margin-bottom: 2px;\n' + 7345 '}\n\n' + 7346 '.search__result-title-item {\n' + 7347 ' margin: 0;\n' + 7348 ' font-size: 12px;\n' + 7349 ' font-weight: 500;\n' + 7350 ' line-height: 1.3;\n' + 7351 ' color: #333;\n' + 7352 ' display: -webkit-box;\n' + 7353 ' -webkit-line-clamp: 4;\n' + 7354 ' line-clamp: 4;\n' + 7355 ' -webkit-box-orient: vertical;\n' + 7356 ' overflow: hidden;\n' + 7357 ' text-overflow: ellipsis;\n' + 7358 '}\n\n' + 7359 '/* Price */\n' + 7360 '.search__result-note {\n' + 7361 ' display: flex;\n' + 7362 ' flex-direction: column;\n' + 7363 ' gap: 2px;\n' + 7364 ' margin-top: auto;\n' + 7365 ' padding-top: 4px;\n' + 7366 '}\n\n' + 7367 '.search__result-note-item {\n' + 7368 ' font-size: 14px;\n' + 7369 ' font-weight: 700;\n' + 7370 ' color: #2c3e50;\n' + 7371 '}\n\n' + 7372 '.search__result-item_active {\n' + 7373 ' color: #e74c3c;\n' + 7374 ' font-size: 15px;\n' + 7375 ' font-weight: 700;\n' + 7376 '}\n\n' + 7377 '/* Promotion */\n' + 7378 '.search__result-note-item span[style*="text-decoration: line-through"] {\n' + 7379 ' font-size: 13px;\n' + 7380 ' color: #95a5a6;\n' + 7381 ' font-weight: 400;\n' + 7382 '}\n\n' + 7383 '.search__result-note-item span[style*="background-color: #dc3545"] {\n' + 7384 ' font-size: 11px;\n' + 7385 ' padding: 2px 6px;\n' + 7386 ' border-radius: 4px;\n' + 7387 ' display: inline-block;\n' + 7388 ' margin-left: 4px;\n' + 7389 '}\n\n' + 7390 '/* Promotion Badge */\n' + 7391 '.beeking-product-price__badge {\n' + 7392 ' position: relative;\n' + 7393 ' display: inline-flex;\n' + 7394 ' align-items: center;\n' + 7395 ' align-content: center;\n' + 7396 ' justify-content: center;\n' + 7397 ' background: #dc2626;\n' + 7398 ' color: white;\n' + 7399 ' font-size: 12px;\n' + 7400 ' font-weight: 700;\n' + 7401 ' padding: 5px 8px 3px;\n' + 7402 ' border-radius: 6px;\n' + 7403 ' z-index: 5;\n' + 7404 ' line-height: 1;\n' + 7405 ' height: 28px;\n' + 7406 ' min-height: 28px;\n' + 7407 ' box-shadow: 0 1px 2px rgba(0,0,0,0.1);\n' + 7408 ' white-space: nowrap;\n' + 7409 ' box-sizing: border-box;\n' + 7410 '}\n\n' + 7411 '/* Divider - forces full grid width */\n' + 7412 '.search__content .search__list .search__list-item[style*="border-top"],\n' + 7413 '.beeking-results-list .search__list .search__list-item[style*="border-top"],\n' + 7414 '.search__list .search__list-item[style*="border-top"] {\n' + 7415 ' grid-column: 1 / -1 !important;\n' + 7416 ' grid-column-start: 1 !important;\n' + 7417 ' grid-column-end: -1 !important;\n' + 7418 ' width: 100% !important;\n' + 7419 ' max-width: 100% !important;\n' + 7420 ' height: 1px !important;\n' + 7421 ' min-height: 1px !important;\n' + 7422 ' margin: 12px 0 !important;\n' + 7423 ' padding: 0 !important;\n' + 7424 ' border-top: 1px solid #e0e0e0 !important;\n' + 7425 ' border-bottom: none !important;\n' + 7426 ' background: transparent !important;\n' + 7427 ' display: block !important;\n' + 7428 ' overflow: hidden;\n' + 7429 ' flex: none !important;\n' + 7430 '}\n\n' + 7431 '.search__list-item[style*="border-top"]:hover {\n' + 7432 ' transform: none !important;\n' + 7433 ' box-shadow: none !important;\n' + 7434 '}\n\n' + 7435 '.search__list-item[style*="border-top"] > * {\n' + 7436 ' display: none !important;\n' + 7437 '}\n\n' + 7438 '/* Modal height */\n' + 7439 '.search__content,\n' + 7440 '.beeking-results-list {\n' + 7441 ' max-height: 80vh !important;\n' + 7442 ' overflow-y: auto !important;\n' + 7443 '}\n\n' + 7444 '.search__item_content {\n' + 7445 ' max-height: none !important;\n' + 7446 ' overflow: visible !important;\n' + 7447 '}\n\n' + 7448 '/* Results container - padding-top to prevent covering sticky header */\n' + 7449 '.search__content .search__list,\n' + 7450 '.beeking-results-list .search__list {\n' + 7451 ' padding-top: 0;\n' + 7452 '}\n\n' + 7453 '/* Section header */\n' + 7454 '.search__section-head {\n' + 7455 ' margin-bottom: 12px;\n' + 7456 ' padding: 8px 8px 8px 4px;\n' + 7457 ' border-bottom: 1px solid #ececec;\n' + 7458 ' font-size: 12px;\n' + 7459 ' font-weight: 600;\n' + 7460 ' letter-spacing: 0.05em;\n' + 7461 ' text-transform: uppercase;\n' + 7462 ' color: #7f8c8d;\n' + 7463 '}\n\n' + 7464 '/* Sticky section header */\n' + 7465 '.search__section-head_sticky {\n' + 7466 ' position: sticky !important;\n' + 7467 ' top: 0 !important;\n' + 7468 ' z-index: 30 !important;\n' + 7469 ' isolation: isolate;\n' + 7470 ' background: #fff !important;\n' + 7471 ' margin-bottom: 12px !important;\n' + 7472 ' padding: 8px 8px 8px 12px !important;\n' + 7473 ' border-bottom: 1px solid #ececec !important;\n' + 7474 ' box-shadow: 0 1px 3px rgba(0, 0, 0, 0.03) !important;\n' + 7475 '}\n\n' + 7476 '.search__section-head_line {\n' + 7477 ' border-bottom: 1px solid #ececec !important;\n' + 7478 '}\n\n' + 7479 '/* Search history area */\n' + 7480 '[data-search-section-name="history"] {\n' + 7481 ' background: #f8f9fc;\n' + 7482 ' border-radius: 12px;\n' + 7483 ' padding: 16px;\n' + 7484 ' border: 1px solid rgba(15, 23, 42, 0.08);\n' + 7485 ' margin-bottom: 20px;\n' + 7486 '}\n\n' + 7487 '[data-search-section-name="history"] .search__section-head {\n' + 7488 ' padding: 0 0 8px 0;\n' + 7489 ' margin: 0 0 10px 0;\n' + 7490 ' border: none;\n' + 7491 ' border-bottom: 1px solid rgba(17, 24, 39, 0.08);\n' + 7492 '}\n\n' + 7493 '[data-search-section-name="history"] .search__item_content,\n' + 7494 '[data-search-section-name="history"] .search__history,\n' + 7495 '[data-search-section-name="history"] .search__history-list {\n' + 7496 ' padding: 0 !important;\n' + 7497 ' margin: 0 !important;\n' + 7498 '}\n\n' + 7499 '[data-search-section-name="history"] .search__history-list,\n' + 7500 '[data-search-section-name="history"] .search__item_content ul {\n' + 7501 ' list-style: none;\n' + 7502 ' display: flex;\n' + 7503 ' flex-wrap: wrap;\n' + 7504 ' gap: 8px;\n' + 7505 '}\n\n' + 7506 '/* Search history area - FORCE styles */\n' + 7507 '[data-search-section-name="history"] .search__history-list,\n' + 7508 '[data-search-section-name="history"] ul.search__list,\n' + 7509 '[data-search-section-name="history"] ul {\n' + 7510 ' display: flex !important;\n' + 7511 ' flex-wrap: wrap !important;\n' + 7512 ' flex-direction: row !important;\n' + 7513 ' justify-content: flex-start !important;\n' + 7514 ' align-items: flex-start !important;\n' + 7515 ' gap: 10px !important;\n' + 7516 ' padding: 0 !important;\n' + 7517 ' margin: 0 !important;\n' + 7518 ' grid-template-columns: none !important;\n' + 7519 ' grid-auto-flow: initial !important;\n' + 7520 ' width: 100% !important;\n' + 7521 ' height: auto !important;\n' + 7522 ' max-height: none !important;\n' + 7523 ' line-height: normal !important;\n' + 7524 ' box-sizing: border-box !important;\n' + 7525 '}\n\n' + 7526 '[data-search-section-name="history"] li.search__list-item,\n' + 7527 '[data-search-section-name="history"] .search__item_content li {\n' + 7528 ' display: inline-flex !important;\n' + 7529 ' position: relative !important;\n' + 7530 ' float: none !important;\n' + 7531 ' clear: none !important;\n' + 7532 ' flex: 0 1 auto !important;\n' + 7533 ' flex-direction: row !important;\n' + 7534 ' align-items: center !important;\n' + 7535 ' justify-content: space-between !important;\n' + 7536 ' width: auto !important;\n' + 7537 ' min-width: 140px !important;\n' + 7538 ' max-width: 100% !important;\n' + 7539 ' height: auto !important;\n' + 7540 ' margin: 0 !important;\n' + 7541 ' padding: 8px 16px 8px 14px !important;\n' + 7542 ' border: 1px solid #e2e8f0 !important;\n' + 7543 ' border-radius: 100px !important;\n' + 7544 ' background: #fff !important;\n' + 7545 ' box-shadow: 0 1px 2px rgba(0, 0, 0, 0.03) !important;\n' + 7546 ' box-sizing: border-box !important;\n' + 7547 ' grid-column: initial !important;\n' + 7548 ' grid-row: initial !important;\n' + 7549 ' grid-area: initial !important;\n' + 7550 '}\n\n' + 7551 '[data-search-section-name="history"] li.search__list-item:hover {\n' + 7552 ' border-color: #94a3b8 !important;\n' + 7553 ' box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05) !important;\n' + 7554 '}\n\n' + 7555 '/* Inner content wrapper (text + reload icon) */\n' + 7556 '[data-search-section-name="history"] .search__history-item {\n' + 7557 ' display: flex !important;\n' + 7558 ' flex-direction: row !important;\n' + 7559 ' align-items: center !important;\n' + 7560 ' gap: 8px !important;\n' + 7561 ' padding: 0 !important;\n' + 7562 ' margin: 0 !important;\n' + 7563 ' border: none !important;\n' + 7564 ' background: transparent !important;\n' + 7565 ' width: auto !important;\n' + 7566 ' flex: 1 !important;\n' + 7567 ' min-width: 0 !important;\n' + 7568 '}\n\n' + 7569 '[data-search-section-name="history"] .search__history-item-value {\n' + 7570 ' font-size: 13px !important;\n' + 7571 ' font-weight: 500 !important;\n' + 7572 ' color: #334155 !important;\n' + 7573 ' white-space: nowrap !important;\n' + 7574 ' overflow: hidden !important;\n' + 7575 ' text-overflow: ellipsis !important;\n' + 7576 ' max-width: 320px !important;\n' + 7577 '}\n\n' + 7578 '[data-search-section-name="history"] li.search__list-item:hover .
7578search__history-item-value {\n' + 7579 ' color: #0f172a !important;\n' + 7580 '}\n\n' + 7581 '/* Reload icon */\n' + 7582 '[data-search-section-name="history"] .icon-reload {\n' + 7583 ' font-size: 14px !important;\n' + 7584 ' color: #94a3b8 !important;\n' + 7585 ' display: inline-block !important;\n' + 7586 ' flex-shrink: 0 !important;\n' + 7587 '}\n\n' + 7588 '/* Close button (X) */\n' + 7589 '[data-search-section-name="history"] .js__search-template-item-remove-btn,\n' + 7590 '[data-search-section-name="history"] .icon-close {\n' + 7591 ' display: inline-flex !important;\n' + 7592 ' align-items: center !important;\n' + 7593 ' justify-content: center !important;\n' + 7594 ' width: 20px !important;\n' + 7595 ' height: 20px !important;\n' + 7596 ' margin-left: 6px !important;\n' + 7597 ' padding: 0 !important;\n' + 7598 ' font-size: 16px !important;\n' + 7599 ' color: #cbd5e1 !important;\n' + 7600 ' cursor: pointer !important;\n' + 7601 ' background: transparent !important;\n' + 7602 ' border: none !important;\n' + 7603 ' flex-shrink: 0 !important;\n' + 7604 '}\n\n' + 7605 '[data-search-section-name="history"] .js__search-template-item-remove-btn:hover {\n' + 7606 ' color: #ef4444 !important;\n' + 7607 '}\n\n' + 7608 '/* Loading */\n' + 7609 '.search__loading {\n' + 7610 ' padding: 30px 20px;\n' + 7611 '}\n\n' + 7612 '.search__spinner {\n' + 7613 ' margin-bottom: 15px;\n' + 7614 '}\n\n' + 7615 '/* Availability */\n' + 7616 '.search__result-note-item:last-child {\n' + 7617 ' font-size: 11px;\n' + 7618 ' color: #7f8c8d;\n' + 7619 ' font-weight: 400;\n' + 7620 '}\n\n' + 7621 '/* Responsive */\n' + 7622 '@media (max-width: 768px) {\n' + 7623 ' .search__content .search__list,\n' + 7624 ' .beeking-results-list .search__list,\n' + 7625 ' .search__list {\n' + 7626 ' grid-template-columns: repeat(2, 1fr) !important;\n' + 7627 ' gap: 8px !important;\n' + 7628 ' }\n' + 7629 ' \n' + 7630 ' .search__result-icon {\n' + 7631 ' min-height: 90px;\n' + 7632 ' }\n' + 7633 ' \n' + 7634 ' .search__result-content {\n' + 7635 ' padding: 8px;\n' + 7636 ' }\n' + 7637 ' \n' + 7638 ' .js__search-clear-btn.search__btn.icon.icon-close.search__icon {\n' + 7639 ' display: none !important;\n' + 7640 ' }\n' + 7641 ' \n' + 7642 ' .search__result-title-item {\n' + 7643 ' font-size: 12px;\n' + 7644 ' }\n' + 7645 ' \n' + 7646 ' /* Full screen height on mobile */\n' + 7647 ' .search__content,\n' + 7648 ' .beeking-results-list {\n' + 7649 ' max-height: 100vh !important;\n' + 7650 ' max-height: 100dvh !important;\n' + 7651 ' }\n\n' + 7652 ' .search__item_content {\n' + 7653 ' max-height: none !important;\n' + 7654 ' }\n' + 7655 '}\n\n' + 7656 '@media (max-width: 480px) {\n' + 7657 ' .search__content .search__list,\n' + 7658 ' .beeking-results-list .search__list,\n' + 7659 ' .search__list {\n' + 7660 ' grid-template-columns: repeat(2, 1fr) !important;\n' + 7661 ' gap: 6px !important;\n' + 7662 ' }\n' + 7663 ' \n' + 7664 ' .search__result-icon {\n' + 7665 ' min-height: 80px;\n' + 7666 ' }\n' + 7667 ' \n' + 7668 ' .search__result-content {\n' + 7669 ' padding: 8px;\n' + 7670 ' }\n' + 7671 ' \n' + 7672 ' .search__result-title-item {\n' + 7673 ' font-size: 11px;\n' + 7674 ' -webkit-line-clamp: 3;\n' + 7675 ' line-clamp: 3;\n' + 7676 ' }\n' + 7677 ' \n' + 7678 ' /* Full screen height on small screens */\n' + 7679 ' .search__content,\n' + 7680 ' .beeking-results-list {\n' + 7681 ' max-height: 100vh !important;\n' + 7682 ' max-height: 100dvh !important;\n' + 7683 ' }\n\n' + 7684 ' .search__item_content {\n' + 7685 ' max-height: none !important;\n' + 7686 ' }\n' + 7687 '}'; 7688 7689 var existing = document.getElementById('beeking-grid-styles'); 7690 if (existing) { 7691 existing.textContent = gridStyles; 7692 return; 7693 } 7694 7695 var styleElement = document.createElement('style'); 7696 styleElement.id = 'beeking-grid-styles'; 7697 styleElement.textContent = gridStyles; 7698 document.head.appendChild(styleElement); 7699 })();
7700</script>
vendor: 1 bytes, line 7700
7700
7701<script> 7702 // ========================================== 7703 // File: snippet.html 7704 // Role: RWD Core Search Logic 7705 // ========================================== 7706 (function () { 7707 // Konfiguracja API 7708 var API_BASE = 'https://beeking.io'; 7709 // var API_BASE = 'https://beeking.ngrok.io'; 7710 var API_PATH = '/api/products/search-shoper'; 7711 var DEFAULT_LIMIT = 30; 7712 var beekingShopId = '516e9574-8b94-48cf-b578-b8e32f3c0e7d'; 7713 var showUnavailable = 'true'; 7714 var showStockInResults = ''; 7715 var disableSearch = ''; 7716 var legacyDisableWidget = ''; 7717 var disableFullpageSearch = 'false'; 7718 7719 // Utils 7720 function tryParseJSON(txt) { 7721 try { 7722 return JSON.parse(txt); 7723 } catch (e) { 7724 return null; 7725 } 7726 } 7727 7728 function normalizePhrase(s) { 7729 if (!s) return ''; 7730 return s 7731 .replace(/\u00A0/g, ' ') 7732 .replace(/\s+/g, ' ') 7733 .trim(); 7734 } 7735 7736 function toBoolean(value) { 7737 if (typeof value === 'boolean') return value; 7738 if (value == null) return false; 7739 var normalized = String(value).trim().toLowerCase(); 7740 return normalized === 'true' || normalized === '1'; 7741 } 7742 7743 function getDisableWidgetFromConfig(config) { 7744 if (!config || typeof config !== 'object') return false; 7745 return toBoolean(config.disableWidget) || 7746 toBoolean(config.disable_search) || 7747 toBoolean(config.disableSearch) || 7748 toBoolean(config.disable_fullpage) || 7749 toBoolean(config.disableFullpage); 7750 } 7751 7752 function generateRandomId() { 7753 return Math.random().toString(36).substr(2, 9); 7754 } 7755 7756 function generateClientSessionId() { 7757 return 'session_' + Date.now().toString(36) + '_' + generateRandomId(); 7758 } 7759 7760 function getClientSessionId() { 7761 if (!clientSessionId) { 7762 clientSessionId = generateClientSessionId(); 7763 } 7764 return clientSessionId; 7765 } 7766 7767 var isWidgetDisabled = toBoolean(disableSearch) || toBoolean(legacyDisableWidget) || getDisableWidgetFromConfig(window.SHOPER_SEARCH_CONFIG); 7768 if (isWidgetDisabled) { 7769 window.BeekingCore = window.BeekingCore || { disabled: true }; 7770 return; 7771 } 7772 7773 var shouldShowAvailability = toBoolean(showUnavailable); 7774 var shouldShowStockInfo = toBoolean(showStockInResults); 7775 var isFullpageSearchDisabled = toBoolean(disableFullpageSearch); 7776 var clientSessionId = generateClientSessionId(); 7777 7778 // Preview mode flag - tylko gdy fullscreen jest wÅÄ czony 7779 var isPreviewMode = false; 7780 7781 // Helper to detect mobile 7782 function isMobile() { 7783 return window.innerWidth <= 768; 7784 } 7785 7786 // Top data state (for preview mode) 7787 var topDataState = { 7788 topProducts: [], 7789 topCategories: [], 7790 topQueries: [], 7791 topDataLoaded: false, 7792 topDataLoading: false 7793 }; 7794 7795 // Top data endpoint 7796 var TOP_DATA_ENDPOINT = '/api/shoper/top-data'; 7797 var LABELS_ENDPOINT = '/api/products/labels-shoper'; 7798 var TRACK_PREVIEW_OPEN_ENDPOINT = '/api/products/track-preview-open'; 7799 var TRACK_SHOPER_SEARCH_ENDPOINT = '/api/products/track-shoper-search'; 7800 7801 function fetchLabels() { 7802 if (!beekingShopId) return Promise.resolve(); 7803 var url = API_BASE + LABELS_ENDPOINT + '?uniqueId=' + encodeURIComponent(beekingShopId); 7804 return fetch(url) 7805 .then(function (res) { return res.json(); }) 7806 .then(function (data) { 7807 if (data && Array.isArray(data.labels)) { 7808 data.labels.forEach(function (label) { 7809 if (Array.isArray(label.productIds)) { 7810 label.productIds.forEach(function (pid) { 7811 var id = String(pid); 7812 var list = labelsMap.get(id) || []; 7813 list.push({ 7814 text: label.text, 7815 background: label.backgroundColor, 7816 color: label.textColor, 7817 position: label.position, 7818 fontSize: label.fontSize, 7819 padding: label.padding, 7820 borderColor: label.borderColor, 7821 borderRadius: label.borderRadius 7822 }); 7823 labelsMap.set(id, list); 7824 }); 7825 } 7826 }); 7827 } 7828 }) 7829 .catch(function (err) { 7830 console.error('[Beeking] Failed to fetch labels:', err); 7831 }); 7832 } 7833 7834 function currentShopUrl() { 7835 if (!cachedShopUrl) { 7836 cachedShopUrl = window.location.origin; 7837 } 7838 return cachedShopUrl; 7839 } 7840 7841 function getCurrentLang() { 7842 var langAttr = document.documentElement.lang || 'pl-PL'; 7843 return langAttr.replace('-', '_'); 7844 } 7845 7846 function getSearchPageUrl(query) { 7847 var langCode = getCurrentLang().split('_')[0]; 7848 return '/' + langCode + '/searchquery/' + encodeURIComponent(query) + '/1/full/5'; 7849 } 7850 7851 // State management 7852 var lastQuery = null; 7853 var debounceTimer = null; 7854 var rawCache = new Map(); 7855 var finalCache = new Map(); 7856 var cachedShopUrl = null; 7857 var currentBeekingAbortController = null; 7858 var currentBeekingFallbackAbortController = null; 7859 var currentShoperComparisonAbortController = null; 7860 var currentAIAbortController = null; 7861 var activeQueryId = 0; 7862 var hasBeekingResults = false; 7863 var SEARCH_FALLBACK_DELAY_MS = 2000; 7864 7865 // Labels state 7866 var labelsMap = new Map(); 7867 7868 // Konteksty dla każdego inputa 7869 var inputContexts = new WeakMap(); 7870 7871 function findSearchContentForInput(input) { 7872 if (!input) return null; 7873 7874 var form = input.closest('form'); 7875 if (form) { 7876 var searchContent = form.querySelector('.search__content'); 7877 if (searchContent) return searchContent; 7878 } 7879 7880 var searchContainer = input.closest('.search'); 7881 if (searchContainer) { 7882 var searchContent = searchContainer.querySelector('.search__content'); 7883 if (searchContent) return searchContent; 7884 } 7885 7886 var parent = input.parentElement; 7887 while (parent) { 7888 var searchContent = parent.querySelector('.search__content'); 7889 if (searchContent) return searchContent; 7890 7891 var sibling = parent.nextElementSibling; 7892 if (sibling && sibling.classList.contains('search__content')) { 7893 return sibling; 7894 } 7895 7896 parent = parent.parentElement; 7897 } 7898 7899 return document.querySelector('.search__content'); 7900 } 7901 7902 function getInputContext(input) { 7903 if (!input) return null; 7904 7905 if (!inputContexts.has(input)) { 7906 var searchContent = findSearchContentForInput(input); 7907 var context = { 7908 input: input, 7909 searchContent: searchContent, 7910 lastQuery: null, 7911 debounceTimer: null, 7912 hasBeekingResults: false, 7913 hasRenderedFallback: false, 7914 lastInputValue: '', 7915 queryId: 0, 7916 searchId: null 7917 }; 7918 inputContexts.set(input, context); 7919 } 7920 7921 return inputContexts.get(input); 7922 } 7923 7924 function findInputContextBySearchContent(searchContent) { 7925 if (!searchContent) return null; 7926 7927 var allInputs = document.querySelectorAll('.search__input[name="search"]'); 7928 for (var i = 0; i < allInputs.length; i++) { 7929 var input = allInputs[i]; 7930 var context = inputContexts.get(input); 7931 if (context && context.searchContent === searchContent) { 7932 return context; 7933 } 7934 } 7935 return null; 7936 } 7937 7938 function beekingKey(q, limit, shopId) { 7939 return [q, limit, shopId].join('|'); 7940 } 7941 7942 function buildShoperComparisonUrl(query, searchId) { 7943 var lang = getCurrentLang(); 7944 var url = '/webapi/front/' + lang + '/search/short-list?text=' + encodeURIComponent(query) + '&org=' + encodeURIComponent(query); 7945 url += '&clientSessionId=' + encodeURIComponent(getClientSessionId()); 7946 if (searchId) { 7947 url += '&searchId=' + encodeURIComponent(searchId); 7948 } 7949 if (beekingShopId) { 7950 url += '&uniqueId=' + encodeURIComponent(beekingShopId); 7951 } 7952 return url; 7953 } 7954 7955 function normalizeShoperCollection(value) { 7956 if (!value) return []; 7957 if (Array.isArray(value)) return value; 7958 if (value.list && Array.isArray(value.list)) return value.list; 7959 if (typeof value === 'object') return Object.values(value); 7960 return []; 7961 } 7962 7963 function pushUniqueEntity(target, seen, entity) { 7964 if (!entity || entity.id == null && !entity.name) return; 7965 var id = entity.id != null ? String(entity.id).trim() : ''; 7966 var name = entity.name != null ? String(entity.name).trim() : ''; 7967 var key = id || name; 7968 if (!key || seen.has(key)) return; 7969 seen.add(key); 7970 target.push({ id: id, name: name }); 7971 } 7972 7973 function extractShoperSearchSummary(data) { 7974 var rawProducts = []; 7975 if (data && data.products && data.products.list && Array.isArray(data.products.list)) { 7976 rawProducts = data.products.list; 7977 } else if (Array.isArray(data)) { 7978 rawProducts = data; 7979 } else if (data && data.products) { 7980 rawProducts = normalizeShoperCollection(data.products); 7981 } else if (data && data.results) { 7982 rawProducts = normalizeShoperCollection(data.results); 7983 } else if (data && data.items) { 7984 rawProducts = normalizeShoperCollection(data.items); 7985 } 7986 7987 var products = []; 7988 var productSeen = new Set();
7989 rawProducts.forEach(function (product) { 7990 if (!product || typeof product !== 'object') return; 7991 var productId = product.product_id != null ? product.product_id : product.id; 7992 if (productId == null) return; 7993 var normalizedProductId = String(productId).trim(); 7994 if (!normalizedProductId || productSeen.has(normalizedProductId)) return; 7995 productSeen.add(normalizedProductId); 7996 products.push({ 7997 id: normalizedProductId, 7998 product_id: normalizedProductId, 7999 title: String(product.name || product.title || '').trim() 8000 }); 8001 }); 8002 8003 var categories = []; 8004 var categorySeen = new Set(); 8005 normalizeShoperCollection(data && data.categories).forEach(function (category) { 8006 if (!category || typeof category !== 'object') return; 8007 pushUniqueEntity(categories, categorySeen, { 8008 id: category.category_id != null ? category.category_id : category.id, 8009 name: category.name || category.title 8010 }); 8011 }); 8012 8013 var producers = []; 8014 var producerSeen = new Set(); 8015 normalizeShoperCollection(data && data.producers).forEach(function (producer) { 8016 if (!producer || typeof producer !== 'object') return; 8017 pushUniqueEntity(producers, producerSeen, { 8018 id: producer.producer_id != null ? producer.producer_id : producer.id, 8019 name: producer.name || producer.title 8020 }); 8021 }); 8022 8023 return { 8024 products: products, 8025 categories: categories, 8026 producers: producers, 8027 productsCount: products.length, 8028 categoriesCount: categories.length, 8029 producersCount: producers.length 8030 }; 8031 } 8032 8033 function trackShoperSearch(query, data, options) { 8034 if (!TRACK_SHOPER_SEARCH_ENDPOINT) return; 8035 8036 var searchId = (options && options.searchId) || ''; 8037 var summary = extractShoperSearchSummary(data); 8038 var products = Array.isArray(summary.products) ? summary.products : []; 8039 var categories = Array.isArray(summary.categories) ? summary.categories : []; 8040 var producers = Array.isArray(summary.producers) ? summary.producers : []; 8041 var requestBody = { 8042 query: query || '', 8043 uniqueId: beekingShopId, 8044 shopUrl: currentShopUrl(), 8045 clientSessionId: getClientSessionId(), 8046 products: products, 8047 categories: categories, 8048 producers: producers, 8049 productsCount: typeof summary.productsCount === 'number' ? summary.productsCount : products.length, 8050 categoriesCount: typeof summary.categoriesCount === 'number' ? summary.categoriesCount : categories.length, 8051 producersCount: typeof summary.producersCount === 'number' ? summary.producersCount : producers.length 8052 }; 8053 8054 if (searchId) { 8055 requestBody.searchId = searchId; 8056 } 8057 8058 fetch(API_BASE + TRACK_SHOPER_SEARCH_ENDPOINT, { 8059 method: 'POST', 8060 headers: { 'Content-Type': 'application/json' }, 8061 body: JSON.stringify(requestBody), 8062 credentials: 'omit', 8063 mode: 'cors', 8064 keepalive: true 8065 }).catch(function () { });
8066 } 8067 8068 function triggerShoperComparisonSearch(query, opts) { 8069 if (!query) return; 8070 8071 var searchId = (opts && opts.searchId) || ''; 8072 var url = buildShoperComparisonUrl(query, searchId); 8073 8074 if (currentShoperComparisonAbortController) { 8075 try { 8076 currentShoperComparisonAbortController.abort(); 8077 } catch (e) { } 8078 } 8079 8080 currentShoperComparisonAbortController = new AbortController(); 8081 var controller = currentShoperComparisonAbortController; 8082 8083 fetch(url, { 8084 signal: controller.signal, 8085 credentials: 'same-origin' 8086 }) 8087 .then(function (res) { 8088 if (!res.ok) throw new Error('HTTP ' + res.status); 8089 return res.json(); 8090 }) 8091 .then(function (data) { 8092 trackShoperSearch(query, data, { searchId: searchId }); 8093 }) 8094 .catch(function () { }) 8095 .finally(function () { 8096 if (currentShoperComparisonAbortController === controller) { 8097 currentShoperComparisonAbortController = null; 8098 } 8099 }); 8100 } 8101 8102 function callBeeking(query, opts) { 8103 var uniqueId = beekingShopId; 8104 var shopUrl = (opts && opts.shopUrl) || currentShopUrl(); 8105 var limit = (opts && opts.limit) || DEFAULT_LIMIT; 8106 var queryId = (opts && opts.queryId) || 0; 8107 var searchId = (opts && opts.searchId) || ''; 8108 var onFallbackResponse = (opts && opts.onFallbackResponse) || null; 8109 8110 var body = { query, uniqueId: uniqueId, limit, shopUrl, showUnavailableProducts: shouldShowAvailability, producers: [], categories: [], clientSessionId: getClientSessionId() }; 8111 if (searchId) { 8112 body.searchId = searchId; 8113 } 8114 var key = beekingKey(query, limit, uniqueId); 8115 8116 if (rawCache.has(key)) { 8117 var cached = rawCache.get(key); 8118 if (Date.now() - cached.ts < 30000) { 8119 return Promise.resolve({ results: cached.results, queryId: queryId }); 8120 } 8121 } 8122 8123 triggerShoperComparisonSearch(query, { searchId: searchId }); 8124 8125 if (currentBeekingAbortController) { 8126 currentBeekingAbortController.abort(); 8127 } 8128 if (currentBeekingFallbackAbortController) { 8129 currentBeekingFallbackAbortController.abort(); 8130 currentBeekingFallbackAbortController = null; 8131 } 8132 8133 currentBeekingAbortController = new AbortController(); 8134 var controller = currentBeekingAbortController; 8135 var signal = controller.signal; 8136 var requestSettled = false; 8137 var fallbackPromise = null; 8138 var fallbackTimerId = setTimeout(function () { 8139 if (currentBeekingAbortController === controller && !requestSettled) { 8140 fallbackPromise = callShoperFallback(query, queryId, { 8141 errorMessage: 'Zapytanie do Beeking przekroczyÅo 2 s', 8142 searchId: searchId 8143 }); 8144 8145 if (typeof onFallbackResponse === 'function') { 8146 fallbackPromise.then(function (fallbackResponse) { 8147 if (requestSettled || currentBeekingAbortController !== controller) { 8148 return fallbackResponse; 8149 } 8150 onFallbackResponse(fallbackResponse); 8151 return fallbackResponse; 8152 }); 8153 } 8154 } 8155 }, SEARCH_FALLBACK_DELAY_MS); 8156 8157 return fetch(API_BASE + API_PATH, { 8158 method: 'POST', 8159 headers: { 'Content-Type': 'application/json' }, 8160 body: JSON.stringify(body), 8161 credentials: 'omit', 8162 mode: 'cors', 8163 signal: signal 8164 }) 8165 .then(function (res) { 8166 clearTimeout(fallbackTimerId); 8167 if (!res.ok) throw new Error('HTTP ' + res.status); 8168 return res.json(); 8169 }) 8170 .then(function (json) { 8171 requestSettled = true; 8172 if (currentBeekingAbortController === controller) { 8173 currentBeekingAbortController = null; 8174 } 8175 rawCache.set(key, { ts: Date.now(), results: json }); 8176 return { results: json, queryId: queryId }; 8177 }) 8178 .catch(function (err) { 8179 clearTimeout(fallbackTimerId); 8180 if (currentBeekingAbortController === controller) { 8181 currentBeekingAbortController = null; 8182 } 8183 8184 if (err.name === 'AbortError') { 8185 return { aborted: true, queryId: queryId }; 8186 } 8187 8188 return (fallbackPromise || callShoperFallback(query, queryId, { 8189 errorMessage: err && err.message ? err.message : 'BÅÄ d zapytania Beeking', 8190 searchId: searchId 8191 })).then(function (fallbackResponse) { 8192 requestSettled = true; 8193 return fallbackResponse; 8194 }); 8195 }); 8196 } 8197 8198 function callShoperFallback(query, queryId, opts) { 8199 var errorMessage = opts && opts.errorMessage; 8200 var searchId = (opts && opts.searchId) || ''; 8201 var url = buildShoperComparisonUrl(query, searchId); 8202 8203 if (currentBeekingFallbackAbortController) { 8204 try { 8205 currentBeekingFallbackAbortController.abort(); 8206 } catch (e) { } 8207 currentBeekingFallbackAbortController = null; 8208 } 8209 8210 currentBeekingFallbackAbortController = new AbortController(); 8211 var fallbackController = currentBeekingFallbackAbortController; 8212 var signal = fallbackController.signal; 8213 8214 return fetch(url, { signal: signal }) 8215 .then(function (res) { 8216 if (!res.ok) throw new Error('HTTP ' + res.status); 8217 return res.json(); 8218 }) 8219 .then(function (data) { 8220 var products = []; 8221 if (data && data.products && data.products.list && Array.isArray(data.products.list)) { 8222 products = data.products.list; 8223 } else if (Array.isArray(data)) { 8224 products = data; 8225 } else if (data && data.products && Array.isArray(data.products)) { 8226 products = data.products; 8227 } else if (data && data.results && Array.isArray(data.results)) { 8228 products = data.results; 8229 } else if (data && data.items && Array.isArray(data.items)) { 8230 products = data.items; 8231 } else if (data && typeof data === 'object') { 8232 products = Object.values(data); 8233 } 8234 8235 if (products.length > 0) { 8236 var results = {}; 8237 var langCode = lang.split('_')[0];
8238 products.forEach(function (product, index) { 8239 if (product && (product.product_id || product.id || product.name || product.title)) { 8240 var price = product.price || product.price_gross || product.price_net || ''; 8241 if (typeof price === 'string') { 8242 price = price.replace(/\s/g, '').replace(',', '.').replace(/[^\d.]/g, ''); 8243 } 8244 8245 var promotionPrice = product.promotion_price || product.promotionPrice || null; 8246 if (promotionPrice && typeof promotionPrice === 'string') { 8247 promotionPrice = promotionPrice.replace(/\s/g, '').replace(',', '.').replace(/[^\d.]/g, ''); 8248 } 8249 8250 var stock = (product.attributes && product.attributes.stock) || product.stock || product.availability || null; 8251 var producerName = (product.attributes && product.attributes.producer_name) || product.brand || ''; 8252 8253 var imgUrl = product.img || product.image || product.image_url || product.photo || ''; 8254 if (imgUrl && !imgUrl.startsWith('http') && !imgUrl.startsWith('//')) { 8255 imgUrl = imgUrl.startsWith('/') ? imgUrl : '/' + imgUrl; 8256 } 8257 8258 var productUrl = product.url || product.link || product.seo_url || ''; 8259 if (productUrl && !productUrl.startsWith('http') && !productUrl.startsWith('//')) { 8260 productUrl = productUrl.startsWith('/') ? productUrl : '/' + productUrl; 8261 } else if (!productUrl) { 8262 productUrl = '/' + langCode + '/searchquery/' + encodeURIComponent(query) + '/1/full/5'; 8263 } 8264 8265 results['product_' + index] = { 8266 id: String(product.product_id || product.id || generateProductId(product)), 8267 product_id: String(product.product_id || product.id || ''), 8268 name: product.name || product.title || '', 8269 title: product.name || product.title || '', 8270 url: productUrl, 8271 img: imgUrl, 8272 price: price, 8273 promotionPrice: promotionPrice || null, 8274 promotion_price: promotionPrice || null, 8275 stock: stock, 8276 category: product.category ? { name: product.category.name || product.category } : null, 8277 attributes: product.attributes || {}, 8278 brand: producerName, 8279 tags: product.tags || '' 8280 }; 8281 } 8282 }); 8283 8284 if (Object.keys(results).length > 0) { 8285 var formattedJson = { results: results }; 8286 formattedJson.isFallback = true; 8287 return { results: formattedJson, queryId: queryId }; 8288 } 8289 } 8290 8291 return { 8292 error: true, 8293 message: errorMessage || 'Brak wyników dla zapytania fallback.', 8294 queryId: queryId 8295 }; 8296 }) 8297 .catch(function (fallbackErr) { 8298 if (fallbackErr.name === 'AbortError') { 8299 return { aborted: true, queryId: queryId }; 8300 } 8301 return { 8302 error: true, 8303 message: errorMessage || (fallbackErr && fallbackErr.message) || 'BÅÄ d zapytania fallback.', 8304 queryId: queryId 8305 }; 8306 }) 8307 .finally(function () { 8308 if (currentBeekingFallbackAbortController === fallbackController) { 8309 currentBeekingFallbackAbortController = null; 8310 } 8311 }); 8312 } 8313 8314 function callAIFilter(query, products, opts) { 8315 var uniqueId = beekingShopId; 8316 var shopUrl = (opts && opts.shopUrl) || currentShopUrl(); 8317 var queryId = (opts && opts.queryId) || 0; 8318 8319 var cacheKey = query + '|' + uniqueId; 8320 8321 if (finalCache.has(cacheKey)) { 8322 var cached = finalCache.get(cacheKey); 8323 if (Date.now() - cached.ts < 300000) { 8324 return Promise.resolve({ result: cached.aiResult, queryId: queryId }); 8325 } 8326 } 8327 8328 if (currentAIAbortController) { 8329 currentAIAbortController.abort(); 8330 } 8331 8332 currentAIAbortController = new AbortController(); 8333 var signal = currentAIAbortController.signal; 8334 8335 var matchedCategories = (opts && opts.matched_categories) || []; 8336 8337 var body = { 8338 query: query, 8339 products: products, 8340 matched_categories: matchedCategories, 8341 uniqueId: uniqueId, 8342 shopUrl: shopUrl, 8343 clientSessionId: getClientSessionId(), 8344 language: 'pl' 8345 }; 8346 8347 return fetch(API_BASE + '/api/products/filter-results', { 8348 method: 'POST', 8349 headers: { 'Content-Type': 'application/json' }, 8350 body: JSON.stringify(body), 8351 credentials: 'omit', 8352 mode: 'cors', 8353 signal: signal 8354 }) 8355 .then(function (res) { 8356 if (!res.ok) throw new Error('HTTP ' + res.status); 8357 return res.json(); 8358 }) 8359 .then(function (json) { 8360 return { result: json, queryId: queryId }; 8361 }) 8362 .catch(function (err) { 8363 if (err.name === 'AbortError') { 8364 return { aborted: true, queryId: queryId }; 8365 } 8366 return { error: true, queryId: queryId }; 8367 }); 8368 } 8369 8370 function generateSearchId() { 8371 return 'search_' + Date.now().toString(36) + '_' + generateRandomId(); 8372 } 8373 8374 function generateProductId(product) { 8375 if (product.id) { 8376 return product.id; 8377 } 8378 if (product.url) { 8379 try { 8380 return product.url.split('/').pop() || generateRandomId(); 8381 } catch (e) { 8382 return generateRandomId(); 8383 } 8384 } 8385 return generateRandomId(); 8386 } 8387 8388 function fetchTopData() { 8389 if (topDataState.topDataLoading || topDataState.topDataLoaded) return Promise.resolve(); 8390 8391 topDataState.topDataLoading = true; 8392 8393 return fetch( 8394 API_BASE + TOP_DATA_ENDPOINT + '?uniqueId=' + encodeURIComponent(beekingShopId) + '&clientSessionId=' + encodeURIComponent(getClientSessionId()), 8395 { 8396 method: 'GET', 8397 headers: { 'Content-Type': 'application/json' } 8398 } 8399 ) 8400 .then(function (res) { 8401 if (!res.ok) throw new Error('Failed to fetch top data'); 8402 return res.json(); 8403 }) 8404 .then(function (data) { 8405 topDataState.topProducts = data.topProducts || []; 8406 topDataState.topCategories = data.topCategories || []; 8407 topDataState.topQueries = data.topQueries || []; 8408 topDataState.topDataLoaded = true; 8409 topDataState.topDataLoading = false; 8410 }) 8411 .catch(function (error) { 8412 console.error('Error fetching top data:', error); 8413 topDataState.topProducts = []; 8414 topDataState.topCategories = []; 8415 topDataState.topQueries = []; 8416 topDataState.topDataLoading = false; 8417 }); 8418 } 8419 8420 function trackPreviewOpen(query) { 8421 if (!TRACK_PREVIEW_OPEN_ENDPOINT) return;
8422 try { 8423 fetch(API_BASE + TRACK_PREVIEW_OPEN_ENDPOINT, { 8424 method: 'POST', 8425 headers: { 'Content-Type': 'application/json' }, 8426 body: JSON.stringify({ 8427 query: query || '', 8428 uniqueId: beekingShopId, 8429 shopUrl: currentShopUrl(), 8430 clientSessionId: getClientSessionId() 8431 }) 8432 }).catch(function () { }); 8433 } catch (e) { } 8434 } 8435 8436 function trackProductClick(query, product, options) { 8437 try { 8438 var uniqueId = beekingShopId; 8439 var shopUrl = (options && options.shopUrl) || currentShopUrl(); 8440 var topResultsProductIds = (options && options.topResultsProductIds) || []; 8441 var searchId = (options && options.searchId) || ''; 8442 8443 var requestBody = { 8444 query: query, 8445 product: { 8446 id: product.id || generateProductId(product), 8447 product_id: product.product_id || product.id || generateProductId(product), 8448 title: product.name || product.title 8449 }, 8450 shopUrl: shopUrl, 8451 uniqueId: uniqueId, 8452 clientSessionId: getClientSessionId(), 8453 topResultsProductIds: topResultsProductIds 8454 }; 8455 if (searchId) { 8456 requestBody.searchId = searchId; 8457 } 8458 8459 fetch(API_BASE + '/api/products/track-click', { 8460 method: 'POST', 8461 headers: { 'Content-Type': 'application/json' }, 8462 body: JSON.stringify(requestBody), 8463 credentials: 'omit', 8464 mode: 'cors', 8465 keepalive: true 8466 }).catch(function () { });
8467 } catch (err) { 8468 console.warn('[Beeking] Click tracking failed:', err); 8469 } 8470 } 8471 8472 function trackCategoryClick(query, category, options) { 8473 try { 8474 var uniqueId = beekingShopId; 8475 var shopUrl = (options && options.shopUrl) || currentShopUrl(); 8476 var searchId = (options && options.searchId) || ''; 8477 8478 var requestBody = { 8479 query: query, 8480 category: { 8481 id: category.id || '', 8482 name: category.name || '' 8483 }, 8484 shopUrl: shopUrl, 8485 uniqueId: uniqueId, 8486 clientSessionId: getClientSessionId() 8487 }; 8488 if (searchId) { 8489 requestBody.searchId = searchId; 8490 } 8491 8492 fetch(API_BASE + '/api/products/track-click', { 8493 method: 'POST', 8494 headers: { 'Content-Type': 'application/json' }, 8495 body: JSON.stringify(requestBody), 8496 credentials: 'omit', 8497 mode: 'cors', 8498 keepalive: true 8499 }).catch(function () { }); 8500 } catch (err) { 8501 console.warn('[Beeking] Category click tracking failed:', err); 8502 } 8503 } 8504 8505 function triggerBeeking(query, source, inputContext) { 8506 if (!inputContext) { 8507 inputContext = { 8508 lastQuery: lastQuery, 8509 debounceTimer: debounceTimer, 8510 hasBeekingResults: hasBeekingResults, 8511 searchContent: document.querySelector('.search__content'), 8512 queryId: activeQueryId 8513 }; 8514 } 8515 8516 var q = normalizePhrase(query); 8517 8518 if (!q || q.length < 1) { 8519 inputContext.lastQuery = null; 8520 inputContext.hasBeekingResults = false; 8521 inputContext.hasRenderedFallback = false; 8522 inputContext.searchId = null; 8523 return; 8524 } 8525 8526 if (q === inputContext.lastQuery) { 8527 return; 8528 } 8529 8530 inputContext.lastQuery = q; 8531 clearTimeout(inputContext.debounceTimer); 8532 8533 activeQueryId++; 8534 inputContext.queryId = activeQueryId; 8535 var currentQueryId = inputContext.queryId; 8536 8537 var key = beekingKey(q, DEFAULT_LIMIT, beekingShopId); 8538 if (finalCache.has(key)) { 8539 var cached = finalCache.get(key); 8540 if (Date.now() - cached.ts < 300000) { 8541 inputContext.searchId = null; 8542 // WywoÅaj renderCachedResults z BeekingRender jeÅli istnieje 8543 if (window.BeekingRender && window.BeekingRender.renderCachedResults) { 8544 window.BeekingRender.renderCachedResults(cached, q, inputContext.searchContent); 8545 } 8546 return; 8547 } 8548 } 8549 8550 if (!inputContext.hasBeekingResults && inputContext.searchContent) { 8551 // WywoÅaj showBeekingSpinner z BeekingRender jeÅli istnieje 8552 if (window.BeekingRender && window.BeekingRender.showBeekingSpinner) { 8553 window.BeekingRender.showBeekingSpinner(inputContext.searchContent); 8554 } 8555 } 8556 8557 inputContext.debounceTimer = setTimeout(function () { 8558 if (q !== inputContext.lastQuery) { 8559 return; 8560 } 8561 8562 inputContext.searchId = generateSearchId(); 8563 inputContext.hasRenderedFallback = false; 8564 8565 // Use BeekingCore.callBeeking to go through the wrapper that renders results 8566 var callFn = (window.BeekingCore && window.BeekingCore.callBeeking) ? window.BeekingCore.callBeeking : callBeeking; 8567 callFn(q, { 8568 shopUrl: currentShopUrl(), 8569 limit: DEFAULT_LIMIT, 8570 queryId: currentQueryId, 8571 searchId: inputContext.searchId, 8572 inputContext: inputContext 8573 }); 8574 }, 150); 8575 } 8576 8577 // BezpoÅrednie nasÅuchiwanie na input użytkownika 8578 function setupDirectInputListener() { 8579 var searchInputs = document.querySelectorAll('.search__input[name="search"]'); 8580 if (!searchInputs || searchInputs.length === 0) return; 8581 8582 searchInputs.forEach(function (searchInput) { 8583 var context = getInputContext(searchInput); 8584 if (!context) return; 8585 8586 function handleInput() { 8587 var normalized = normalizePhrase(searchInput.value); 8588 8589 if (normalized === context.lastInputValue) return; 8590 8591 context.lastInputValue = normalized; 8592 triggerBeeking(normalized, 'input', context); 8593 } 8594 8595 function handleFocus() { 8596 if (isMobile()) { 8597 if (window.BeekingShoperSearchWidget && typeof window.BeekingShoperSearchWidget.open === 'function') { 8598 var query = searchInput.value.trim(); 8599 window.BeekingShoperSearchWidget.open(query || ''); 8600 return; 8601 } 8602 } 8603 8604 if (!isFullpageSearchDisabled) { 8605 isPreviewMode = true; 8606 hideDefaultSearchResults(context.searchContent); 8607 if (!topDataState.topDataLoaded && !topDataState.topDataLoading) { 8608 fetchTopData(); 8609 } 8610 trackPreviewOpen(searchInput.value || ''); 8611 } 8612 8613 handleInput(); 8614 } 8615 8616 searchInput.addEventListener('input', handleInput); 8617 searchInput.addEventListener('focus', handleFocus); 8618 searchInput.addEventListener('click', handleFocus); 8619 searchInput.addEventListener('paste', function () { 8620 setTimeout(handleInput, 10); 8621 }); 8622 8623 searchInput.addEventListener('blur', function () { 8624 setTimeout(function () { 8625 var activeEl = document.activeElement; 8626 var searchContainer = searchInput.closest('.search'); 8627 if (searchContainer && !searchContainer.contains(activeEl)) { 8628 isPreviewMode = false; 8629 } 8630 }, 200); 8631 }); 8632 }); 8633 } 8634 8635 function hideDefaultSearchResults(searchContent) { 8636 if (!searchContent) return; 8637 8638 var historySection = searchContent.querySelector('[data-search-section-name="history"]'); 8639 if (historySection) { 8640 historySection.style.display = 'none'; 8641 } 8642 8643 var defaultProductsSection = searchContent.querySelector('[data-search-section-name="products"]:not([data-beeking-section])'); 8644 if (defaultProductsSection) { 8645 defaultProductsSection.style.display = 'none'; 8646 } 8647 8648 var allSections = searchContent.querySelectorAll('.search__section'); 8649 allSections.forEach(function (section) { 8650 if (!section.hasAttribute('data-beeking-section')) { 8651 section.style.display = 'none'; 8652 } 8653 }); 8654 } 8655 8656 function setupFormSubmissionHandler() { 8657 document.addEventListener('submit', function (e) { 8658 var form = e.target; 8659 var action = form.getAttribute('action'); 8660 var isSearchForm = (action && action.includes('/search')) || 8661 form.querySelector('input[name="search"]'); 8662 8663 if (isSearchForm) { 8664 var input = form.querySelector('input[name="search"]'); 8665 var query = input ? input.value.trim() : ''; 8666 8667 var shouldOpenFullscreen = isMobile() || !isFullpageSearchDisabled; 8668 8669 if (shouldOpenFullscreen && query.length > 0 && window.BeekingShoperSearchWidget && typeof window.BeekingShoperSearchWidget.open === 'function') { 8670 e.preventDefault(); 8671 e.stopPropagation(); 8672 e.stopImmediatePropagation(); 8673 8674 window.BeekingShoperSearchWidget.open(query); 8675 return false; 8676 } 8677 } 8678 }, true); 8679 8680 document.addEventListener('keydown', function (e) { 8681 if (e.key === 'Enter' || e.keyCode === 13) { 8682 var target = e.target; 8683 if (target.tagName === 'INPUT' && target.name === 'search') { 8684 var query = target.value.trim(); 8685 8686 var shouldOpenFullscreen = isMobile() || !isFullpageSearchDisabled; 8687 8688 if (shouldOpenFullscreen && query.length > 0 && window.BeekingShoperSearchWidget && typeof window.BeekingShoperSearchWidget.open === 'function') { 8689 e.preventDefault(); 8690 e.stopPropagation(); 8691 e.stopImmediatePropagation(); 8692 8693 window.BeekingShoperSearchWidget.open(query); 8694 return false; 8695 } 8696 } 8697 } 8698 }, true); 8699 8700 document.addEventListener('click', function (e) { 8701 var target = e.target.closest('button, input[type="submit"]'); 8702 if (target) { 8703 var form = target.closest('form'); 8704 if (form) { 8705 var action = form.getAttribute('action'); 8706 var isSearchForm = (action && action.includes('/search')) || 8707 form.querySelector('input[name="search"]'); 8708 8709 if (isSearchForm) { 8710 var input = form.querySelector('input[name="search"]'); 8711 var query = input ? input.value.trim() : ''; 8712 8713 var shouldOpenFullscreen = isMobile() || !isFullpageSearchDisabled; 8714 8715 if (shouldOpenFullscreen && query.length > 0 && window.BeekingShoperSearchWidget && typeof window.BeekingShoperSearchWidget.open === 'function') { 8716 e.preventDefault(); 8717 e.stopPropagation(); 8718 e.stopImmediatePropagation(); 8719 8720 window.BeekingShoperSearchWidget.open(query); 8721 return false; 8722 } 8723 } 8724 } 8725 } 8726 }, true); 8727 } 8728 8729 function setupHistoryClickHandler() { 8730 document.addEventListener('click', function (e) { 8731 var historyItem = e.target.closest('[data-history-item-value]'); 8732 var removeBtn = e.target.closest('.js__search-template-item-remove-btn'); 8733 8734 if (historyItem && !removeBtn) { 8735 var query = historyItem.getAttribute('data-history-item-value'); 8736 8737 var shouldOpenFullscreen = isMobile() || !isFullpageSearchDisabled; 8738 8739 if (shouldOpenFullscreen && query && window.BeekingShoperSearchWidget && typeof window.BeekingShoperSearchWidget.open === 'function') { 8740 e.preventDefault(); 8741 e.stopPropagation(); 8742 e.stopImmediatePropagation(); 8743 8744 window.BeekingShoperSearchWidget.open(query); 8745 return false; 8746 } 8747 } 8748 }, true); 8749 } 8750 8751 function setupSearchContentObserver() { 8752 var observer = new MutationObserver(function (mutations) { 8753 mutations.forEach(function (mutation) { 8754 if (mutation.type === 'attributes' || mutation.type === 'childList') { 8755 var searchContents = document.querySelectorAll('.search__content');
8756 searchContents.forEach(function (searchContent) { 8757 var style = window.getComputedStyle(searchContent); 8758 if (style.display !== 'none' && style.visibility !== 'hidden' && style.opacity !== '0') { 8759 if (window.BeekingRender && window.BeekingRender.checkAndFixOverflow) { 8760 window.BeekingRender.checkAndFixOverflow(searchContent); 8761 } 8762 } 8763 }); 8764 } 8765 }); 8766 }); 8767 8768 observer.observe(document.body, { 8769 attributes: true, 8770 childList: true, 8771 subtree: true, 8772 attributeFilter: ['class', 'style'] 8773 }); 8774 8775 document.addEventListener('focusin', function (e) { 8776 if (e.target.matches('.search__input[name="search"]')) { 8777 var context = getInputContext(e.target); 8778 if (context && context.searchContent) { 8779 setTimeout(function () { 8780 if (window.BeekingRender && window.BeekingRender.checkAndFixOverflow) { 8781 window.BeekingRender.checkAndFixOverflow(context.searchContent); 8782 } 8783 }, 50); 8784 } 8785 } 8786 }); 8787 } 8788 8789 // Uruchom po zaÅadowaniu DOM 8790 if (document.readyState === 'loading') { 8791 document.addEventListener('DOMContentLoaded', function () { 8792 fetchLabels(); 8793 setupDirectInputListener(); 8794 setupFormSubmissionHandler(); 8795 setupHistoryClickHandler(); 8796 setupSearchContentObserver(); 8797 }); 8798 } else { 8799 fetchLabels(); 8800 setupDirectInputListener(); 8801 setupFormSubmissionHandler(); 8802 setupHistoryClickHandler(); 8803 setupSearchContentObserver(); 8804 } 8805 8806 // Eksportuj do window dla snippet-render.html 8807 window.BeekingCore = { 8808 API_BASE: API_BASE, 8809 DEFAULT_LIMIT: DEFAULT_LIMIT, 8810 beekingShopId: beekingShopId, 8811 shouldShowStockInfo: shouldShowStockInfo, 8812 rawCache: rawCache, 8813 finalCache: finalCache, 8814 labelsMap: labelsMap, 8815 activeQueryId: activeQueryId, 8816 getActiveQueryId: function () { return activeQueryId; }, 8817 currentShopUrl: currentShopUrl, 8818 getCurrentLang: getCurrentLang, 8819 getSearchPageUrl: getSearchPageUrl, 8820 normalizePhrase: normalizePhrase, 8821 beekingKey: beekingKey, 8822 generateProductId: generateProductId, 8823 generateRandomId: generateRandomId, 8824 callBeeking: callBeeking, 8825 callShoperFallback: callShoperFallback, 8826 callAIFilter: callAIFilter, 8827 trackProductClick: trackProductClick, 8828 trackCategoryClick: trackCategoryClick, 8829 findInputContextBySearchContent: findInputContextBySearchContent, 8830 getClientSessionId: getClientSessionId 8831 }; 8832 8833 })(); 8834 8835</script>
vendor: 1 bytes, line 8835
8835
8836<script>window.edroneAppId = '6941606b21aa9'; 8837</script>
vendor: 2 bytes, line 8837
8837
8838<script src="https://api.edrone.me/shoper.js"> 8839</script>
vendor: 1 bytes, line 8839
8839
8840<script> 8841var accountId = 2452209; 8842var popupsElement = 0; 8843var enablePopups = popupsElement == '1'; 8844var mailerliteData = { 8845 account: accountId, 8846 enablePopups: enablePopups 8847}; 8848 8849// Load the universal.js script using the IIFE pattern 8850(function (w, d, e, u, f, l, n) { 8851 w[f] = w[f] || function () { 8852 (w[f].q = w[f].q || []) 8853 .push(arguments); 8854 }, l = d.createElement(e), l.async = 1, l.src = u, 8855 n = d.getElementsByTagName(e)[0], n.parentNode.insertBefore(l, n); 8856}) 8857(window, document, 'script', 'https://assets.mailerlite.com/js/universal.js', 'ml'); 8858 8859// Configure the ml function with your data 8860ml('account', mailerliteData.account); 8861ml('enablePopups', mailerliteData.enablePopups); 8862</script>
vendor: 1 bytes, line 8862
8862
8863<script type="text/javascript"> 8864(async function () { 8865 const path = new URL(document.URL).pathname; 8866 const AUTO_SUBMITING_TIMEOUT = 5000; 8867 8868 if (!/\/basket\/done\/+/.test(path) && !/\/panel\/payment\/+/.test(path)) { 8869 return; 8870 } 8871 8872 // 1. Parse Data Safely 8873 const scriptTag = document.getElementById('paymentForm'); 8874 let paymentData; 8875 try { 8876 paymentData = JSON.parse(scriptTag.text || scriptTag.textContent); 8877 } catch (e) { 8878 loader.hidden = true; 8879 return; 8880 } 8881 8882 if (paymentData) { 8883 if (paymentData.applicationId != '7ee2cb8c4443490c4e8be719c2dacdc8') { 8884 return; 8885 } 8886 8887 // Configuration 8888 const MAX_RETRIES = 30; 8889 const RETRY_DELAY_MS = 1000; 8890 // NOTE: Ensure this variable is parsed correctly by your template engine 8891 const API_URL = "https://appstore-bridge.prod.shoper.cloud/api/front/v1/transaction-link"; 8892 8893 // 2. DOM Element Creation & Setup 8894 if (!scriptTag) return console.error("Payment script tag not found."); 8895 8896 const form = document.createElement('form'); 8897 const loader = document.createElement('span'); 8898 const button = document.createElement('button'); 8899 8900 // Setup Loader 8901 loader.classList.add('loader', 'loader__spinner'); 8902 8903 // Setup Button 8904 button.textContent = "OpÅaÄ"; 8905 button.classList.add('important', 'btn', 'btn-primary'); // Removed 'none' to rely on hidden attr 8906 button.type = 'submit'; 8907 button.hidden = true; 8908 8909 // Inject into DOM 8910 scriptTag.after(form); 8911 form.appendChild(loader); 8912 form.appendChild(button); 8913 8914 // 3. Utility: Delay function for polling 8915 const wait = (ms) => new Promise(resolve => setTimeout(resolve, ms)); 8916 8917 // 4. Polling Logic 8918 const fetchPaymentLink = async () => { 8919 const payload = { 8920 shop: paymentData.shop, 8921 transactionId: paymentData.transactionId, 8922 time: paymentData.time, 8923 hash: paymentData.hash, 8924 paymentSuccessShopLink: paymentData.paymentSuccessShopLink, 8925 paymentFailShopLink: paymentData.paymentFailShopLink 8926 }; 8927 8928 for (let attempt = 0; attempt < MAX_RETRIES; attempt++) { 8929 try { 8930 const response = await fetch(API_URL, { 8931 method: 'POST', 8932 headers: {'Content-Type': 'application/json'}, 8933 body: JSON.stringify(payload) 8934 }); 8935 8936 // Success Case (HTTP 200) 8937 if (response.ok) { 8938 const data = await response.json(); 8939 form.action = data.transaction_url; 8940 8941 // Switch UI state 8942 loader.hidden = true; 8943 loader.style.display = 'none'; // Ensure it's visually gone if CSS ignores hidden 8944 button.hidden = false; 8945 setTimeout(() => { 8946 form.submit(); 8947 button.disabled = true; 8948 }, AUTO_SUBMITING_TIMEOUT); // Delay before auto-submitting to allow users to see the button state change 8949 return; // Exit loop 8950 } 8951 8952 // Retry Case (HTTP 404) 8953 if (response.status === 404) { 8954 if (attempt === MAX_RETRIES - 1) { 8955 console.error('Payment link not found after max retries.'); 8956 // Optional: Show an error message to the user here 8957 } else { 8958 await wait(RETRY_DELAY_MS); 8959 continue; // Retry loop 8960 } 8961 } else { 8962 // Other HTTP Errors 8963 console.error(`API Error: \$ \$`); 8964 break; 8965 } 8966 } catch (networkError) { 8967 console.error("Network request failed", networkError); 8968 break; 8969 } 8970 } 8971 }; 8972 8973 // Start the process 8974 await fetchPaymentLink(); 8975 } 8976})(); 8977</script>
vendor: 1 bytes, line 8977
8977
8978<script type="text/javascript"> 8979 8980 window.Shop = window.Shop || {}; 8981 window.Shop.basket = window.Shop.basket || {}; 8982 window.Shop.values = window.Shop.values || {}; 8983 8984 Shop.basket.basketProducts = ''; 8985 Shop.basket.categoryProducts = ''; 8986 Shop.values.currency = 'PLN'; 8987 Shop.values.decimalSep = ','; 8988 Shop.values.thousandSep = ''; 8989 Shop.values.decimalPrecision = 2; 8990 Shop.countryCode = 'PL'; 8991 Shop.pageType = 'shop_news'; 8992 Shop.pageId = 'shop_news134'.replace(/\D/g, ''); 8993 Shop.includeFacebookSDK = ''; 8994 Shop.displayCookieInfo = '1' 8995 Shop.cookiesViewType = '2'; 8996 </script>
8996 8997 8998<template id="consents-modal"> 8999 <div class="consents"> 9000 <div class="consents__wrapper"> 9001 <div class="consents__modal"> 9002 <div class="consents__basic-view js__basic-view" role="dialog" aria-modal="true" aria-labelledby="customer_privacy_banner_header"> 9003 <div class="consents__content"> 9004 <p class="consents__heading" id="customer_privacy_banner_header"> 9005 Dbamy o TwojÄ prywatnoÅÄ 9006 </p> 9007 9008 <p>Pliki cookies i pokrewne im technologie umożliwiajÄ poprawne dziaÅanie strony i pomagajÄ nam dostosowaÄ ofertÄ do Twoich potrzeb. WiÄcej o plikach cookies przeczytasz w naszej <a href="/pl/i/Polityka-prywatnosci/15">Polityce prywatnoÅci.</a></p> 9009 9010 </div> 9011 9012 <div class="consents__buttons"> 9013 <button type="button" class="btn js__accept-necessary">Zaakceptuj tylko niezbÄdne</button> 9014 <button type="button" class="btn js__show-advanced-view">Dostosuj zgody</button> 9015 <button type="button" class="btn btn-red js__accept-all-consents">Zaakceptuj wszystkie</button> 9016 </div> 9017 </div> 9018 9019 <div class="consents__advanced-view js__advanced-view none" role="dialog" aria-modal="true" aria-labelledby="customer_privacy_cookie_header"> 9020 <div class="consents__advanced-content"> 9021 <p class="consents__heading" id="customer_privacy_cookie_header"> 9022 Ustawienia plików cookies 9023 </p> 9024 9025 <p>W tym miejscu możesz okreÅliÄ swoje preferencje w zakresie wykorzystywania przez nas plików cookies.</p> 9026 <br> 9027 9028 <div class="consents__consent"> 9029 <div class="consents__consent-checkbox"> 9030 <span class="checkbox-wrap"> 9031 <input type="checkbox" id="select_all" class="checkbox js__select-all-consents"> 9032 <label for="select_all"></label> 9033 </span> 9034 </div> 9035 9036 <div class="consents__consent-description"> 9037 <p class="consents__text"> 9038 <label for="select_all"><strong>Zaznacz wszystko</strong></label> 9039 </p> 9040 </div> 9041 </div> 9042 9043 <div class="consents__consent"> 9044 <div class="consents__consent-checkbox"> 9045 <span class="checkbox-wrap"> 9046 <input type="checkbox" id="functionCategoryConsent" name="functionCategoryConsent" class="checkbox" checked disabled> 9047 <label for="functionCategoryConsent"></label> 9048 </span> 9049 </div> 9050 9051 <div class="consents__consent-description"> 9052 <p class="consents__text"> 9053 <label for="functionCategoryConsent"><strong>NiezbÄdne do dziaÅania strony</strong></label> 9054 </p> 9055 9056 <p> 9057 <p>Te pliki sÄ niezbÄdne do dziaÅania naszej strony internetowej, dlatego też nie możesz ich wyÅÄ czyÄ.</p> 9058 </p> 9059 </div> 9060 </div> 9061 9062 <div class="consents__consent"> 9063 <div class="consents__consent-checkbox"> 9064 <span class="checkbox-wrap"> 9065 <input type="checkbox" id="functionalConsent" name="functionalConsent" class="checkbox js__consent"> 9066 <label for="functionalConsent"></label> 9067 </span> 9068 </div> 9069 9070 <div class="consents__consent-description"> 9071 <p class="consents__text"> 9072 <label for="functionalConsent"><strong>Funkcjonalne</strong></label> 9073 </p> 9074 9075 <p> 9076 <p>Te pliki umożliwiajÄ Ci korzystanie z pozostaÅych funkcji strony internetowej (innych niż niezbÄdne do jej dziaÅania). Ich wÅÄ czenie da Ci dostÄp do peÅnej funkcjonalnoÅci strony.</p> 9077 </p> 9078 </div> 9079 </div> 9080 9081 <div class="consents__consent"> 9082 <div class="consents__consent-checkbox">
9083 <span class="checkbox-wrap"> 9084 <input type="checkbox" id="analyticsConsent" name="analyticsConsent" class="checkbox js__consent"> 9085 <label for="analyticsConsent"></label> 9086 </span> 9087 </div> 9088 9089 <div class="consents__consent-description"> 9090 <p class="consents__text"> 9091 <label for="analyticsConsent"><strong>Analityczne</strong></label> 9092 </p> 9093 9094 <p> 9095 <p>Te pliki pozwalajÄ nam na dokonanie analiz dotyczÄ cych naszego sklepu internetowego, co może przyczyniÄ siÄ do jego lepszego funkcjonowania i dostosowania do potrzeb Użytkowników.</p> 9096 </p> 9097 </div> 9098 </div> 9099 9100 <div class="consents__consent"> 9101 <div class="consents__consent-checkbox"> 9102 <span class="checkbox-wrap"> 9103 <input type="checkbox" id="platformAnalyticsConsent" name="platformAnalyticsConsent" class="checkbox js__consent"> 9104 <label for="platformAnalyticsConsent"></label> 9105 </span> 9106 </div> 9107 9108 <div class="consents__consent-description"> 9109 <p class="consents__text"> 9110 <label for="platformAnalyticsConsent"><strong>Analityczne dostawcy oprogramowania</strong></label> 9111 </p> 9112 9113 <p> 9114 Dane wykorzystywane przez dostawcÄ oprogramowania sklepu - cyber_Folks S.A. Na ich podstawie dokonywane sÄ analizy, zwiÄ zane z rozwojem oprogramowania, oraz mierzona jest skutecznoÅÄ kampanii reklamowych. Nie sÄ ÅÄ czone z innymi informacjami, podawanymi podczas rejestracji i skÅadania zamówienia. WiÄcej na ten temat przeczytasz w <a href="https://www.shoper.pl/static/dokumenty/polityka-prywatnosci-dla-osob-odwiedzajacych-sklepy-internetowe.pdf" target="_blank" rel="noopener" data-label="Otwieranie w nowej karcie" aria-label="Polityka plików cookies Shoper - otwiera siÄ w nowej karcie">Polityce plików cookies Shoper</a>. 9115 </p> 9116 </div> 9117 </div> 9118 9119 <div class="consents__consent"> 9120 <div class="consents__consent-checkbox"> 9121 <span class="checkbox-wrap"> 9122 <input type="checkbox" id="marketingConsent" name="marketingConsent" class="checkbox js__consent"> 9123 <label for="marketingConsent"></label> 9124 </span> 9125 </div> 9126 9127 <div class="consents__consent-description"> 9128 <p class="consents__text"> 9129 <label for="marketingConsent"><strong>Marketingowe</strong></label> 9130 </p> 9131 9132 <p> 9133 <p>DziÄki tym plikom możemy prowadziÄ dziaÅania marketingowe.</p> 9134 </p> 9135 </div> 9136 </div> 9137 </div> 9138 9139 <div class="consents__advanced-buttons"> 9140 <button type="button" class="btn js__show-basic-view">Anuluj</button> 9141 <button type="button" class="btn btn-red js__save-consents">Zapisz ustawienia</button> 9142 </div> 9143 </diV> 9144 </div> 9145 </div> 9146 9147 <div class="consents__mask"></div> 9148 </div> 9149</template> 9150
9150<script id="config-analytics" type="application/json"> 9151 { 9152 "clientGoogleAnalyticsV4": { 9153 "isActive": "1", 9154 "trackingId": "G-LY3GJ6MJ3D", 9155 "isGtm": "0" 9156 9157 , 9158 "googleRemarketing": { 9159 "isRemarketingActive": false, 9160 "conversionId": "", 9161 "conversionLabel": "", 9162 "isConversionEnabled": false, 9163 "isShoppingAdsEnabled": false, 9164 "awMerchantId": "", 9165 "awFeedCountry": "", 9166 "awFeedLanguage": "" 9167 } 9168 9169 9170 }, 9171 9172 "facebookBusinessExtension": { 9173 "isActive": false, 9174 "pixelId": "" 9175 } 9176 9177 , 9178 "campaignGoogleAnalyticsV4": { 9179 "isActive": false, 9180 "trackingId": "", 9181 "isGtm": "0" 9182 } 9183 9184 9185 } 9186 </script>
9186 9187<div id="shoper-foot"> 9188 <a href="https://www.shoper.pl/premium/" target="_blank" rel="noopener" title="Sklep internetowy Shoper Premium" class="popup" aria-label="Sklep Shoper Premium stworzony na platformie Shoper. Przejdź do strony shoper.pl - otwiera siÄ w nowej karcie">Sklep internetowy Shoper Premium</a> 9189</div>
9189<script type="module" src="https://static.cloudflareinsights.com/beacon.min.js/v4bc70e2c01a94c73b74392e4234840661791215815920" integrity="sha512-L0ha0OXavK/8okipN9F8BtP84dg9DUhPERbBXzwI6dgTA55d2+yweo3pn5CSFYs45/r8md2+xvUPtTdvTNRfjA==" data-cf-beacon='{"version":"2024.11.0","token":"b86d1bf2c48340a7b7a3999d809954a0","r":1,"spa":2}' crossorigin="anonymous"></script>
9189 9190</body> 9191</html>
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.