diff -pruN 4.4.0-1/CHANGES 4.38.0-1/CHANGES
--- 4.4.0-1/CHANGES	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/CHANGES	2025-11-02 08:23:03.000000000 +0000
@@ -1,4 +1,458 @@
-4.4.0 (Unreleased)
+4.38.0 (2025-10-24)
+=========================
+* Fix BiDi Network issue by removing nil values on network requests (#16442)
+* Remove cruft from old CI environment (#16473)
+* [bidi] remove deprecated classes for log inspector (#16474)
+* update devtools versions
+
+4.37.0 (2025-10-16)
+=========================
+* Add CDP for Chrome 141 and remove 138
+* Update Chrome/Edge args for test environment (#16376)
+* Remove `prism` dependency (#16437)
+* Remove `json` version constraint (#16436)
+
+4.36.0 (2025-09-18)
+=========================
+* Add CDP for Chrome 140 and remove 137
+* [BiDi] Create browser module, added user context related methods (#15371)
+* BiDi get client windows (#16211)
+* Fix links to exception documentation on website (#16305)
+* Update `unhandled_prompt_behavior` capability to support hash syntax (#16289)
+
+4.35.0 (2025-08-12)
+=========================
+* Add CDP for Chrome 139 and remove 136
+* Fix typos in javascript & rb (#16019)
+* Allow to use `rubyzip` v3 (#16108)
+
+4.34.0 (2025-06-29)
+=========================
+* Add CDP for Chrome 138 and remove 135
+* Fix child process terminate method when a process is already terminated (#15789)
+* Deprecate ftp proxy (#15926)
+* Add macOS key mappings for Options and Function keys (#15959)
+
+4.33.0 (2025-05-23)
+=========================
+* Add CDP for Chrome 137 and remove 134
+* Let firefox choose the bidi port by default (#15727)
+* Upgrade to Ruby 3.2
+
+4.32.0 (2025-05-02)
+=========================
+* Add CDP for Chrome 136 and remove 133
+* log at info level with names and values when Guards#add_condition used
+* Add PrintOptions Implementation for Ruby WebDriver (#15158)
+* [ruby] fix lint for print_options.rb (#15608)
+* add enable_downloads to attr_accessor for all options classes
+* make logging of test guards debug level not info
+* Set remote active protocol in Firefox to BiDi only
+* handle issue with selenium manager exit status being nil (#15676)
+* Add websocket-port parameter to firefox service (#15458)
+
+4.31.0 (2025-04-04)
+=========================
+* Add support for 135 and remove 132
+* Remove the pre-compiled atoms from trunk
+* Allow symbols again to be passed on delete_cookie (#15519)
+
+4.30.1 (2025-03-22)
+=========================
+* put back the driver#script method that was inadvertently deleted
+
+4.30.0 (2025-03-20)
+=========================
+Ruby:
+* Raise error when trying to delete a cookie without a name  (#15386)
+* Remove deprecated html 5 web storage features
+* Remove deprecated script alias for execute_script
+* Add debug message for location of screenshot
+
+BiDi:
+* Add set viewport for browsing context (#15290)
+* Add support for handling user prompt (#15291)
+* Add Browser context activate command (#15365)
+
+DevTools:
+* Add support for 134 and remove 131
+* Remove support for v85 since no longer required by Firefox
+* Add support for additional target types (#15416)
+
+4.29.1 (2025-02-22)
+=========================
+* [rb] Fix "no anonymous block parameter" in ruby 3.1 (#15315)
+
+4.29.0 (2025-02-17)
+=========================
+* Add CDP for Chrome 133 and remove 130
+* [rb] Add Bidi Network Response Handler (#14900)
+* [rb] Remove Firefox CDP (#15200)
+* [rb][BiDi] Add support for provide response command (#15080)
+* [rb][BiDi] Add set cache behaviour (#15114)
+
+4.28.0 (2025-01-16)
+=========================
+* Add CDP for Chrome 132 and remove 129
+* [ci] Bumping versions for nightly
+* [rb] Add tests for the cookie named, and updates type (#14843)
+* [rb] Update note for return value of Hash (#14845)
+* [rb] BiDi Network: add_request_handler, remove_request_handler, clear_request_handlers (#14751)
+* Update supported versions for Chrome DevTools
+
+4.27.0 (2024-11-21)
+=========================
+* Add CDP for Chrome 131 and remove 128
+* Add Firefox CDP deprecation warnings (#14763)
+* Add Bidi network commands for authentication and interception (#14523)
+* Handle graceful webdriver shutdown (#14430)
+* Reduce RBS errors to 0 (#14661)
+* Resolve `uri` gem deprecation warning (#14770)
+* Update minimum Ruby to 3.1 (#14685)
+* Implement navigation commands with BiDi (#14094)
+
+4.26.0 (2024-10-28)
+=========================
+* Add CDP for Chrome 130 and remove 127
+* Add missing RBS methods (#14621)
+* Update Ruby BiDi script structs to match spec
+* Add RBS type support for BiDi related classes (#14611)
+
+4.25.0 (2024-09-19)
+=========================
+* Add CDP for Chrome 129 and remove 126
+* Fix add_cause method not being able to process an array of hashes (#14433)
+* replace `fedcm` links with new ones (#14478)
+* Allow driver path to be set using ENV variables (#14287)
+
+4.24.0 (2024-08-23)
+=========================
+* Deprecate WebStorage JS methods (#14276)
+* BUGFIX: Add stamp to nightly build (#14320)
+* Add timeout and tests for curb, also added the gem curb that was not part of selenium (#14285)
+* Add CDP for Chrome 128 and remove 125
+
+4.23.0 (2024-07-18)
+=========================
+* Add FedCM support to the ruby selenium client (#13796)
+* Add URLs constant to update error messages (#14174)
+* Update selenium manager types (#14189)
+* Add backtrace locations and cause to errors (#14170)
+* Add CDP for Chrome 127 and remove 124
+
+4.22.0 (2024-06-20)
+=========================
+
+* Force UTF-8 encoding on logger (see #6937)
+* Don't crash when ChildProcess is already killed (see #14032)
+* Manage bidi instance on the bridge not the driver (#14071)
+* Implement High Level Logging API with BiDi (#14073)
+* Fix bug with message deletion in Guard class
+* Change output for Guard class
+* Implement toggle for BiDi and Classic implementations (#14092)
+* Add preference to enable CDP in Firefox by default (#14091)
+* Add support for the w3c silent option for the ruby library (#14152)
+* Add CDP for Chrome 126 and remove 123
+
+4.21.1 (2024-05-16)
+=========================
+
+* Fixed missing Chrome binary error in Rails system tests.
+
+4.21.0 (2024-05-16)
+=========================
+
+* Add CDP for Chrome 125 and remove 122
+* Initial extensibility points for Appium
+  * Support registering extra headers in HTTP client
+  * Support overriding User-Agent in HTTP client
+  * Support registering extra bridge commands
+  * Support overriding default locator conversion
+  * Support registering custom finders for SearchContext
+  * Support using custom element classes
+
+4.20.1 (2024-04-25)
+=========================
+
+* Returned accidentally removed DriverFinder.path and deprecated it.
+
+4.20.0 (2024-04-24)
+=========================
+
+* Add CDP for Chrome 124 and remove 121
+* Making Selenium Manager a thin wrapper (#13386)
+  * This change has been made to make it easier to maintain and improve, the interface has
+  changed and if users were invoking it, they might experience issues. Selenium Manager is
+  still in beta and these type of changes are expected.
+
+4.19.0 (2024-03-27)
+=========================
+
+* Add CDP for Chrome 123 and remove 120
+* Avoid over-escaping browser path (#13632)
+* Add full RBS support (#13234)
+
+4.18.1 (2024-02-19)
+=========================
+
+* Add CDP for Chrome 122 and remove 119
+
+4.18.0 (2024-02-19)
+=========================
+
+* Update documentation link in readme (#13570)
+* make suggested updates from rubocop
+
+4.17.0 (2024-01-22)
+=========================
+
+* Logger defaults output to stderr instead of stdout
+* Fully support Chrome 120+ old headless mode (#13271)
+* Add ruby to Selenium Manager input for tracking (see #13288)
+* Define default command_list (fixes #13307)
+* Fix issues with incorrectly named edge browser
+* Check for whether driver supports full page screenshots to error (#12799)
+* Add CDP for Chrome 121 and remove 118
+
+4.16.0 (2023-12-06)
+=========================
+
+Ruby:
+* Add RBS files to Ruby (#12844)
+* Convert binary locations for cygwin (#12618)
+* Allow Selenium Manager to work with Unix (#13161)
+* Extend RBS support for logger and log entry (#13192)
+* Update rules_ruby to the latest version (#13235)
+
+BiDi:
+  * Released selenium-devtools 0.120.0 (supports CDP v85, v118, v119, v120)
+
+Chrome:
+* Fix http proxy configuration for chrome (#13093)
+
+Firefox:
+* Delete 'lock' file in FF profile (#13090)
+
+4.15.0 (2023-11-01)
+=========================
+
+* Do not set browser binary in selenium manager if it is an empty string (#12738)
+* Add flaky condition to guards to mark unreliable tests
+* Rake update needs to build latest grid for running remote tests
+* Add CDP v119 and remove v116
+* Implement file downloads (#12979)
+
+4.14.0 (2023-10-09)
+=========================
+Ruby:
+  * allow users to access the full script of the atom directly
+
+BiDi:
+  * Released selenium-devtools 0.118.0 (supports CDP v85, v116, v117, v118)
+
+4.13.1 (2023-09-25)
+=========================
+Ruby:
+  * Fix bug preventing logging chromedriver to file
+
+4.13.0 (2023-09-25)
+=========================
+Ruby:
+  * Fix bug preventing using performance logging with chromium
+  * Allow users to set Selenium Manager path by environment variable (#12752)
+  * Allow service to be started before the driver
+  * remove deprecated driver extensions for location and network connection
+
+BiDi:
+  * Released selenium-devtools 0.117.0 (supports CDP v85, v115, v116, v117)
+
+4.12.0 (2023-08-31)
+=========================
+Ruby:
+  * Fix bug preventing good error messages in Selenium Manager when stdout empty
+  * Fix bug with Firefox not loading net/http library by default (#12506)
+  * Remove support for using capabilities in local drivers
+
+BiDi:
+  * Released selenium-devtools 0.116.0 (supports CDP v85, v114, v115, v116)
+
+4.11.0 (2023-07-31)
+=========================
+Ruby:
+  * Made network interception threads fail silently (#12226)
+  * Have Selenium Manager binary locate drivers on PATH (#12345)
+  * Add browser output from selenium manager to options (#12398)
+  * Remove deprecated code (#12417)
+BiDi:
+  * Released selenium-devtools 0.115.0 (supports CDP v85, v113, v114, v115)
+Edge:
+  * Adding ignore process match for IE Mode across bindings (#12279)
+
+4.10.0 (2023-06-07)
+=========================
+Ruby:
+  * Implement proxy support for Selenium Manager
+  * Prevent setting driver log level in Safari
+  * Change all Selenium Manager logging to :debug (#12145)
+  * Error messages include links to documentation
+  * Add custom error class for driver location and improve error logic
+
+BiDi:
+  * Released selenium-devtools 0.114.0 (supports CDP v85, v112, v113, v114)
+
+Edge:
+  * Add support for webview2
+
+4.9.1 (2023-05-08)
+=========================
+Ruby:
+  * Allow users to specify driver process output in Service class (#11964)
+  * Updated minimum required Ruby version to 3.0
+  * Selenium Logger defaults to :info and all debugging is now logged as :debug (#11967)
+  * Every logging entry can be ignored based on ID, not just warnings
+  * Logging entries can be filtered to allow or ignore specific IDs
+
+BiDi:
+  * Fix bug with loading devtools (#11931) (thanks Boris Petrov!)
+  * Released selenium-devtools 0.113.0 (supports CDP v85, v111, v112, v113)
+
+4.9.0 (2023-04-21)
+=========================
+Ruby:
+  * Fix devtools version fallback (#11869)
+  * Fix bug in selenium manager escaping back slashes in Windows (#11884)
+
+BiDi:
+  * Released selenium-devtools 0.112.0 (supports CDP v85, v110, v111, v112)
+
+4.8.6 (2023-03-29)
+=========================
+Ruby:
+  * Properly escape arguments passed to Selenium Manager
+
+4.8.5 (2023-03-28)
+=========================
+Ruby:
+  * Wrapping browser name in quotes when calling Selenium Manager
+
+4.8.4 (2023-03-28)
+=========================
+Ruby:
+  * Update the selenium-manager versions to fix an IE naming issue (#11828)
+
+4.8.3 (2023-03-26)
+=========================
+Ruby:
+  * Still need to use driver finder when using capabilities parameter
+  * Accommodate Driver Finder being sent something other than an Options instance
+
+4.8.2 (2023-03-24)
+=========================
+Ruby:
+  * Ruby driver finder (#11523)
+  * Using json output with Selenium Manager
+
+BiDi:
+  * Released selenium-devtools 0.111.0 (supports CDP v85, v109, v110, v111)
+
+4.8.1 (2023-02-17)
+=========================
+Ruby:
+  * Fix autoload of WebDriver::Remote::Bridge::COMMANDS
+  * Subclass is setting value before the superclass is setting it to nil
+  * Updating Selenium Manager binaries for 4.8.1 release
+
+BiDi:
+  * Released selenium-devtools 0.110.0 (supports CDP v85, v108, v109, v110)
+  * Close BiDi session on closing the last top-level browsing context
+  * Add filtering capability to LogInspector
+
+4.8.0 (2023-01-23)
+=========================
+Ruby:
+  * Allow updating instance variables on service classes
+  * Deprecate extract_service_args processing in service classes
+  * Fix bug preventing sending nil to #send_keys with Remote Driver
+  * Fix bug with IE specific methods not available to IE Driver
+  * Created Chromium superclass for Chrome and Edge
+  * Deprecated platform and version setters/getters in Capabilities class
+  * Revamped driver constructor logic
+  * Fix bug preventing using Safari Technology Preview when using SafariOptions
+  * Fix bug preventing more than one driver type to access Selenium Manager
+  * Defaults to using Options instead of Capabilities
+  * Make Options classes more strict for allowed arguments and types
+  * Removed previously deprecated actions class parameters
+  * Removed Location struct
+  * Add comment with name of large JS executions (#11038)
+  * update logger with link on how to use it (#11478)
+  * Deprecate #add_option for Option classes in favor of constructor and attr_accessor
+  * Deprecate all unrecognized capabilities for Options classes
+  * Deprecate support for :capabilities for local drivers
+  * Deprecate browser class methods for Capabilities
+  * Deprecate #headless! for Chrome and Firefox
+
+BiDi:
+  * Released selenium-devtools 0.109.0 (supports CDP v85, v107, v108, v109)
+  * Add LogInspector (#11368)
+  * Add Browsing context commands (#11446)
+
+4.7.1 (2022-12-02)
+=========================
+Ruby:
+  * Fix bug preventing selenium manager from using Internet Explorer
+
+4.7.0 (2022-12-01)
+=========================
+BiDi:
+  * Released selenium-devtools 0.108.0 (supports CDP v85, v106, v107, v108)
+  * Fix bug with socket stability
+
+Ruby:
+  * Remove dependency on ChildProcess gem in favor of native Process.spawn (#11251)
+  * Add support for Selenium Manager to work with IE Driver
+  * Improve error handling for Selenium Manager
+
+Safari:
+  * Fix bug preventing Safari Options from being used with Safari Technology Preview
+
+4.6.1 (2022-11-04)
+=========================
+Ruby:
+  * fix bug preventing selenium-manager from being executable by default
+
+4.6.0 (2022-11-04)
+=========================
+BiDi:
+  * Released selenium-devtools 0.107.0 (supports CDP v85, v105, v106, v107)
+
+Ruby:
+  * firefox scroll by amount is only failing on mac
+  * add initial support for selenium manager
+  * Revert "[rb] do not allow Select class to work with disabled selects"
+  * Make sure selenium-manager is packed into gem
+  * Fix platform list in #scroll_by guard
+
+4.5.0 (2022-09-28)
+=========================
+
+BiDi:
+  * Released selenium-devtools 0.105.0 (supports CDP v85, v103, v104, v105)
+  * Released selenium-devtools 0.106.0 (supports CDP v85, v104, v105, v106)
+  * Add HasBiDi support to Chrome
+
+Ruby:
+  * Fix bug in Platform code
+  * Update Select class to error when elements are disabled (#10812)
+
+Firefox:
+  * Add support for installing unsigned add-ons (#10265, thanks TamsilAmani!)
+  * Change accept_insecure_certificates to true by default (to match other bindings)
+  * Set debugger_address option to true by default
+
+Server:
+  * Add support for initializing server class with arguments and log level
+
+4.4.0 (2022-08-09)
 =========================
 
 BiDi:
@@ -1429,7 +1883,7 @@ Safari:
   * Replace 'libwebsocket' with 'websocket' gem. This should ensure
     support with recent Safari.
 Other:
-  * Fix Cygwin issue in PortProber/Firefox::Bianry (#4963)
+  * Fix Cygwin issue in PortProber/Firefox::Binary (#4963)
 
 2.27.2 (2012-12-11)
 ===================
@@ -1519,7 +1973,7 @@ IE:
 * Fix conflict with ActiveSupport's Object#load (#3819)
 * IE:
   * Default to standalone server executable, fall back to bundled DLLs.
-  * The 'nativeEvents' capabilitiy is exposed as :native_events in the Ruby client (mode still experimental).
+  * The 'nativeEvents' capability is exposed as :native_events in the Ruby client (mode still experimental).
 * Firefox:
   * Native events for Firefox 12.
   * Native events retained for Firefox 3.x, 10 and 11.
@@ -1659,7 +2113,7 @@ IE:
 ===================
 
 * Firefox:
-  * Now supports up to Firefox 11 (for syntesized events)
+  * Now supports up to Firefox 11 (for synthesized events)
   * Implicit waits now change how long we wait for alerts. This
     functionality will change in 2.16
   * Fix scrolling issue (#2700)
@@ -1853,7 +2307,7 @@ IE:
 2.1.0 (2011-07-18)
 ==================
 
-* Various improvments to the IE driver (#2049, #1870)
+* Various improvements to the IE driver (#2049, #1870)
 * Atoms fixes (#1776, #1972).
 * Synthetic mouse clicks do not propagate errors in onmouseover.
 
@@ -2003,7 +2457,7 @@ IE:
 * Cookie expiration dates are now handled correctly (#730)
 * Make Driver#bridge private, since this seems to be a common cause of confusion.
 * Add {Element,Remote::Capabilities}#as_json for Rails 3 (http://jonathanjulian.com/2010/04/rails-to_json-or-as_json/)
-* User can configure path to exectuables with {Firefox,Chrome}.path = "/some/path"
+* User can configure path to executables with {Firefox,Chrome}.path = "/some/path"
 * Added "chromium" as a possible name for the Chrome binary (#769)
 * Correctly set the HTTP client timeout (#768)
 * switch_to.window with block now handles exceptions and non-local returns.
diff -pruN 4.4.0-1/Gemfile 4.38.0-1/Gemfile
--- 4.4.0-1/Gemfile	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/Gemfile	2025-11-02 08:23:03.000000000 +0000
@@ -4,3 +4,9 @@ source 'https://rubygems.org'
 Dir["#{__dir__}/*.gemspec"].each do |spec|
   gemspec name: File.basename(spec, '.gemspec')
 end
+
+# ActiveSupport 8.x requires Ruby 3.2+ (dependency of Steep)
+gem 'activesupport', '~> 7.0', require: false, platforms: %i[mri mingw x64_mingw]
+gem 'curb', '~> 1.0.5', require: false, platforms: %i[mri mingw x64_mingw]
+gem 'debug', '~> 1.7', require: false, platforms: %i[mri mingw x64_mingw]
+gem 'steep', '~> 1.5.0', require: false, platforms: %i[mri mingw x64_mingw]
diff -pruN 4.4.0-1/LICENSE 4.38.0-1/LICENSE
--- 4.4.0-1/LICENSE	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/LICENSE	2025-11-02 08:23:03.000000000 +0000
@@ -187,7 +187,7 @@
       same "printed page" as the copyright notice for easier
       identification within third-party archives.
 
-   Copyright 2022 Software Freedom Conservancy (SFC)
+   Copyright 2025 Software Freedom Conservancy (SFC)
 
    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
diff -pruN 4.4.0-1/NOTICE 4.38.0-1/NOTICE
--- 4.4.0-1/NOTICE	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/NOTICE	2025-11-02 08:23:03.000000000 +0000
@@ -1,2 +1,2 @@
-Copyright 2011-2022 Software Freedom Conservancy
+Copyright 2011-2025 Software Freedom Conservancy
 Copyright 2004-2011 Selenium committers
diff -pruN 4.4.0-1/README.md 4.38.0-1/README.md
--- 4.4.0-1/README.md	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/README.md	2025-11-02 08:23:03.000000000 +0000
@@ -1,6 +1,6 @@
 # selenium-webdriver
 
-This gem provides Ruby bindings for Selenium and supports MRI >= 2.6
+This gem provides Ruby bindings for Selenium and supports MRI >= 3.2.
 
 ## Install
 
@@ -10,12 +10,12 @@ This gem provides Ruby bindings for Sele
 
 * https://rubygems.org/gems/selenium-webdriver
 * https://www.selenium.dev/selenium/docs/api/rb/index.html
-* https://github.com/SeleniumHQ/selenium/wiki/Ruby-Bindings
+* https://www.selenium.dev/documentation/?tab=ruby
 * https://github.com/SeleniumHQ/selenium/issues
 
 ## License
 
-Copyright 2009-2021 Software Freedom Conservancy
+Copyright 2009-2024 Software Freedom Conservancy
 
 Licensed to the Software Freedom Conservancy (SFC) under one
 or more contributor license agreements.  See the NOTICE file
Binary files 4.4.0-1/bin/linux/selenium-manager and 4.38.0-1/bin/linux/selenium-manager differ
Binary files 4.4.0-1/bin/macos/selenium-manager and 4.38.0-1/bin/macos/selenium-manager differ
Binary files 4.4.0-1/bin/windows/selenium-manager.exe and 4.38.0-1/bin/windows/selenium-manager.exe differ
diff -pruN 4.4.0-1/debian/changelog 4.38.0-1/debian/changelog
--- 4.4.0-1/debian/changelog	2022-08-19 21:20:11.000000000 +0000
+++ 4.38.0-1/debian/changelog	2025-11-04 16:36:34.000000000 +0000
@@ -1,3 +1,21 @@
+ruby-selenium-webdriver (4.38.0-1) unstable; urgency=medium
+
+  [ Debian Janitor ]
+  * Update standards version to 4.6.2, no changes needed.
+
+  [ Lucas Nussbaum ]
+  * d/salsa-ci.yml: remove custom variables as pipeline succeeds without them
+
+  [ Simon Quigley ]
+  * Team upload.
+  * New upstream release.
+  * Drop {XS,XB}-Ruby-Versions from control.
+  * Remove dependency on ruby-childprocess.
+  * Use ${ruby:Depends} for runtime dependencies.
+  * Add override to remove bin files.
+
+ -- Simon Quigley <tsimonq2@debian.org>  Tue, 04 Nov 2025 10:36:34 -0600
+
 ruby-selenium-webdriver (4.4.0-1) unstable; urgency=medium
 
   [ Cédric Boutillier ]
diff -pruN 4.4.0-1/debian/control 4.38.0-1/debian/control
--- 4.4.0-1/debian/control	2022-08-19 21:20:11.000000000 +0000
+++ 4.38.0-1/debian/control	2025-11-04 15:18:41.000000000 +0000
@@ -6,23 +6,18 @@ Uploaders: Utkarsh Gupta <utkarsh@debian
            Gabriela Pivetta <gpivetta99@gmail.com>
 Build-Depends: debhelper-compat (= 13),
                gem2deb,
-               ruby-childprocess,
                ruby-zip,
                ruby-websocket
-Standards-Version: 4.6.1
+Standards-Version: 4.6.2
 Vcs-Git: https://salsa.debian.org/ruby-team/ruby-selenium-webdriver.git
 Vcs-Browser: https://salsa.debian.org/ruby-team/ruby-selenium-webdriver
 Homepage: https://github.com/SeleniumHQ/selenium
 Testsuite: autopkgtest-pkg-ruby
-XS-Ruby-Versions: all
 Rules-Requires-Root: no
 
 Package: ruby-selenium-webdriver
 Architecture: all
-XB-Ruby-Versions: ${ruby:Versions}
-Depends: ruby-childprocess,
-         ruby-zip,
-         ruby-websocket,
+Depends: ${ruby:Depends},
          ${misc:Depends},
          ${shlibs:Depends}
 Recommends: chromium-driver | chromedriver | phantomjs
diff -pruN 4.4.0-1/debian/gbp.conf 4.38.0-1/debian/gbp.conf
--- 4.4.0-1/debian/gbp.conf	1970-01-01 00:00:00.000000000 +0000
+++ 4.38.0-1/debian/gbp.conf	2025-11-04 15:11:51.000000000 +0000
@@ -0,0 +1,4 @@
+[DEFAULT]
+debian-branch = debian/latest
+upstream-branch = upstream/latest
+pristine-tar = True
diff -pruN 4.4.0-1/debian/rules 4.38.0-1/debian/rules
--- 4.4.0-1/debian/rules	2022-08-19 20:43:26.000000000 +0000
+++ 4.38.0-1/debian/rules	2025-11-04 15:26:29.000000000 +0000
@@ -4,3 +4,7 @@ export GEM2DEB_TEST_RUNNER = --check-dep
 
 %:
 	dh $@ --buildsystem=ruby --with ruby
+
+override_dh_install:
+	dh_install
+	rm -rvf debian/ruby-selenium-webdriver/usr/bin/
diff -pruN 4.4.0-1/debian/salsa-ci.yml 4.38.0-1/debian/salsa-ci.yml
--- 4.4.0-1/debian/salsa-ci.yml	2022-08-19 20:43:26.000000000 +0000
+++ 4.38.0-1/debian/salsa-ci.yml	2025-11-04 15:11:51.000000000 +0000
@@ -1,8 +1,3 @@
 ---
 include:
-  - https://salsa.debian.org/salsa-ci-team/pipeline/raw/master/salsa-ci.yml
-  - https://salsa.debian.org/salsa-ci-team/pipeline/raw/master/pipeline-jobs.yml
-
-variables:
-  SALSA_CI_DISABLE_BLHC: 1
-  SALSA_CI_DISABLE_BUILD_PACKAGE_ANY: 1
+  - https://salsa.debian.org/ruby-team/meta/raw/master/salsa-ci.yml
diff -pruN 4.4.0-1/lib/selenium/server.rb 4.38.0-1/lib/selenium/server.rb
--- 4.4.0-1/lib/selenium/server.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/server.rb	2025-11-02 08:23:03.000000000 +0000
@@ -17,7 +17,8 @@
 # specific language governing permissions and limitations
 # under the License.
 
-require 'childprocess'
+require 'selenium/webdriver/common/child_process'
+require 'selenium/webdriver/common/port_prober'
 require 'selenium/webdriver/common/socket_poller'
 require 'net/http'
 
@@ -165,7 +166,7 @@ module Selenium
     # :standalone, #hub, #node
     #
 
-    attr_accessor :role, :port, :timeout, :background, :log
+    attr_accessor :role, :host, :port, :timeout, :background, :log
 
     #
     # @param [String] jar Path to the server jar.
@@ -182,15 +183,22 @@ module Selenium
     def initialize(jar, opts = {})
       raise Errno::ENOENT, jar unless File.exist?(jar)
 
-      @jar        = jar
-      @host       = '127.0.0.1'
-      @role       = opts.fetch(:role, 'standalone')
-      @port       = opts.fetch(:port, 4444)
-      @timeout    = opts.fetch(:timeout, 30)
+      @java = opts.fetch(:java, 'java') || 'java'
+      @jar = jar
+      @host = '127.0.0.1'
+      @role = opts.fetch(:role, 'standalone')
+      @port = opts.fetch(:port, WebDriver::PortProber.above(4444))
+      @timeout = opts.fetch(:timeout, 30)
       @background = opts.fetch(:background, false)
-      @log        = opts[:log]
-      @log_file   = nil
-      @additional_args = []
+      @additional_args = opts.fetch(:args, [])
+      @log = opts[:log]
+      if opts[:log_level]
+        @log ||= true
+        @additional_args << '--log-level'
+        @additional_args << opts[:log_level].to_s
+      end
+
+      @log_file = nil
     end
 
     def start
@@ -201,11 +209,6 @@ module Selenium
     end
 
     def stop
-      begin
-        Net::HTTP.get(@host, '/selenium-server/driver/?cmd=shutDownSeleniumServer', @port)
-      rescue Errno::ECONNREFUSED
-      end
-
       stop_process if @process
       poll_for_shutdown
 
@@ -227,13 +230,7 @@ module Selenium
     private
 
     def stop_process
-      return unless @process.alive?
-
-      begin
-        @process.poll_for_exit(5)
-      rescue ChildProcess::TimeoutError
-        @process.stop
-      end
+      @process.stop
     rescue Errno::ECHILD
       # already dead
     ensure
@@ -245,17 +242,13 @@ module Selenium
         # extract any additional_args that start with -D as options
         properties = @additional_args.dup - @additional_args.delete_if { |arg| arg[/^-D/] }
         args = ['-jar', @jar, @role, '--port', @port.to_s]
-        server_command = ['java'] + properties + args + @additional_args
-        cp = ChildProcess.build(*server_command)
-        WebDriver.logger.debug("Executing Process #{server_command}")
-
-        io = cp.io
+        server_command = [@java] + properties + args + @additional_args
+        cp = WebDriver::ChildProcess.build(*server_command)
 
         if @log.is_a?(String)
-          @log_file = File.open(@log, 'w')
-          io.stdout = io.stderr = @log_file
+          cp.io = @log
         elsif @log
-          io.inherit!
+          cp.io = :out
         end
 
         cp.detach = @background
diff -pruN 4.4.0-1/lib/selenium/webdriver/atoms/findElements.js 4.38.0-1/lib/selenium/webdriver/atoms/findElements.js
--- 4.4.0-1/lib/selenium/webdriver/atoms/findElements.js	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/atoms/findElements.js	2025-11-02 08:23:03.000000000 +0000
@@ -1,122 +1,55 @@
-function(){return (function(){var aa=this||self;function ba(a){return"string"==typeof a}function ca(a,b){a=a.split(".");var c=aa;a[0]in c||"undefined"==typeof c.execScript||c.execScript("var "+a[0]);for(var d;a.length&&(d=a.shift());)a.length||void 0===b?c[d]&&c[d]!==Object.prototype[d]?c=c[d]:c=c[d]={}:c[d]=b}
-function da(a){var b=typeof a;if("object"==b)if(a){if(a instanceof Array)return"array";if(a instanceof Object)return b;var c=Object.prototype.toString.call(a);if("[object Window]"==c)return"object";if("[object Array]"==c||"number"==typeof a.length&&"undefined"!=typeof a.splice&&"undefined"!=typeof a.propertyIsEnumerable&&!a.propertyIsEnumerable("splice"))return"array";if("[object Function]"==c||"undefined"!=typeof a.call&&"undefined"!=typeof a.propertyIsEnumerable&&!a.propertyIsEnumerable("call"))return"function"}else return"null";
-else if("function"==b&&"undefined"==typeof a.call)return"object";return b}function ea(a){return"function"==da(a)}function ha(a){var b=typeof a;return"object"==b&&null!=a||"function"==b}function ia(a,b,c){return a.call.apply(a.bind,arguments)}
-function ja(a,b,c){if(!a)throw Error();if(2<arguments.length){var d=Array.prototype.slice.call(arguments,2);return function(){var e=Array.prototype.slice.call(arguments);Array.prototype.unshift.apply(e,d);return a.apply(b,e)}}return function(){return a.apply(b,arguments)}}function ka(a,b,c){Function.prototype.bind&&-1!=Function.prototype.bind.toString().indexOf("native code")?ka=ia:ka=ja;return ka.apply(null,arguments)}
-function la(a,b){var c=Array.prototype.slice.call(arguments,1);return function(){var d=c.slice();d.push.apply(d,arguments);return a.apply(this,d)}}function k(a,b){function c(){}c.prototype=b.prototype;a.prototype=new c;a.prototype.constructor=a};/*
-
- The MIT License
-
- Copyright (c) 2007 Cybozu Labs, Inc.
- Copyright (c) 2012 Google Inc.
-
- Permission is hereby granted, free of charge, to any person obtaining a copy
- of this software and associated documentation files (the "Software"), to
- deal in the Software without restriction, including without limitation the
- rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- sell copies of the Software, and to permit persons to whom the Software is
- furnished to do so, subject to the following conditions:
-
- The above copyright notice and this permission notice shall be included in
- all copies or substantial portions of the Software.
-
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- IN THE SOFTWARE.
-*/
-function ma(a,b,c){this.a=a;this.b=b||1;this.f=c||1};var na;var oa=Array.prototype.indexOf?function(a,b){return Array.prototype.indexOf.call(a,b,void 0)}:function(a,b){if("string"===typeof a)return"string"!==typeof b||1!=b.length?-1:a.indexOf(b,0);for(var c=0;c<a.length;c++)if(c in a&&a[c]===b)return c;return-1},l=Array.prototype.forEach?function(a,b,c){Array.prototype.forEach.call(a,b,c)}:function(a,b,c){for(var d=a.length,e="string"===typeof a?a.split(""):a,f=0;f<d;f++)f in e&&b.call(c,e[f],f,a)},pa=Array.prototype.filter?function(a,b){return Array.prototype.filter.call(a,
-b,void 0)}:function(a,b){for(var c=a.length,d=[],e=0,f="string"===typeof a?a.split(""):a,g=0;g<c;g++)if(g in f){var h=f[g];b.call(void 0,h,g,a)&&(d[e++]=h)}return d},qa=Array.prototype.map?function(a,b){return Array.prototype.map.call(a,b,void 0)}:function(a,b){for(var c=a.length,d=Array(c),e="string"===typeof a?a.split(""):a,f=0;f<c;f++)f in e&&(d[f]=b.call(void 0,e[f],f,a));return d},ra=Array.prototype.reduce?function(a,b,c){return Array.prototype.reduce.call(a,b,c)}:function(a,b,c){var d=c;l(a,
-function(e,f){d=b.call(void 0,d,e,f,a)});return d},sa=Array.prototype.some?function(a,b){return Array.prototype.some.call(a,b,void 0)}:function(a,b){for(var c=a.length,d="string"===typeof a?a.split(""):a,e=0;e<c;e++)if(e in d&&b.call(void 0,d[e],e,a))return!0;return!1},ta=Array.prototype.every?function(a,b,c){return Array.prototype.every.call(a,b,c)}:function(a,b,c){for(var d=a.length,e="string"===typeof a?a.split(""):a,f=0;f<d;f++)if(f in e&&!b.call(c,e[f],f,a))return!1;return!0};
-function ua(a,b){a:{for(var c=a.length,d="string"===typeof a?a.split(""):a,e=0;e<c;e++)if(e in d&&b.call(void 0,d[e],e,a)){b=e;break a}b=-1}return 0>b?null:"string"===typeof a?a.charAt(b):a[b]}function va(a){return Array.prototype.concat.apply([],arguments)}function wa(a,b,c){return 2>=arguments.length?Array.prototype.slice.call(a,b):Array.prototype.slice.call(a,b,c)}function xa(a,b){a.sort(b||ya)}function ya(a,b){return a>b?1:a<b?-1:0};function za(a){var b=a.length-1;return 0<=b&&a.indexOf(" ",b)==b}var Aa=String.prototype.trim?function(a){return a.trim()}:function(a){return/^[\s\xa0]*([\s\S]*?)[\s\xa0]*$/.exec(a)[1]};
-function Ba(a,b){var c=0;a=Aa(String(a)).split(".");b=Aa(String(b)).split(".");for(var d=Math.max(a.length,b.length),e=0;0==c&&e<d;e++){var f=a[e]||"",g=b[e]||"";do{f=/(\d*)(\D*)(.*)/.exec(f)||["","","",""];g=/(\d*)(\D*)(.*)/.exec(g)||["","","",""];if(0==f[0].length&&0==g[0].length)break;c=Ca(0==f[1].length?0:parseInt(f[1],10),0==g[1].length?0:parseInt(g[1],10))||Ca(0==f[2].length,0==g[2].length)||Ca(f[2],g[2]);f=f[3];g=g[3]}while(0==c)}return c}function Ca(a,b){return a<b?-1:a>b?1:0};var q;a:{var Da=aa.navigator;if(Da){var Ea=Da.userAgent;if(Ea){q=Ea;break a}}q=""}function r(a){return-1!=q.indexOf(a)};function Fa(){return r("Firefox")||r("FxiOS")}function Ga(){return(r("Chrome")||r("CriOS"))&&!r("Edge")};function Ha(a){return String(a).replace(/\-([a-z])/g,function(b,c){return c.toUpperCase()})};function Ia(){return r("iPhone")&&!r("iPod")&&!r("iPad")};function Ja(a,b){var c=Ka;return Object.prototype.hasOwnProperty.call(c,a)?c[a]:c[a]=b(a)};var La=r("Opera"),t=r("Trident")||r("MSIE"),Ma=r("Edge"),Na=r("Gecko")&&!(-1!=q.toLowerCase().indexOf("webkit")&&!r("Edge"))&&!(r("Trident")||r("MSIE"))&&!r("Edge"),Oa=-1!=q.toLowerCase().indexOf("webkit")&&!r("Edge");function Pa(){var a=aa.document;return a?a.documentMode:void 0}var Qa;
-a:{var Ra="",Sa=function(){var a=q;if(Na)return/rv:([^\);]+)(\)|;)/.exec(a);if(Ma)return/Edge\/([\d\.]+)/.exec(a);if(t)return/\b(?:MSIE|rv)[: ]([^\);]+)(\)|;)/.exec(a);if(Oa)return/WebKit\/(\S+)/.exec(a);if(La)return/(?:Version)[ \/]?(\S+)/.exec(a)}();Sa&&(Ra=Sa?Sa[1]:"");if(t){var Ta=Pa();if(null!=Ta&&Ta>parseFloat(Ra)){Qa=String(Ta);break a}}Qa=Ra}var Ka={};function Ua(a){return Ja(a,function(){return 0<=Ba(Qa,a)})}var w;w=aa.document&&t?Pa():void 0;var x=t&&!(9<=Number(w)),Va=t&&!(8<=Number(w));function Wa(a,b,c,d){this.a=a;this.nodeName=c;this.nodeValue=d;this.nodeType=2;this.parentNode=this.ownerElement=b}function Xa(a,b){var c=Va&&"href"==b.nodeName?a.getAttribute(b.nodeName,2):b.nodeValue;return new Wa(b,a,b.nodeName,c)};function Ya(a){this.b=a;this.a=0}function Za(a){a=a.match($a);for(var b=0;b<a.length;b++)ab.test(a[b])&&a.splice(b,1);return new Ya(a)}var $a=/\$?(?:(?![0-9-\.])(?:\*|[\w-\.]+):)?(?![0-9-\.])(?:\*|[\w-\.]+)|\/\/|\.\.|::|\d+(?:\.\d*)?|\.\d+|"[^"]*"|'[^']*'|[!<>]=|\s+|./g,ab=/^\s/;function y(a,b){return a.b[a.a+(b||0)]}function z(a){return a.b[a.a++]}function bb(a){return a.b.length<=a.a};function cb(a,b){this.x=void 0!==a?a:0;this.y=void 0!==b?b:0}cb.prototype.ceil=function(){this.x=Math.ceil(this.x);this.y=Math.ceil(this.y);return this};cb.prototype.floor=function(){this.x=Math.floor(this.x);this.y=Math.floor(this.y);return this};cb.prototype.round=function(){this.x=Math.round(this.x);this.y=Math.round(this.y);return this};function db(a,b){this.width=a;this.height=b}db.prototype.aspectRatio=function(){return this.width/this.height};db.prototype.ceil=function(){this.width=Math.ceil(this.width);this.height=Math.ceil(this.height);return this};db.prototype.floor=function(){this.width=Math.floor(this.width);this.height=Math.floor(this.height);return this};db.prototype.round=function(){this.width=Math.round(this.width);this.height=Math.round(this.height);return this};function eb(a){return a?new fb(A(a)):na||(na=new fb)}function gb(a){for(;a&&1!=a.nodeType;)a=a.previousSibling;return a}function hb(a,b){if(!a||!b)return!1;if(a.contains&&1==b.nodeType)return a==b||a.contains(b);if("undefined"!=typeof a.compareDocumentPosition)return a==b||!!(a.compareDocumentPosition(b)&16);for(;b&&a!=b;)b=b.parentNode;return b==a}
-function ib(a,b){if(a==b)return 0;if(a.compareDocumentPosition)return a.compareDocumentPosition(b)&2?1:-1;if(t&&!(9<=Number(w))){if(9==a.nodeType)return-1;if(9==b.nodeType)return 1}if("sourceIndex"in a||a.parentNode&&"sourceIndex"in a.parentNode){var c=1==a.nodeType,d=1==b.nodeType;if(c&&d)return a.sourceIndex-b.sourceIndex;var e=a.parentNode,f=b.parentNode;return e==f?jb(a,b):!c&&hb(e,b)?-1*kb(a,b):!d&&hb(f,a)?kb(b,a):(c?a.sourceIndex:e.sourceIndex)-(d?b.sourceIndex:f.sourceIndex)}d=A(a);c=d.createRange();
-c.selectNode(a);c.collapse(!0);a=d.createRange();a.selectNode(b);a.collapse(!0);return c.compareBoundaryPoints(aa.Range.START_TO_END,a)}function kb(a,b){var c=a.parentNode;if(c==b)return-1;for(;b.parentNode!=c;)b=b.parentNode;return jb(b,a)}function jb(a,b){for(;b=b.previousSibling;)if(b==a)return-1;return 1}function A(a){return 9==a.nodeType?a:a.ownerDocument||a.document}function lb(a,b){a&&(a=a.parentNode);for(var c=0;a;){if(b(a))return a;a=a.parentNode;c++}return null}
-function fb(a){this.a=a||aa.document||document}fb.prototype.getElementsByTagName=function(a,b){return(b||this.a).getElementsByTagName(String(a))};
-function mb(a,b,c,d){a=d||a.a;var e=b&&"*"!=b?String(b).toUpperCase():"";if(a.querySelectorAll&&a.querySelector&&(e||c))c=a.querySelectorAll(e+(c?"."+c:""));else if(c&&a.getElementsByClassName)if(b=a.getElementsByClassName(c),e){a={};for(var f=d=0,g;g=b[f];f++)e==g.nodeName&&(a[d++]=g);a.length=d;c=a}else c=b;else if(b=a.getElementsByTagName(e||"*"),c){a={};for(f=d=0;g=b[f];f++){e=g.className;var h;if(h="function"==typeof e.split)h=0<=oa(e.split(/\s+/),c);h&&(a[d++]=g)}a.length=d;c=a}else c=b;return c}
-;function B(a){var b=null,c=a.nodeType;1==c&&(b=a.textContent,b=void 0==b||null==b?a.innerText:b,b=void 0==b||null==b?"":b);if("string"!=typeof b)if(x&&"title"==a.nodeName.toLowerCase()&&1==c)b=a.text;else if(9==c||1==c){a=9==c?a.documentElement:a.firstChild;c=0;var d=[];for(b="";a;){do 1!=a.nodeType&&(b+=a.nodeValue),x&&"title"==a.nodeName.toLowerCase()&&(b+=a.text),d[c++]=a;while(a=a.firstChild);for(;c&&!(a=d[--c].nextSibling););}}else b=a.nodeValue;return b}
-function nb(a,b,c){if(null===b)return!0;try{if(!a.getAttribute)return!1}catch(d){return!1}Va&&"class"==b&&(b="className");return null==c?!!a.getAttribute(b):a.getAttribute(b,2)==c}function ob(a,b,c,d,e){return(x?pb:qb).call(null,a,b,ba(c)?c:null,ba(d)?d:null,e||new C)}
-function pb(a,b,c,d,e){if(a instanceof rb||8==a.b||c&&null===a.b){var f=b.all;if(!f)return e;a=sb(a);if("*"!=a&&(f=b.getElementsByTagName(a),!f))return e;if(c){for(var g=[],h=0;b=f[h++];)nb(b,c,d)&&g.push(b);f=g}for(h=0;b=f[h++];)"*"==a&&"!"==b.tagName||e.add(b);return e}tb(a,b,c,d,e);return e}
-function qb(a,b,c,d,e){b.getElementsByName&&d&&"name"==c&&!t?(b=b.getElementsByName(d),l(b,function(f){a.a(f)&&e.add(f)})):b.getElementsByClassName&&d&&"class"==c?(b=b.getElementsByClassName(d),l(b,function(f){f.className==d&&a.a(f)&&e.add(f)})):a instanceof D?tb(a,b,c,d,e):b.getElementsByTagName&&(b=b.getElementsByTagName(a.f()),l(b,function(f){nb(f,c,d)&&e.add(f)}));return e}
-function ub(a,b,c,d,e){var f;if((a instanceof rb||8==a.b||c&&null===a.b)&&(f=b.childNodes)){var g=sb(a);if("*"!=g&&(f=pa(f,function(h){return h.tagName&&h.tagName.toLowerCase()==g}),!f))return e;c&&(f=pa(f,function(h){return nb(h,c,d)}));l(f,function(h){"*"==g&&("!"==h.tagName||"*"==g&&1!=h.nodeType)||e.add(h)});return e}return vb(a,b,c,d,e)}function vb(a,b,c,d,e){for(b=b.firstChild;b;b=b.nextSibling)nb(b,c,d)&&a.a(b)&&e.add(b);return e}
-function tb(a,b,c,d,e){for(b=b.firstChild;b;b=b.nextSibling)nb(b,c,d)&&a.a(b)&&e.add(b),tb(a,b,c,d,e)}function sb(a){if(a instanceof D){if(8==a.b)return"!";if(null===a.b)return"*"}return a.f()};function C(){this.b=this.a=null;this.m=0}function wb(a){this.f=a;this.a=this.b=null}function xb(a,b){if(!a.a)return b;if(!b.a)return a;var c=a.a;b=b.a;for(var d=null,e,f=0;c&&b;){e=c.f;var g=b.f;e==g||e instanceof Wa&&g instanceof Wa&&e.a==g.a?(e=c,c=c.a,b=b.a):0<ib(c.f,b.f)?(e=b,b=b.a):(e=c,c=c.a);(e.b=d)?d.a=e:a.a=e;d=e;f++}for(e=c||b;e;)e.b=d,d=d.a=e,f++,e=e.a;a.b=d;a.m=f;return a}function yb(a,b){b=new wb(b);b.a=a.a;a.b?a.a.b=b:a.a=a.b=b;a.a=b;a.m++}
-C.prototype.add=function(a){a=new wb(a);a.b=this.b;this.a?this.b.a=a:this.a=this.b=a;this.b=a;this.m++};function zb(a){return(a=a.a)?a.f:null}function Bb(a){return(a=zb(a))?B(a):""}function Cb(a,b){return new Db(a,!!b)}function Db(a,b){this.f=a;this.b=(this.A=b)?a.b:a.a;this.a=null}function E(a){var b=a.b;if(null==b)return null;var c=a.a=b;a.b=a.A?b.b:b.a;return c.f};function F(a){this.i=a;this.b=this.g=!1;this.f=null}function H(a){return"\n  "+a.toString().split("\n").join("\n  ")}function Eb(a,b){a.g=b}function Fb(a,b){a.b=b}function I(a,b){a=a.a(b);return a instanceof C?+Bb(a):+a}function J(a,b){a=a.a(b);return a instanceof C?Bb(a):""+a}function Gb(a,b){a=a.a(b);return a instanceof C?!!a.m:!!a};function Hb(a,b,c){F.call(this,a.i);this.c=a;this.h=b;this.v=c;this.g=b.g||c.g;this.b=b.b||c.b;this.c==Ib&&(c.b||c.g||4==c.i||0==c.i||!b.f?b.b||b.g||4==b.i||0==b.i||!c.f||(this.f={name:c.f.name,B:b}):this.f={name:b.f.name,B:c})}k(Hb,F);
-function Jb(a,b,c,d,e){b=b.a(d);c=c.a(d);var f;if(b instanceof C&&c instanceof C){b=Cb(b);for(d=E(b);d;d=E(b))for(e=Cb(c),f=E(e);f;f=E(e))if(a(B(d),B(f)))return!0;return!1}if(b instanceof C||c instanceof C){b instanceof C?(e=b,d=c):(e=c,d=b);f=Cb(e);for(var g=typeof d,h=E(f);h;h=E(f)){switch(g){case "number":h=+B(h);break;case "boolean":h=!!B(h);break;case "string":h=B(h);break;default:throw Error("Illegal primitive type for comparison.");}if(e==b&&a(h,d)||e==c&&a(d,h))return!0}return!1}return e?
-"boolean"==typeof b||"boolean"==typeof c?a(!!b,!!c):"number"==typeof b||"number"==typeof c?a(+b,+c):a(b,c):a(+b,+c)}Hb.prototype.a=function(a){return this.c.s(this.h,this.v,a)};Hb.prototype.toString=function(){var a="Binary Expression: "+this.c;a+=H(this.h);return a+=H(this.v)};function Kb(a,b,c,d){this.$=a;this.M=b;this.i=c;this.s=d}Kb.prototype.toString=function(){return this.$};var Lb={};
-function K(a,b,c,d){if(Lb.hasOwnProperty(a))throw Error("Binary operator already created: "+a);a=new Kb(a,b,c,d);return Lb[a.toString()]=a}K("div",6,1,function(a,b,c){return I(a,c)/I(b,c)});K("mod",6,1,function(a,b,c){return I(a,c)%I(b,c)});K("*",6,1,function(a,b,c){return I(a,c)*I(b,c)});K("+",5,1,function(a,b,c){return I(a,c)+I(b,c)});K("-",5,1,function(a,b,c){return I(a,c)-I(b,c)});K("<",4,2,function(a,b,c){return Jb(function(d,e){return d<e},a,b,c)});
-K(">",4,2,function(a,b,c){return Jb(function(d,e){return d>e},a,b,c)});K("<=",4,2,function(a,b,c){return Jb(function(d,e){return d<=e},a,b,c)});K(">=",4,2,function(a,b,c){return Jb(function(d,e){return d>=e},a,b,c)});var Ib=K("=",3,2,function(a,b,c){return Jb(function(d,e){return d==e},a,b,c,!0)});K("!=",3,2,function(a,b,c){return Jb(function(d,e){return d!=e},a,b,c,!0)});K("and",2,2,function(a,b,c){return Gb(a,c)&&Gb(b,c)});K("or",1,2,function(a,b,c){return Gb(a,c)||Gb(b,c)});function Mb(a,b){if(b.a.length&&4!=a.i)throw Error("Primary expression must evaluate to nodeset if filter has predicate(s).");F.call(this,a.i);this.c=a;this.h=b;this.g=a.g;this.b=a.b}k(Mb,F);Mb.prototype.a=function(a){a=this.c.a(a);return Nb(this.h,a)};Mb.prototype.toString=function(){var a="Filter:"+H(this.c);return a+=H(this.h)};function Ob(a,b){if(b.length<a.L)throw Error("Function "+a.l+" expects at least"+a.L+" arguments, "+b.length+" given");if(null!==a.H&&b.length>a.H)throw Error("Function "+a.l+" expects at most "+a.H+" arguments, "+b.length+" given");a.Z&&l(b,function(c,d){if(4!=c.i)throw Error("Argument "+d+" to function "+a.l+" is not of type Nodeset: "+c);});F.call(this,a.i);this.D=a;this.c=b;Eb(this,a.g||sa(b,function(c){return c.g}));Fb(this,a.Y&&!b.length||a.X&&!!b.length||sa(b,function(c){return c.b}))}
-k(Ob,F);Ob.prototype.a=function(a){return this.D.s.apply(null,va(a,this.c))};Ob.prototype.toString=function(){var a="Function: "+this.D;if(this.c.length){var b=ra(this.c,function(c,d){return c+H(d)},"Arguments:");a+=H(b)}return a};function Pb(a,b,c,d,e,f,g,h){this.l=a;this.i=b;this.g=c;this.Y=d;this.X=!1;this.s=e;this.L=f;this.H=void 0!==g?g:f;this.Z=!!h}Pb.prototype.toString=function(){return this.l};var Qb={};
-function L(a,b,c,d,e,f,g,h){if(Qb.hasOwnProperty(a))throw Error("Function already created: "+a+".");Qb[a]=new Pb(a,b,c,d,e,f,g,h)}L("boolean",2,!1,!1,function(a,b){return Gb(b,a)},1);L("ceiling",1,!1,!1,function(a,b){return Math.ceil(I(b,a))},1);L("concat",3,!1,!1,function(a,b){return ra(wa(arguments,1),function(c,d){return c+J(d,a)},"")},2,null);L("contains",2,!1,!1,function(a,b,c){b=J(b,a);a=J(c,a);return a=-1!=b.indexOf(a)},2);L("count",1,!1,!1,function(a,b){return b.a(a).m},1,1,!0);
-L("false",2,!1,!1,function(){return!1},0);L("floor",1,!1,!1,function(a,b){return Math.floor(I(b,a))},1);L("id",4,!1,!1,function(a,b){function c(h){if(x){var n=e.all[h];if(n){if(n.nodeType&&h==n.id)return n;if(n.length)return ua(n,function(u){return h==u.id})}return null}return e.getElementById(h)}var d=a.a,e=9==d.nodeType?d:d.ownerDocument;a=J(b,a).split(/\s+/);var f=[];l(a,function(h){h=c(h);!h||0<=oa(f,h)||f.push(h)});f.sort(ib);var g=new C;l(f,function(h){g.add(h)});return g},1);
-L("lang",2,!1,!1,function(){return!1},1);L("last",1,!0,!1,function(a){if(1!=arguments.length)throw Error("Function last expects ()");return a.f},0);L("local-name",3,!1,!0,function(a,b){return(a=b?zb(b.a(a)):a.a)?a.localName||a.nodeName.toLowerCase():""},0,1,!0);L("name",3,!1,!0,function(a,b){return(a=b?zb(b.a(a)):a.a)?a.nodeName.toLowerCase():""},0,1,!0);L("namespace-uri",3,!0,!1,function(){return""},0,1,!0);
-L("normalize-space",3,!1,!0,function(a,b){return(b?J(b,a):B(a.a)).replace(/[\s\xa0]+/g," ").replace(/^\s+|\s+$/g,"")},0,1);L("not",2,!1,!1,function(a,b){return!Gb(b,a)},1);L("number",1,!1,!0,function(a,b){return b?I(b,a):+B(a.a)},0,1);L("position",1,!0,!1,function(a){return a.b},0);L("round",1,!1,!1,function(a,b){return Math.round(I(b,a))},1);L("starts-with",2,!1,!1,function(a,b,c){b=J(b,a);a=J(c,a);return 0==b.lastIndexOf(a,0)},2);L("string",3,!1,!0,function(a,b){return b?J(b,a):B(a.a)},0,1);
-L("string-length",1,!1,!0,function(a,b){return(b?J(b,a):B(a.a)).length},0,1);L("substring",3,!1,!1,function(a,b,c,d){c=I(c,a);if(isNaN(c)||Infinity==c||-Infinity==c)return"";d=d?I(d,a):Infinity;if(isNaN(d)||-Infinity===d)return"";c=Math.round(c)-1;var e=Math.max(c,0);a=J(b,a);return Infinity==d?a.substring(e):a.substring(e,c+Math.round(d))},2,3);L("substring-after",3,!1,!1,function(a,b,c){b=J(b,a);a=J(c,a);c=b.indexOf(a);return-1==c?"":b.substring(c+a.length)},2);
-L("substring-before",3,!1,!1,function(a,b,c){b=J(b,a);a=J(c,a);a=b.indexOf(a);return-1==a?"":b.substring(0,a)},2);L("sum",1,!1,!1,function(a,b){a=Cb(b.a(a));b=0;for(var c=E(a);c;c=E(a))b+=+B(c);return b},1,1,!0);L("translate",3,!1,!1,function(a,b,c,d){b=J(b,a);c=J(c,a);var e=J(d,a);a={};for(d=0;d<c.length;d++){var f=c.charAt(d);f in a||(a[f]=e.charAt(d))}c="";for(d=0;d<b.length;d++)f=b.charAt(d),c+=f in a?a[f]:f;return c},3);L("true",2,!1,!1,function(){return!0},0);function D(a,b){this.h=a;this.c=void 0!==b?b:null;this.b=null;switch(a){case "comment":this.b=8;break;case "text":this.b=3;break;case "processing-instruction":this.b=7;break;case "node":break;default:throw Error("Unexpected argument");}}function Rb(a){return"comment"==a||"text"==a||"processing-instruction"==a||"node"==a}D.prototype.a=function(a){return null===this.b||this.b==a.nodeType};D.prototype.f=function(){return this.h};
-D.prototype.toString=function(){var a="Kind Test: "+this.h;null===this.c||(a+=H(this.c));return a};function Sb(a){F.call(this,3);this.c=a.substring(1,a.length-1)}k(Sb,F);Sb.prototype.a=function(){return this.c};Sb.prototype.toString=function(){return"Literal: "+this.c};function rb(a,b){this.l=a.toLowerCase();a="*"==this.l?"*":"http://www.w3.org/1999/xhtml";this.c=b?b.toLowerCase():a}rb.prototype.a=function(a){var b=a.nodeType;if(1!=b&&2!=b)return!1;b=void 0!==a.localName?a.localName:a.nodeName;return"*"!=this.l&&this.l!=b.toLowerCase()?!1:"*"==this.c?!0:this.c==(a.namespaceURI?a.namespaceURI.toLowerCase():"http://www.w3.org/1999/xhtml")};rb.prototype.f=function(){return this.l};
-rb.prototype.toString=function(){return"Name Test: "+("http://www.w3.org/1999/xhtml"==this.c?"":this.c+":")+this.l};function Tb(a){F.call(this,1);this.c=a}k(Tb,F);Tb.prototype.a=function(){return this.c};Tb.prototype.toString=function(){return"Number: "+this.c};function Ub(a,b){F.call(this,a.i);this.h=a;this.c=b;this.g=a.g;this.b=a.b;1==this.c.length&&(a=this.c[0],a.G||a.c!=Vb||(a=a.v,"*"!=a.f()&&(this.f={name:a.f(),B:null})))}k(Ub,F);function Wb(){F.call(this,4)}k(Wb,F);Wb.prototype.a=function(a){var b=new C;a=a.a;9==a.nodeType?b.add(a):b.add(a.ownerDocument);return b};Wb.prototype.toString=function(){return"Root Helper Expression"};function Xb(){F.call(this,4)}k(Xb,F);Xb.prototype.a=function(a){var b=new C;b.add(a.a);return b};Xb.prototype.toString=function(){return"Context Helper Expression"};
-function Yb(a){return"/"==a||"//"==a}Ub.prototype.a=function(a){var b=this.h.a(a);if(!(b instanceof C))throw Error("Filter expression must evaluate to nodeset.");a=this.c;for(var c=0,d=a.length;c<d&&b.m;c++){var e=a[c],f=Cb(b,e.c.A);if(e.g||e.c!=Zb)if(e.g||e.c!=$b){var g=E(f);for(b=e.a(new ma(g));null!=(g=E(f));)g=e.a(new ma(g)),b=xb(b,g)}else g=E(f),b=e.a(new ma(g));else{for(g=E(f);(b=E(f))&&(!g.contains||g.contains(b))&&b.compareDocumentPosition(g)&8;g=b);b=e.a(new ma(g))}}return b};
-Ub.prototype.toString=function(){var a="Path Expression:"+H(this.h);if(this.c.length){var b=ra(this.c,function(c,d){return c+H(d)},"Steps:");a+=H(b)}return a};function ac(a,b){this.a=a;this.A=!!b}
-function Nb(a,b,c){for(c=c||0;c<a.a.length;c++)for(var d=a.a[c],e=Cb(b),f=b.m,g,h=0;g=E(e);h++){var n=a.A?f-h:h+1;g=d.a(new ma(g,n,f));if("number"==typeof g)n=n==g;else if("string"==typeof g||"boolean"==typeof g)n=!!g;else if(g instanceof C)n=0<g.m;else throw Error("Predicate.evaluate returned an unexpected type.");if(!n){n=e;g=n.f;var u=n.a;if(!u)throw Error("Next must be called at least once before remove.");var p=u.b;u=u.a;p?p.a=u:g.a=u;u?u.b=p:g.b=p;g.m--;n.a=null}}return b}
-ac.prototype.toString=function(){return ra(this.a,function(a,b){return a+H(b)},"Predicates:")};function bc(a,b,c,d){F.call(this,4);this.c=a;this.v=b;this.h=c||new ac([]);this.G=!!d;b=this.h;b=0<b.a.length?b.a[0].f:null;a.ca&&b&&(a=b.name,a=x?a.toLowerCase():a,this.f={name:a,B:b.B});a:{a=this.h;for(b=0;b<a.a.length;b++)if(c=a.a[b],c.g||1==c.i||0==c.i){a=!0;break a}a=!1}this.g=a}k(bc,F);
-bc.prototype.a=function(a){var b=a.a,c=this.f,d=null,e=null,f=0;c&&(d=c.name,e=c.B?J(c.B,a):null,f=1);if(this.G)if(this.g||this.c!=cc)if(b=Cb((new bc(dc,new D("node"))).a(a)),c=E(b))for(a=this.s(c,d,e,f);null!=(c=E(b));)a=xb(a,this.s(c,d,e,f));else a=new C;else a=ob(this.v,b,d,e),a=Nb(this.h,a,f);else a=this.s(a.a,d,e,f);return a};bc.prototype.s=function(a,b,c,d){a=this.c.D(this.v,a,b,c);return a=Nb(this.h,a,d)};
-bc.prototype.toString=function(){var a="Step:"+H("Operator: "+(this.G?"//":"/"));this.c.l&&(a+=H("Axis: "+this.c));a+=H(this.v);if(this.h.a.length){var b=ra(this.h.a,function(c,d){return c+H(d)},"Predicates:");a+=H(b)}return a};function ec(a,b,c,d){this.l=a;this.D=b;this.A=c;this.ca=d}ec.prototype.toString=function(){return this.l};var fc={};function M(a,b,c,d){if(fc.hasOwnProperty(a))throw Error("Axis already created: "+a);b=new ec(a,b,c,!!d);return fc[a]=b}
-M("ancestor",function(a,b){for(var c=new C;b=b.parentNode;)a.a(b)&&yb(c,b);return c},!0);M("ancestor-or-self",function(a,b){var c=new C;do a.a(b)&&yb(c,b);while(b=b.parentNode);return c},!0);
-var Vb=M("attribute",function(a,b){var c=new C,d=a.f();if("style"==d&&x&&b.style)return c.add(new Wa(b.style,b,"style",b.style.cssText)),c;var e=b.attributes;if(e)if(a instanceof D&&null===a.b||"*"==d)for(a=0;d=e[a];a++)x?d.nodeValue&&c.add(Xa(b,d)):c.add(d);else(d=e.getNamedItem(d))&&(x?d.nodeValue&&c.add(Xa(b,d)):c.add(d));return c},!1),cc=M("child",function(a,b,c,d,e){return(x?ub:vb).call(null,a,b,ba(c)?c:null,ba(d)?d:null,e||new C)},!1,!0);M("descendant",ob,!1,!0);
-var dc=M("descendant-or-self",function(a,b,c,d){var e=new C;nb(b,c,d)&&a.a(b)&&e.add(b);return ob(a,b,c,d,e)},!1,!0),Zb=M("following",function(a,b,c,d){var e=new C;do for(var f=b;f=f.nextSibling;)nb(f,c,d)&&a.a(f)&&e.add(f),e=ob(a,f,c,d,e);while(b=b.parentNode);return e},!1,!0);M("following-sibling",function(a,b){for(var c=new C;b=b.nextSibling;)a.a(b)&&c.add(b);return c},!1);M("namespace",function(){return new C},!1);
-var gc=M("parent",function(a,b){var c=new C;if(9==b.nodeType)return c;if(2==b.nodeType)return c.add(b.ownerElement),c;b=b.parentNode;a.a(b)&&c.add(b);return c},!1),$b=M("preceding",function(a,b,c,d){var e=new C,f=[];do f.unshift(b);while(b=b.parentNode);for(var g=1,h=f.length;g<h;g++){var n=[];for(b=f[g];b=b.previousSibling;)n.unshift(b);for(var u=0,p=n.length;u<p;u++)b=n[u],nb(b,c,d)&&a.a(b)&&e.add(b),e=ob(a,b,c,d,e)}return e},!0,!0);
-M("preceding-sibling",function(a,b){for(var c=new C;b=b.previousSibling;)a.a(b)&&yb(c,b);return c},!0);var hc=M("self",function(a,b){var c=new C;a.a(b)&&c.add(b);return c},!1);function ic(a){F.call(this,1);this.c=a;this.g=a.g;this.b=a.b}k(ic,F);ic.prototype.a=function(a){return-I(this.c,a)};ic.prototype.toString=function(){return"Unary Expression: -"+H(this.c)};function jc(a){F.call(this,4);this.c=a;Eb(this,sa(this.c,function(b){return b.g}));Fb(this,sa(this.c,function(b){return b.b}))}k(jc,F);jc.prototype.a=function(a){var b=new C;l(this.c,function(c){c=c.a(a);if(!(c instanceof C))throw Error("Path expression must evaluate to NodeSet.");b=xb(b,c)});return b};jc.prototype.toString=function(){return ra(this.c,function(a,b){return a+H(b)},"Union Expression:")};function kc(a,b){this.a=a;this.b=b}function lc(a){for(var b,c=[];;){N(a,"Missing right hand side of binary expression.");b=mc(a);var d=z(a.a);if(!d)break;var e=(d=Lb[d]||null)&&d.M;if(!e){a.a.a--;break}for(;c.length&&e<=c[c.length-1].M;)b=new Hb(c.pop(),c.pop(),b);c.push(b,d)}for(;c.length;)b=new Hb(c.pop(),c.pop(),b);return b}function N(a,b){if(bb(a.a))throw Error(b);}function nc(a,b){a=z(a.a);if(a!=b)throw Error("Bad token, expected: "+b+" got: "+a);}
-function oc(a){a=z(a.a);if(")"!=a)throw Error("Bad token: "+a);}function rc(a){a=z(a.a);if(2>a.length)throw Error("Unclosed literal string");return new Sb(a)}
-function sc(a){var b=[];if(Yb(y(a.a))){var c=z(a.a);var d=y(a.a);if("/"==c&&(bb(a.a)||"."!=d&&".."!=d&&"@"!=d&&"*"!=d&&!/(?![0-9])[\w]/.test(d)))return new Wb;d=new Wb;N(a,"Missing next location step.");c=tc(a,c);b.push(c)}else{a:{c=y(a.a);d=c.charAt(0);switch(d){case "$":throw Error("Variable reference not allowed in HTML XPath");case "(":z(a.a);c=lc(a);N(a,'unclosed "("');nc(a,")");break;case '"':case "'":c=rc(a);break;default:if(isNaN(+c))if(!Rb(c)&&/(?![0-9])[\w]/.test(d)&&"("==y(a.a,1)){c=z(a.a);
-c=Qb[c]||null;z(a.a);for(d=[];")"!=y(a.a);){N(a,"Missing function argument list.");d.push(lc(a));if(","!=y(a.a))break;z(a.a)}N(a,"Unclosed function argument list.");oc(a);c=new Ob(c,d)}else{c=null;break a}else c=new Tb(+z(a.a))}"["==y(a.a)&&(d=new ac(uc(a)),c=new Mb(c,d))}if(c)if(Yb(y(a.a)))d=c;else return c;else c=tc(a,"/"),d=new Xb,b.push(c)}for(;Yb(y(a.a));)c=z(a.a),N(a,"Missing next location step."),c=tc(a,c),b.push(c);return new Ub(d,b)}
-function tc(a,b){if("/"!=b&&"//"!=b)throw Error('Step op should be "/" or "//"');if("."==y(a.a)){var c=new bc(hc,new D("node"));z(a.a);return c}if(".."==y(a.a))return c=new bc(gc,new D("node")),z(a.a),c;if("@"==y(a.a)){var d=Vb;z(a.a);N(a,"Missing attribute name")}else if("::"==y(a.a,1)){if(!/(?![0-9])[\w]/.test(y(a.a).charAt(0)))throw Error("Bad token: "+z(a.a));var e=z(a.a);d=fc[e]||null;if(!d)throw Error("No axis with name: "+e);z(a.a);N(a,"Missing node name")}else d=cc;e=y(a.a);if(/(?![0-9])[\w\*]/.test(e.charAt(0)))if("("==
-y(a.a,1)){if(!Rb(e))throw Error("Invalid node type: "+e);e=z(a.a);if(!Rb(e))throw Error("Invalid type name: "+e);nc(a,"(");N(a,"Bad nodetype");var f=y(a.a).charAt(0),g=null;if('"'==f||"'"==f)g=rc(a);N(a,"Bad nodetype");oc(a);e=new D(e,g)}else if(e=z(a.a),f=e.indexOf(":"),-1==f)e=new rb(e);else{g=e.substring(0,f);if("*"==g)var h="*";else if(h=a.b(g),!h)throw Error("Namespace prefix not declared: "+g);e=e.substr(f+1);e=new rb(e,h)}else throw Error("Bad token: "+z(a.a));a=new ac(uc(a),d.A);return c||
-new bc(d,e,a,"//"==b)}function uc(a){for(var b=[];"["==y(a.a);){z(a.a);N(a,"Missing predicate expression.");var c=lc(a);b.push(c);N(a,"Unclosed predicate expression.");nc(a,"]")}return b}function mc(a){if("-"==y(a.a))return z(a.a),new ic(mc(a));var b=sc(a);if("|"!=y(a.a))a=b;else{for(b=[b];"|"==z(a.a);)N(a,"Missing next union location path."),b.push(sc(a));a.a.a--;a=new jc(b)}return a};function vc(a){switch(a.nodeType){case 1:return la(wc,a);case 9:return vc(a.documentElement);case 11:case 10:case 6:case 12:return xc;default:return a.parentNode?vc(a.parentNode):xc}}function xc(){return null}function wc(a,b){if(a.prefix==b)return a.namespaceURI||"http://www.w3.org/1999/xhtml";var c=a.getAttributeNode("xmlns:"+b);return c&&c.specified?c.value||null:a.parentNode&&9!=a.parentNode.nodeType?wc(a.parentNode,b):null};function yc(a,b){if(!a.length)throw Error("Empty XPath expression.");a=Za(a);if(bb(a))throw Error("Invalid XPath expression.");b?ea(b)||(b=ka(b.lookupNamespaceURI,b)):b=function(){return null};var c=lc(new kc(a,b));if(!bb(a))throw Error("Bad token: "+z(a));this.evaluate=function(d,e){d=c.a(new ma(d));return new O(d,e)}}
-function O(a,b){if(0==b)if(a instanceof C)b=4;else if("string"==typeof a)b=2;else if("number"==typeof a)b=1;else if("boolean"==typeof a)b=3;else throw Error("Unexpected evaluation result.");if(2!=b&&1!=b&&3!=b&&!(a instanceof C))throw Error("value could not be converted to the specified type");this.resultType=b;switch(b){case 2:this.stringValue=a instanceof C?Bb(a):""+a;break;case 1:this.numberValue=a instanceof C?+Bb(a):+a;break;case 3:this.booleanValue=a instanceof C?0<a.m:!!a;break;case 4:case 5:case 6:case 7:var c=
-Cb(a);var d=[];for(var e=E(c);e;e=E(c))d.push(e instanceof Wa?e.a:e);this.snapshotLength=a.m;this.invalidIteratorState=!1;break;case 8:case 9:a=zb(a);this.singleNodeValue=a instanceof Wa?a.a:a;break;default:throw Error("Unknown XPathResult type.");}var f=0;this.iterateNext=function(){if(4!=b&&5!=b)throw Error("iterateNext called with wrong result type");return f>=d.length?null:d[f++]};this.snapshotItem=function(g){if(6!=b&&7!=b)throw Error("snapshotItem called with wrong result type");return g>=d.length||
-0>g?null:d[g]}}O.ANY_TYPE=0;O.NUMBER_TYPE=1;O.STRING_TYPE=2;O.BOOLEAN_TYPE=3;O.UNORDERED_NODE_ITERATOR_TYPE=4;O.ORDERED_NODE_ITERATOR_TYPE=5;O.UNORDERED_NODE_SNAPSHOT_TYPE=6;O.ORDERED_NODE_SNAPSHOT_TYPE=7;O.ANY_UNORDERED_NODE_TYPE=8;O.FIRST_ORDERED_NODE_TYPE=9;function zc(a){this.lookupNamespaceURI=vc(a)}
-function Ac(a,b){a=a||aa;var c=a.Document&&a.Document.prototype||a.document;if(!c.evaluate||b)a.XPathResult=O,c.evaluate=function(d,e,f,g){return(new yc(d,f)).evaluate(e,g)},c.createExpression=function(d,e){return new yc(d,e)},c.createNSResolver=function(d){return new zc(d)}}ca("wgxpath.install",Ac);ca("wgxpath.install",Ac);var Bc=window;function P(a,b){this.code=a;this.a=Q[a]||Cc;this.message=b||"";a=this.a.replace(/((?:^|\s+)[a-z])/g,function(c){return c.toUpperCase().replace(/^[\s\xa0]+/g,"")});b=a.length-5;if(0>b||a.indexOf("Error",b)!=b)a+="Error";this.name=a;a=Error(this.message);a.name=this.name;this.stack=a.stack||""}k(P,Error);var Cc="unknown error",Q={15:"element not selectable",11:"element not visible"};Q[31]=Cc;Q[30]=Cc;Q[24]="invalid cookie domain";Q[29]="invalid element coordinates";Q[12]="invalid element state";
-Q[32]="invalid selector";Q[51]="invalid selector";Q[52]="invalid selector";Q[17]="javascript error";Q[405]="unsupported operation";Q[34]="move target out of bounds";Q[27]="no such alert";Q[7]="no such element";Q[8]="no such frame";Q[23]="no such window";Q[28]="script timeout";Q[33]="session not created";Q[10]="stale element reference";Q[21]="timeout";Q[25]="unable to set cookie";Q[26]="unexpected alert open";Q[13]=Cc;Q[9]="unknown command";var Dc={C:function(a){return!(!a.querySelectorAll||!a.querySelector)},o:function(a,b){if(!a)throw new P(32,"No class name specified");a=Aa(a);if(-1!==a.indexOf(" "))throw new P(32,"Compound class names not permitted");if(Dc.C(b))try{return b.querySelector("."+a.replace(/\./g,"\\."))||null}catch(c){throw new P(32,"An invalid or illegal class name was specified");}a=mb(eb(b),"*",a,b);return a.length?a[0]:null},j:function(a,b){if(!a)throw new P(32,"No class name specified");a=Aa(a);if(-1!==a.indexOf(" "))throw new P(32,
-"Compound class names not permitted");if(Dc.C(b))try{return b.querySelectorAll("."+a.replace(/\./g,"\\."))}catch(c){throw new P(32,"An invalid or illegal class name was specified");}return mb(eb(b),"*",a,b)}};var Ec=Fa(),Fc=Ia()||r("iPod"),Gc=r("iPad"),Hc=r("Android")&&!(Ga()||Fa()||r("Opera")||r("Silk")),Ic=Ga(),Jc=r("Safari")&&!(Ga()||r("Coast")||r("Opera")||r("Edge")||r("Edg/")||r("OPR")||Fa()||r("Silk")||r("Android"))&&!(Ia()||r("iPad")||r("iPod"));function Kc(a){return(a=a.exec(q))?a[1]:""}(function(){if(Ec)return Kc(/Firefox\/([0-9.]+)/);if(t||Ma||La)return Qa;if(Ic)return Ia()||r("iPad")||r("iPod")?Kc(/CriOS\/([0-9.]+)/):Kc(/Chrome\/([0-9.]+)/);if(Jc&&!(Ia()||r("iPad")||r("iPod")))return Kc(/Version\/([0-9.]+)/);if(Fc||Gc){var a=/Version\/(\S+).*Mobile\/(\S+)/.exec(q);if(a)return a[1]+"."+a[2]}else if(Hc)return(a=Kc(/Android\s+([0-9.]+)/))?a:Kc(/Version\/([0-9.]+)/);return""})();var Lc=t&&!(8<=Number(w)),Mc=t&&!(9<=Number(w));var Nc={o:function(a,b){if(!ea(b.querySelector)&&t&&(t?0<=Ba(w,8):Ua(8))&&!ha(b.querySelector))throw Error("CSS selection is not supported");if(!a)throw new P(32,"No selector specified");a=Aa(a);try{var c=b.querySelector(a)}catch(d){throw new P(32,"An invalid or illegal selector was specified");}return c&&1==c.nodeType?c:null},j:function(a,b){if(!ea(b.querySelectorAll)&&t&&(t?0<=Ba(w,8):Ua(8))&&!ha(b.querySelector))throw Error("CSS selection is not supported");if(!a)throw new P(32,"No selector specified");
-a=Aa(a);try{return b.querySelectorAll(a)}catch(c){throw new P(32,"An invalid or illegal selector was specified");}}};var Oc={aliceblue:"#f0f8ff",antiquewhite:"#faebd7",aqua:"#00ffff",aquamarine:"#7fffd4",azure:"#f0ffff",beige:"#f5f5dc",bisque:"#ffe4c4",black:"#000000",blanchedalmond:"#ffebcd",blue:"#0000ff",blueviolet:"#8a2be2",brown:"#a52a2a",burlywood:"#deb887",cadetblue:"#5f9ea0",chartreuse:"#7fff00",chocolate:"#d2691e",coral:"#ff7f50",cornflowerblue:"#6495ed",cornsilk:"#fff8dc",crimson:"#dc143c",cyan:"#00ffff",darkblue:"#00008b",darkcyan:"#008b8b",darkgoldenrod:"#b8860b",darkgray:"#a9a9a9",darkgreen:"#006400",
+function(){return (function(){var h=this||self;
+function aa(a){var b=typeof a;if("object"==b)if(a){if(a instanceof Array)return"array";if(a instanceof Object)return b;var c=Object.prototype.toString.call(a);if("[object Window]"==c)return"object";if("[object Array]"==c||"number"==typeof a.length&&"undefined"!=typeof a.splice&&"undefined"!=typeof a.propertyIsEnumerable&&!a.propertyIsEnumerable("splice"))return"array";if("[object Function]"==c||"undefined"!=typeof a.call&&"undefined"!=typeof a.propertyIsEnumerable&&!a.propertyIsEnumerable("call"))return"function"}else return"null";else if("function"==
+b&&"undefined"==typeof a.call)return"object";return b}function l(a){return"function"==aa(a)}function n(a){var b=typeof a;return"object"==b&&null!=a||"function"==b}function ba(a,b){function c(){}c.prototype=b.prototype;a.prototype=new c;a.prototype.constructor=a};var ca=window;function q(a,b){this.code=a;this.a=r[a]||u;this.message=b||"";a=this.a.replace(/((?:^|\s+)[a-z])/g,function(c){return c.toUpperCase().replace(/^[\s\xa0]+/g,"")});b=a.length-5;if(0>b||a.indexOf("Error",b)!=b)a+="Error";this.name=a;a=Error(this.message);a.name=this.name;this.stack=a.stack||""}ba(q,Error);var u="unknown error",r={15:"element not selectable",11:"element not visible"};r[31]=u;r[30]=u;r[24]="invalid cookie domain";r[29]="invalid element coordinates";r[12]="invalid element state";
+r[32]="invalid selector";r[51]="invalid selector";r[52]="invalid selector";r[17]="javascript error";r[405]="unsupported operation";r[34]="move target out of bounds";r[27]="no such alert";r[7]="no such element";r[8]="no such frame";r[23]="no such window";r[28]="script timeout";r[33]="session not created";r[10]="stale element reference";r[21]="timeout";r[25]="unable to set cookie";r[26]="unexpected alert open";r[13]=u;r[9]="unknown command";var da;var ea=Array.prototype.indexOf?function(a,b){return Array.prototype.indexOf.call(a,b,void 0)}:function(a,b){if("string"===typeof a)return"string"!==typeof b||1!=b.length?-1:a.indexOf(b,0);for(var c=0;c<a.length;c++)if(c in a&&a[c]===b)return c;return-1},w=Array.prototype.forEach?function(a,b,c){Array.prototype.forEach.call(a,b,c)}:function(a,b,c){for(var d=a.length,e="string"===typeof a?a.split(""):a,f=0;f<d;f++)f in e&&b.call(c,e[f],f,a)},fa=Array.prototype.filter?function(a,b){return Array.prototype.filter.call(a,
+b,void 0)}:function(a,b){for(var c=a.length,d=[],e=0,f="string"===typeof a?a.split(""):a,g=0;g<c;g++)if(g in f){var k=f[g];b.call(void 0,k,g,a)&&(d[e++]=k)}return d},ha=Array.prototype.map?function(a,b){return Array.prototype.map.call(a,b,void 0)}:function(a,b){for(var c=a.length,d=Array(c),e="string"===typeof a?a.split(""):a,f=0;f<c;f++)f in e&&(d[f]=b.call(void 0,e[f],f,a));return d},ia=Array.prototype.some?function(a,b){return Array.prototype.some.call(a,b,void 0)}:function(a,b){for(var c=a.length,
+d="string"===typeof a?a.split(""):a,e=0;e<c;e++)if(e in d&&b.call(void 0,d[e],e,a))return!0;return!1},ja=Array.prototype.every?function(a,b,c){return Array.prototype.every.call(a,b,c)}:function(a,b,c){for(var d=a.length,e="string"===typeof a?a.split(""):a,f=0;f<d;f++)if(f in e&&!b.call(c,e[f],f,a))return!1;return!0};
+function ka(a,b){a:{for(var c=a.length,d="string"===typeof a?a.split(""):a,e=0;e<c;e++)if(e in d&&b.call(void 0,d[e],e,a)){b=e;break a}b=-1}return 0>b?null:"string"===typeof a?a.charAt(b):a[b]}function la(a,b){a.sort(b||ma)}function ma(a,b){return a>b?1:a<b?-1:0};function na(a){var b=a.length-1;return 0<=b&&a.indexOf(" ",b)==b}var x=String.prototype.trim?function(a){return a.trim()}:function(a){return/^[\s\xa0]*([\s\S]*?)[\s\xa0]*$/.exec(a)[1]};
+function oa(a,b){var c=0;a=x(String(a)).split(".");b=x(String(b)).split(".");for(var d=Math.max(a.length,b.length),e=0;0==c&&e<d;e++){var f=a[e]||"",g=b[e]||"";do{f=/(\d*)(\D*)(.*)/.exec(f)||["","","",""];g=/(\d*)(\D*)(.*)/.exec(g)||["","","",""];if(0==f[0].length&&0==g[0].length)break;c=pa(0==f[1].length?0:parseInt(f[1],10),0==g[1].length?0:parseInt(g[1],10))||pa(0==f[2].length,0==g[2].length)||pa(f[2],g[2]);f=f[3];g=g[3]}while(0==c)}return c}function pa(a,b){return a<b?-1:a>b?1:0};var y;a:{var qa=h.navigator;if(qa){var ra=qa.userAgent;if(ra){y=ra;break a}}y=""}function C(a){return-1!=y.indexOf(a)};function sa(){return C("Firefox")||C("FxiOS")}function ta(){return(C("Chrome")||C("CriOS"))&&!C("Edge")};function ua(a){return String(a).replace(/\-([a-z])/g,function(b,c){return c.toUpperCase()})};function D(){return C("iPhone")&&!C("iPod")&&!C("iPad")};function va(a,b){var c=xa;return Object.prototype.hasOwnProperty.call(c,a)?c[a]:c[a]=b(a)};var ya=C("Opera"),E=C("Trident")||C("MSIE"),za=C("Edge"),Aa=C("Gecko")&&!(-1!=y.toLowerCase().indexOf("webkit")&&!C("Edge"))&&!(C("Trident")||C("MSIE"))&&!C("Edge"),Ba=-1!=y.toLowerCase().indexOf("webkit")&&!C("Edge");function Ca(){var a=h.document;return a?a.documentMode:void 0}var Da;
+a:{var Ea="",Fa=function(){var a=y;if(Aa)return/rv:([^\);]+)(\)|;)/.exec(a);if(za)return/Edge\/([\d\.]+)/.exec(a);if(E)return/\b(?:MSIE|rv)[: ]([^\);]+)(\)|;)/.exec(a);if(Ba)return/WebKit\/(\S+)/.exec(a);if(ya)return/(?:Version)[ \/]?(\S+)/.exec(a)}();Fa&&(Ea=Fa?Fa[1]:"");if(E){var Ga=Ca();if(null!=Ga&&Ga>parseFloat(Ea)){Da=String(Ga);break a}}Da=Ea}var xa={};function Ha(a){return va(a,function(){return 0<=oa(Da,a)})}var F;F=h.document&&E?Ca():void 0;function G(a,b){this.x=void 0!==a?a:0;this.y=void 0!==b?b:0}G.prototype.ceil=function(){this.x=Math.ceil(this.x);this.y=Math.ceil(this.y);return this};G.prototype.floor=function(){this.x=Math.floor(this.x);this.y=Math.floor(this.y);return this};G.prototype.round=function(){this.x=Math.round(this.x);this.y=Math.round(this.y);return this};function H(a,b){this.width=a;this.height=b}H.prototype.aspectRatio=function(){return this.width/this.height};H.prototype.ceil=function(){this.width=Math.ceil(this.width);this.height=Math.ceil(this.height);return this};H.prototype.floor=function(){this.width=Math.floor(this.width);this.height=Math.floor(this.height);return this};H.prototype.round=function(){this.width=Math.round(this.width);this.height=Math.round(this.height);return this};function I(a){return a?new Ia(J(a)):da||(da=new Ia)}function Ja(a){for(;a&&1!=a.nodeType;)a=a.previousSibling;return a}function Ka(a,b){if(!a||!b)return!1;if(a.contains&&1==b.nodeType)return a==b||a.contains(b);if("undefined"!=typeof a.compareDocumentPosition)return a==b||!!(a.compareDocumentPosition(b)&16);for(;b&&a!=b;)b=b.parentNode;return b==a}function J(a){return 9==a.nodeType?a:a.ownerDocument||a.document}
+function La(a,b){a&&(a=a.parentNode);for(var c=0;a;){if(b(a))return a;a=a.parentNode;c++}return null}function Ia(a){this.a=a||h.document||document}
+function L(a,b,c,d){a=d||a.a;var e=b&&"*"!=b?String(b).toUpperCase():"";if(a.querySelectorAll&&a.querySelector&&(e||c))c=a.querySelectorAll(e+(c?"."+c:""));else if(c&&a.getElementsByClassName)if(b=a.getElementsByClassName(c),e){a={};for(var f=d=0,g;g=b[f];f++)e==g.nodeName&&(a[d++]=g);a.length=d;c=a}else c=b;else if(b=a.getElementsByTagName(e||"*"),c){a={};for(f=d=0;g=b[f];f++){e=g.className;var k;if(k="function"==typeof e.split)k=0<=ea(e.split(/\s+/),c);k&&(a[d++]=g)}a.length=d;c=a}else c=b;return c}
+;var Ma={l:function(a){return!(!a.querySelectorAll||!a.querySelector)},g:function(a,b){if(!a)throw new q(32,"No class name specified");a=x(a);if(-1!==a.indexOf(" "))throw new q(32,"Compound class names not permitted");if(Ma.l(b))try{return b.querySelector("."+a.replace(/\./g,"\\."))||null}catch(c){throw new q(32,"An invalid or illegal class name was specified");}a=L(I(b),"*",a,b);return a.length?a[0]:null},c:function(a,b){if(!a)throw new q(32,"No class name specified");a=x(a);if(-1!==a.indexOf(" "))throw new q(32,
+"Compound class names not permitted");if(Ma.l(b))try{return b.querySelectorAll("."+a.replace(/\./g,"\\."))}catch(c){throw new q(32,"An invalid or illegal class name was specified");}return L(I(b),"*",a,b)}};var Na=sa(),Oa=D()||C("iPod"),Ra=C("iPad"),Sa=C("Android")&&!(ta()||sa()||C("Opera")||C("Silk")),Ta=ta(),Ua=C("Safari")&&!(ta()||C("Coast")||C("Opera")||C("Edge")||C("Edg/")||C("OPR")||sa()||C("Silk")||C("Android"))&&!(D()||C("iPad")||C("iPod"));function M(a){return(a=a.exec(y))?a[1]:""}(function(){if(Na)return M(/Firefox\/([0-9.]+)/);if(E||za||ya)return Da;if(Ta)return D()||C("iPad")||C("iPod")?M(/CriOS\/([0-9.]+)/):M(/Chrome\/([0-9.]+)/);if(Ua&&!(D()||C("iPad")||C("iPod")))return M(/Version\/([0-9.]+)/);if(Oa||Ra){var a=/Version\/(\S+).*Mobile\/(\S+)/.exec(y);if(a)return a[1]+"."+a[2]}else if(Sa)return(a=M(/Android\s+([0-9.]+)/))?a:M(/Version\/([0-9.]+)/);return""})();var Va=E&&!(8<=Number(F)),Wa=E&&!(9<=Number(F));var N={g:function(a,b){if(!l(b.querySelector)&&E&&(E?0<=oa(F,8):Ha(8))&&!n(b.querySelector))throw Error("CSS selection is not supported");if(!a)throw new q(32,"No selector specified");a=x(a);try{var c=b.querySelector(a)}catch(d){throw new q(32,"An invalid or illegal selector was specified");}return c&&1==c.nodeType?c:null},c:function(a,b){if(!l(b.querySelectorAll)&&E&&(E?0<=oa(F,8):Ha(8))&&!n(b.querySelector))throw Error("CSS selection is not supported");if(!a)throw new q(32,"No selector specified");
+a=x(a);try{return b.querySelectorAll(a)}catch(c){throw new q(32,"An invalid or illegal selector was specified");}}};var Xa={aliceblue:"#f0f8ff",antiquewhite:"#faebd7",aqua:"#00ffff",aquamarine:"#7fffd4",azure:"#f0ffff",beige:"#f5f5dc",bisque:"#ffe4c4",black:"#000000",blanchedalmond:"#ffebcd",blue:"#0000ff",blueviolet:"#8a2be2",brown:"#a52a2a",burlywood:"#deb887",cadetblue:"#5f9ea0",chartreuse:"#7fff00",chocolate:"#d2691e",coral:"#ff7f50",cornflowerblue:"#6495ed",cornsilk:"#fff8dc",crimson:"#dc143c",cyan:"#00ffff",darkblue:"#00008b",darkcyan:"#008b8b",darkgoldenrod:"#b8860b",darkgray:"#a9a9a9",darkgreen:"#006400",
 darkgrey:"#a9a9a9",darkkhaki:"#bdb76b",darkmagenta:"#8b008b",darkolivegreen:"#556b2f",darkorange:"#ff8c00",darkorchid:"#9932cc",darkred:"#8b0000",darksalmon:"#e9967a",darkseagreen:"#8fbc8f",darkslateblue:"#483d8b",darkslategray:"#2f4f4f",darkslategrey:"#2f4f4f",darkturquoise:"#00ced1",darkviolet:"#9400d3",deeppink:"#ff1493",deepskyblue:"#00bfff",dimgray:"#696969",dimgrey:"#696969",dodgerblue:"#1e90ff",firebrick:"#b22222",floralwhite:"#fffaf0",forestgreen:"#228b22",fuchsia:"#ff00ff",gainsboro:"#dcdcdc",
 ghostwhite:"#f8f8ff",gold:"#ffd700",goldenrod:"#daa520",gray:"#808080",green:"#008000",greenyellow:"#adff2f",grey:"#808080",honeydew:"#f0fff0",hotpink:"#ff69b4",indianred:"#cd5c5c",indigo:"#4b0082",ivory:"#fffff0",khaki:"#f0e68c",lavender:"#e6e6fa",lavenderblush:"#fff0f5",lawngreen:"#7cfc00",lemonchiffon:"#fffacd",lightblue:"#add8e6",lightcoral:"#f08080",lightcyan:"#e0ffff",lightgoldenrodyellow:"#fafad2",lightgray:"#d3d3d3",lightgreen:"#90ee90",lightgrey:"#d3d3d3",lightpink:"#ffb6c1",lightsalmon:"#ffa07a",
 lightseagreen:"#20b2aa",lightskyblue:"#87cefa",lightslategray:"#778899",lightslategrey:"#778899",lightsteelblue:"#b0c4de",lightyellow:"#ffffe0",lime:"#00ff00",limegreen:"#32cd32",linen:"#faf0e6",magenta:"#ff00ff",maroon:"#800000",mediumaquamarine:"#66cdaa",mediumblue:"#0000cd",mediumorchid:"#ba55d3",mediumpurple:"#9370db",mediumseagreen:"#3cb371",mediumslateblue:"#7b68ee",mediumspringgreen:"#00fa9a",mediumturquoise:"#48d1cc",mediumvioletred:"#c71585",midnightblue:"#191970",mintcream:"#f5fffa",mistyrose:"#ffe4e1",
 moccasin:"#ffe4b5",navajowhite:"#ffdead",navy:"#000080",oldlace:"#fdf5e6",olive:"#808000",olivedrab:"#6b8e23",orange:"#ffa500",orangered:"#ff4500",orchid:"#da70d6",palegoldenrod:"#eee8aa",palegreen:"#98fb98",paleturquoise:"#afeeee",palevioletred:"#db7093",papayawhip:"#ffefd5",peachpuff:"#ffdab9",peru:"#cd853f",pink:"#ffc0cb",plum:"#dda0dd",powderblue:"#b0e0e6",purple:"#800080",red:"#ff0000",rosybrown:"#bc8f8f",royalblue:"#4169e1",saddlebrown:"#8b4513",salmon:"#fa8072",sandybrown:"#f4a460",seagreen:"#2e8b57",
-seashell:"#fff5ee",sienna:"#a0522d",silver:"#c0c0c0",skyblue:"#87ceeb",slateblue:"#6a5acd",slategray:"#708090",slategrey:"#708090",snow:"#fffafa",springgreen:"#00ff7f",steelblue:"#4682b4",tan:"#d2b48c",teal:"#008080",thistle:"#d8bfd8",tomato:"#ff6347",turquoise:"#40e0d0",violet:"#ee82ee",wheat:"#f5deb3",white:"#ffffff",whitesmoke:"#f5f5f5",yellow:"#ffff00",yellowgreen:"#9acd32"};var Pc="backgroundColor borderTopColor borderRightColor borderBottomColor borderLeftColor color outlineColor".split(" "),Qc=/#([0-9a-fA-F])([0-9a-fA-F])([0-9a-fA-F])/,Rc=/^#(?:[0-9a-f]{3}){1,2}$/i,Sc=/^(?:rgba)?\((\d{1,3}),\s?(\d{1,3}),\s?(\d{1,3}),\s?(0|1|0\.\d*)\)$/i,Tc=/^(?:rgb)?\((0|[1-9]\d{0,2}),\s?(0|[1-9]\d{0,2}),\s?(0|[1-9]\d{0,2})\)$/i;function Uc(a,b){b=b.toLowerCase();return"style"==b?Vc(a.style.cssText):Lc&&"value"==b&&S(a,"INPUT")?a.value:Mc&&!0===a[b]?String(a.getAttribute(b)):(a=a.getAttributeNode(b))&&a.specified?a.value:null}var Wc=/[;]+(?=(?:(?:[^"]*"){2})*[^"]*$)(?=(?:(?:[^']*'){2})*[^']*$)(?=(?:[^()]*\([^()]*\))*[^()]*$)/;
-function Vc(a){var b=[];l(a.split(Wc),function(c){var d=c.indexOf(":");0<d&&(c=[c.slice(0,d),c.slice(d+1)],2==c.length&&b.push(c[0].toLowerCase(),":",c[1],";"))});b=b.join("");return b=";"==b.charAt(b.length-1)?b:b+";"}function S(a,b){b&&"string"!==typeof b&&(b=b.toString());return!!a&&1==a.nodeType&&(!b||a.tagName.toUpperCase()==b)};var T={};T.I=function(){var a={da:"http://www.w3.org/2000/svg"};return function(b){return a[b]||null}}();
-T.s=function(a,b,c){var d=A(a);if(!d.documentElement)return null;(t||Hc)&&Ac(d?d.parentWindow||d.defaultView:window);try{var e=d.createNSResolver?d.createNSResolver(d.documentElement):T.I;if(t&&!Ua(7))return d.evaluate.call(d,b,a,e,c,null);if(!t||9<=Number(w)){for(var f={},g=d.getElementsByTagName("*"),h=0;h<g.length;++h){var n=g[h],u=n.namespaceURI;if(u&&!f[u]){var p=n.lookupPrefix(u);if(!p){var G=u.match(".*/(\\w+)/?$");p=G?G[1]:"xhtml"}f[u]=p}}var R={},fa;for(fa in f)R[f[fa]]=fa;e=function(m){return R[m]||
-null}}try{return d.evaluate(b,a,e,c,null)}catch(m){if("TypeError"===m.name)return e=d.createNSResolver?d.createNSResolver(d.documentElement):T.I,d.evaluate(b,a,e,c,null);throw m;}}catch(m){if(!Na||"NS_ERROR_ILLEGAL_VALUE"!=m.name)throw new P(32,"Unable to locate an element with the xpath expression "+b+" because of the following error:\n"+m);}};T.J=function(a,b){if(!a||1!=a.nodeType)throw new P(32,'The result of the xpath expression "'+b+'" is: '+a+". It should be an element.");};
-T.o=function(a,b){var c=function(){var d=T.s(b,a,9);return d?d.singleNodeValue||null:b.selectSingleNode?(d=A(b),d.setProperty&&d.setProperty("SelectionLanguage","XPath"),b.selectSingleNode(a)):null}();null===c||T.J(c,a);return c};
-T.j=function(a,b){var c=function(){var d=T.s(b,a,7);if(d){for(var e=d.snapshotLength,f=[],g=0;g<e;++g)f.push(d.snapshotItem(g));return f}return b.selectNodes?(d=A(b),d.setProperty&&d.setProperty("SelectionLanguage","XPath"),b.selectNodes(a)):[]}();l(c,function(d){T.J(d,a)});return c};function Xc(a,b,c,d){this.c=a;this.a=b;this.b=c;this.f=d}Xc.prototype.ceil=function(){this.c=Math.ceil(this.c);this.a=Math.ceil(this.a);this.b=Math.ceil(this.b);this.f=Math.ceil(this.f);return this};Xc.prototype.floor=function(){this.c=Math.floor(this.c);this.a=Math.floor(this.a);this.b=Math.floor(this.b);this.f=Math.floor(this.f);return this};Xc.prototype.round=function(){this.c=Math.round(this.c);this.a=Math.round(this.a);this.b=Math.round(this.b);this.f=Math.round(this.f);return this};function U(a,b,c,d){this.a=a;this.b=b;this.width=c;this.height=d}U.prototype.ceil=function(){this.a=Math.ceil(this.a);this.b=Math.ceil(this.b);this.width=Math.ceil(this.width);this.height=Math.ceil(this.height);return this};U.prototype.floor=function(){this.a=Math.floor(this.a);this.b=Math.floor(this.b);this.width=Math.floor(this.width);this.height=Math.floor(this.height);return this};
-U.prototype.round=function(){this.a=Math.round(this.a);this.b=Math.round(this.b);this.width=Math.round(this.width);this.height=Math.round(this.height);return this};var Yc="function"===typeof ShadowRoot;function Zc(a){for(a=a.parentNode;a&&1!=a.nodeType&&9!=a.nodeType&&11!=a.nodeType;)a=a.parentNode;return S(a)?a:null}
-function V(a,b){b=Ha(b);if("float"==b||"cssFloat"==b||"styleFloat"==b)b=Mc?"styleFloat":"cssFloat";a:{var c=b;var d=A(a);if(d.defaultView&&d.defaultView.getComputedStyle&&(d=d.defaultView.getComputedStyle(a,null))){c=d[c]||d.getPropertyValue(c)||"";break a}c=""}a=c||$c(a,b);if(null===a)a=null;else if(0<=oa(Pc,b)){b:{var e=a.match(Sc);if(e&&(b=Number(e[1]),c=Number(e[2]),d=Number(e[3]),e=Number(e[4]),0<=b&&255>=b&&0<=c&&255>=c&&0<=d&&255>=d&&0<=e&&1>=e)){b=[b,c,d,e];break b}b=null}if(!b)b:{if(d=a.match(Tc))if(b=
-Number(d[1]),c=Number(d[2]),d=Number(d[3]),0<=b&&255>=b&&0<=c&&255>=c&&0<=d&&255>=d){b=[b,c,d,1];break b}b=null}if(!b)b:{b=a.toLowerCase();c=Oc[b.toLowerCase()];if(!c&&(c="#"==b.charAt(0)?b:"#"+b,4==c.length&&(c=c.replace(Qc,"#$1$1$2$2$3$3")),!Rc.test(c))){b=null;break b}b=[parseInt(c.substr(1,2),16),parseInt(c.substr(3,2),16),parseInt(c.substr(5,2),16),1]}a=b?"rgba("+b.join(", ")+")":a}return a}
-function $c(a,b){var c=a.currentStyle||a.style,d=c[b];void 0===d&&ea(c.getPropertyValue)&&(d=c.getPropertyValue(b));return"inherit"!=d?void 0!==d?d:null:(a=Zc(a))?$c(a,b):null}
-function ad(a,b,c){function d(g){var h=W(g);return 0<h.height&&0<h.width?!0:S(g,"PATH")&&(0<h.height||0<h.width)?(g=V(g,"stroke-width"),!!g&&0<parseInt(g,10)):"hidden"!=V(g,"overflow")&&sa(g.childNodes,function(n){return 3==n.nodeType||S(n)&&d(n)})}function e(g){return bd(g)==X&&ta(g.childNodes,function(h){return!S(h)||e(h)||!d(h)})}if(!S(a))throw Error("Argument to isShown must be of type Element");if(S(a,"BODY"))return!0;if(S(a,"OPTION")||S(a,"OPTGROUP"))return a=lb(a,function(g){return S(g,"SELECT")}),
-!!a&&ad(a,!0,c);var f=cd(a);if(f)return!!f.image&&0<f.rect.width&&0<f.rect.height&&ad(f.image,b,c);if(S(a,"INPUT")&&"hidden"==a.type.toLowerCase()||S(a,"NOSCRIPT"))return!1;f=V(a,"visibility");return"collapse"!=f&&"hidden"!=f&&c(a)&&(b||0!=dd(a))&&d(a)?!e(a):!1}
-function ed(a){function b(c){if(S(c)&&"none"==V(c,"display"))return!1;var d;if((d=c.parentNode)&&d.shadowRoot&&void 0!==c.assignedSlot)d=c.assignedSlot?c.assignedSlot.parentNode:null;else if(c.getDestinationInsertionPoints){var e=c.getDestinationInsertionPoints();0<e.length&&(d=e[e.length-1])}if(Yc&&d instanceof ShadowRoot){if(d.host.shadowRoot!==d)return!1;d=d.host}return!d||9!=d.nodeType&&11!=d.nodeType?d&&S(d,"DETAILS")&&!d.open&&!S(c,"SUMMARY")?!1:!!d&&b(d):!0}return ad(a,!1,b)}var X="hidden";
-function bd(a){function b(m){function v(Ab){if(Ab==g)return!0;var pc=V(Ab,"display");return 0==pc.lastIndexOf("inline",0)||"contents"==pc||"absolute"==qc&&"static"==V(Ab,"position")?!1:!0}var qc=V(m,"position");if("fixed"==qc)return u=!0,m==g?null:g;for(m=Zc(m);m&&!v(m);)m=Zc(m);return m}function c(m){var v=m;if("visible"==n)if(m==g&&h)v=h;else if(m==h)return{x:"visible",y:"visible"};v={x:V(v,"overflow-x"),y:V(v,"overflow-y")};m==g&&(v.x="visible"==v.x?"auto":v.x,v.y="visible"==v.y?"auto":v.y);return v}
-function d(m){if(m==g){var v=(new fb(f)).a;m=v.scrollingElement?v.scrollingElement:Oa||"CSS1Compat"!=v.compatMode?v.body||v.documentElement:v.documentElement;v=v.parentWindow||v.defaultView;m=t&&Ua("10")&&v.pageYOffset!=m.scrollTop?new cb(m.scrollLeft,m.scrollTop):new cb(v.pageXOffset||m.scrollLeft,v.pageYOffset||m.scrollTop)}else m=new cb(m.scrollLeft,m.scrollTop);return m}var e=fd(a),f=A(a),g=f.documentElement,h=f.body,n=V(g,"overflow"),u;for(a=b(a);a;a=b(a)){var p=c(a);if("visible"!=p.x||"visible"!=
-p.y){var G=W(a);if(0==G.width||0==G.height)return X;var R=e.a<G.a,fa=e.b<G.b;if(R&&"hidden"==p.x||fa&&"hidden"==p.y)return X;if(R&&"visible"!=p.x||fa&&"visible"!=p.y){R=d(a);fa=e.b<G.b-R.y;if(e.a<G.a-R.x&&"visible"!=p.x||fa&&"visible"!=p.x)return X;e=bd(a);return e==X?X:"scroll"}R=e.f>=G.a+G.width;G=e.c>=G.b+G.height;if(R&&"hidden"==p.x||G&&"hidden"==p.y)return X;if(R&&"visible"!=p.x||G&&"visible"!=p.y){if(u&&(p=d(a),e.f>=g.scrollWidth-p.x||e.a>=g.scrollHeight-p.y))return X;e=bd(a);return e==X?X:
-"scroll"}}}return"none"}
-function W(a){var b=cd(a);if(b)return b.rect;if(S(a,"HTML"))return a=A(a),a=((a?a.parentWindow||a.defaultView:window)||window).document,a="CSS1Compat"==a.compatMode?a.documentElement:a.body,a=new db(a.clientWidth,a.clientHeight),new U(0,0,a.width,a.height);try{var c=a.getBoundingClientRect()}catch(d){return new U(0,0,0,0)}b=new U(c.left,c.top,c.right-c.left,c.bottom-c.top);t&&a.ownerDocument.body&&(a=A(a),b.a-=a.documentElement.clientLeft+a.body.clientLeft,b.b-=a.documentElement.clientTop+a.body.clientTop);
-return b}function cd(a){var b=S(a,"MAP");if(!b&&!S(a,"AREA"))return null;var c=b?a:S(a.parentNode,"MAP")?a.parentNode:null,d=null,e=null;c&&c.name&&(d=T.o('/descendant::*[@usemap = "#'+c.name+'"]',A(c)))&&(e=W(d),b||"default"==a.shape.toLowerCase()||(a=gd(a),b=Math.min(Math.max(a.a,0),e.width),c=Math.min(Math.max(a.b,0),e.height),e=new U(b+e.a,c+e.b,Math.min(a.width,e.width-b),Math.min(a.height,e.height-c))));return{image:d,rect:e||new U(0,0,0,0)}}
-function gd(a){var b=a.shape.toLowerCase();a=a.coords.split(",");if("rect"==b&&4==a.length){b=a[0];var c=a[1];return new U(b,c,a[2]-b,a[3]-c)}if("circle"==b&&3==a.length)return b=a[2],new U(a[0]-b,a[1]-b,2*b,2*b);if("poly"==b&&2<a.length){b=a[0];c=a[1];for(var d=b,e=c,f=2;f+1<a.length;f+=2)b=Math.min(b,a[f]),d=Math.max(d,a[f]),c=Math.min(c,a[f+1]),e=Math.max(e,a[f+1]);return new U(b,c,d-b,e-c)}return new U(0,0,0,0)}function fd(a){a=W(a);return new Xc(a.b,a.a+a.width,a.b+a.height,a.a)}
-function hd(a){return a.replace(/^[^\S\xa0]+|[^\S\xa0]+$/g,"")}function id(a){var b=[];Yc?jd(a,b):kd(a,b);a=qa(b,hd);return hd(a.join("\n")).replace(/\xa0/g," ")}
-function ld(a,b,c){if(S(a,"BR"))b.push("");else{var d=S(a,"TD"),e=V(a,"display"),f=!d&&!(0<=oa(md,e)),g=void 0!==a.previousElementSibling?a.previousElementSibling:gb(a.previousSibling);g=g?V(g,"display"):"";var h=V(a,"float")||V(a,"cssFloat")||V(a,"styleFloat");!f||"run-in"==g&&"none"==h||/^[\s\xa0]*$/.test(b[b.length-1]||"")||b.push("");var n=ed(a),u=null,p=null;n&&(u=V(a,"white-space"),p=V(a,"text-transform"));l(a.childNodes,function(G){c(G,b,n,u,p)});a=b[b.length-1]||"";!d&&"table-cell"!=e||!a||
-za(a)||(b[b.length-1]+=" ");f&&"run-in"!=e&&!/^[\s\xa0]*$/.test(a)&&b.push("")}}function kd(a,b){ld(a,b,function(c,d,e,f,g){3==c.nodeType&&e?nd(c,d,f,g):S(c)&&kd(c,d)})}var md="inline inline-block inline-table none table-cell table-column table-column-group".split(" ");
-function nd(a,b,c,d){a=a.nodeValue.replace(/[\u200b\u200e\u200f]/g,"");a=a.replace(/(\r\n|\r|\n)/g,"\n");if("normal"==c||"nowrap"==c)a=a.replace(/\n/g," ");a="pre"==c||"pre-wrap"==c?a.replace(/[ \f\t\v\u2028\u2029]/g,"\u00a0"):a.replace(/[ \f\t\v\u2028\u2029]+/g," ");"capitalize"==d?a=a.replace(t?/(^|\s|\b)(\S)/g:/(^|[^\d\p{L}\p{S}])([\p{Ll}|\p{S}])/gu,function(e,f,g){return f+g.toUpperCase()}):"uppercase"==d?a=a.toUpperCase():"lowercase"==d&&(a=a.toLowerCase());c=b.pop()||"";za(c)&&0==a.lastIndexOf(" ",
-0)&&(a=a.substr(1));b.push(c+a)}function dd(a){if(Mc){if("relative"==V(a,"position"))return 1;a=V(a,"filter");return(a=a.match(/^alpha\(opacity=(\d*)\)/)||a.match(/^progid:DXImageTransform.Microsoft.Alpha\(Opacity=(\d*)\)/))?Number(a[1])/100:1}return od(a)}function od(a){var b=1,c=V(a,"opacity");c&&(b=Number(c));(a=Zc(a))&&(b*=od(a));return b}
-function pd(a,b,c,d,e){if(3==a.nodeType&&c)nd(a,b,d,e);else if(S(a))if(S(a,"CONTENT")||S(a,"SLOT")){for(var f=a;f.parentNode;)f=f.parentNode;f instanceof ShadowRoot?(a=S(a,"CONTENT")?a.getDistributedNodes():a.assignedNodes(),l(a,function(g){pd(g,b,c,d,e)})):jd(a,b)}else if(S(a,"SHADOW")){for(f=a;f.parentNode;)f=f.parentNode;if(f instanceof ShadowRoot&&(a=f))for(a=a.olderShadowRoot;a;)l(a.childNodes,function(g){pd(g,b,c,d,e)}),a=a.olderShadowRoot}else jd(a,b)}
-function jd(a,b){a.shadowRoot&&l(a.shadowRoot.childNodes,function(c){pd(c,b,!0,null,null)});ld(a,b,function(c,d,e,f,g){var h=null;1==c.nodeType?h=c:3==c.nodeType&&(h=c);null!=h&&(null!=h.assignedSlot||h.getDestinationInsertionPoints&&0<h.getDestinationInsertionPoints().length)||pd(c,d,e,f,g)})};var qd={C:function(a,b){return!(!a.querySelectorAll||!a.querySelector)&&!/^\d.*/.test(b)},o:function(a,b){var c=eb(b),d="string"===typeof a?c.a.getElementById(a):a;return d?Uc(d,"id")==a&&b!=d&&hb(b,d)?d:ua(mb(c,"*"),function(e){return Uc(e,"id")==a&&b!=e&&hb(b,e)}):null},j:function(a,b){if(!a)return[];if(qd.C(b,a))try{return b.querySelectorAll("#"+qd.T(a))}catch(c){return[]}b=mb(eb(b),"*",null,b);return pa(b,function(c){return Uc(c,"id")==a})},T:function(a){return a.replace(/([\s'"\\#.:;,!?+<>=~*^$|%&@`{}\-\/\[\]\(\)])/g,
-"\\$1")}};var Y={},rd={};Y.N=function(a,b,c){try{var d=Nc.j("a",b)}catch(e){d=mb(eb(b),"A",null,b)}return ua(d,function(e){e=id(e);e=e.replace(/^[\s]+|[\s]+$/g,"");return c&&-1!=e.indexOf(a)||e==a})};Y.K=function(a,b,c){try{var d=Nc.j("a",b)}catch(e){d=mb(eb(b),"A",null,b)}return pa(d,function(e){e=id(e);e=e.replace(/^[\s]+|[\s]+$/g,"");return c&&-1!=e.indexOf(a)||e==a})};Y.o=function(a,b){return Y.N(a,b,!1)};Y.j=function(a,b){return Y.K(a,b,!1)};rd.o=function(a,b){return Y.N(a,b,!0)};
-rd.j=function(a,b){return Y.K(a,b,!0)};var Z={F:function(a,b){return function(c){var d=Z.u(a);d=W(d);c=W(c);return b.call(null,d,c)}},R:function(a){return Z.F(a,function(b,c){return c.b+c.height<b.b})},S:function(a){return Z.F(a,function(b,c){return b.b+b.height<c.b})},V:function(a){return Z.F(a,function(b,c){return c.a+c.width<b.a})},aa:function(a){return Z.F(a,function(b,c){return b.a+b.width<c.a})},W:function(a,b){var c;b?c=b:"number"==typeof a.distance&&(c=a.distance);c||(c=100);return function(d){var e=Z.u(a);if(e===d)return!1;e=
-W(e);d=W(d);var f=Math.abs(e.a+e.width-d.a),g=Math.abs(e.b+e.height-d.b);g=Math.abs(e.b-(d.b+d.height))<=c||g<=c;return(Math.abs(e.a-(d.a+d.width))<=c||f<=c)&&g?!0:Math.sqrt(Math.pow(Math.abs(e.a+e.width/2-(d.a+d.width/2)),2)+Math.pow(Math.abs(e.b+e.height/2-(d.b+d.height/2)),2))<=c}},u:function(a){if(ha(a)&&1==a.nodeType)return a;if(ea(a))return Z.u(a.call(null));if(ha(a)){var b;a:{if(b=sd(a)){var c=td[b];if(c&&ea(c.o)){b=c.o(a[b],Bc.document);break a}}throw new P(61,"Unsupported locator strategy: "+
-b);}if(!b)throw new P(7,"No element has been found by "+JSON.stringify(a));return b}throw new P(61,"Selector is of wrong type: "+JSON.stringify(a));}};Z.P={left:Z.V,right:Z.aa,above:Z.R,below:Z.S,near:Z.W};Z.O={left:Z.u,right:Z.u,above:Z.u,below:Z.u,near:Z.u};
-Z.U=function(a,b){var c=[];l(a,function(e){e&&ta(b,function(f){var g=f.kind,h=Z.P[g];if(!h)throw new P(61,"Cannot find filter suitable for "+g);return h.apply(null,f.args)(e)},null)&&c.push(e)},null);a=b[b.length-1];var d=Z.O[a?a.kind:"unknown"];return d?(a=d.apply(null,a.args))?Z.ba(a,c):c:c};
-Z.ba=function(a,b){function c(f){f=W(f);return Math.sqrt(Math.pow(d-(f.a+Math.max(1,f.width)/2),2)+Math.pow(e-(f.b+Math.max(1,f.height)/2),2))}a=W(a);var d=a.a+Math.max(1,a.width)/2,e=a.b+Math.max(1,a.height)/2;xa(b,function(f,g){return c(f)-c(g)});return b};Z.o=function(a,b){a=Z.j(a,b);return 0==a.length?null:a[0]};
-Z.j=function(a,b){if(!a.hasOwnProperty("root")||!a.hasOwnProperty("filters"))throw new P(61,"Locator not suitable for relative locators: "+JSON.stringify(a));var c=a.filters,d=da(c);if("array"!=d&&("object"!=d||"number"!=typeof c.length))throw new P(61,"Targets should be an array: "+JSON.stringify(a));var e;S(a.root)?e=[a.root]:e=ud(a.root,b);return 0==e.length?[]:Z.U(e,a.filters)};var vd={o:function(a,b){if(""===a)throw new P(32,'Unable to locate an element with the tagName ""');return b.getElementsByTagName(a)[0]||null},j:function(a,b){if(""===a)throw new P(32,'Unable to locate an element with the tagName ""');return b.getElementsByTagName(a)}};var td={className:Dc,"class name":Dc,css:Nc,"css selector":Nc,relative:Z,id:qd,linkText:Y,"link text":Y,name:{o:function(a,b){b=mb(eb(b),"*",null,b);return ua(b,function(c){return Uc(c,"name")==a})},j:function(a,b){b=mb(eb(b),"*",null,b);return pa(b,function(c){return Uc(c,"name")==a})}},partialLinkText:rd,"partial link text":rd,tagName:vd,"tag name":vd,xpath:T};function sd(a){for(var b in a)if(a.hasOwnProperty(b))return b;return null}
-function ud(a,b){var c=sd(a);if(c){var d=td[c];if(d&&ea(d.j))return d.j(a[c],b||Bc.document)}throw new P(61,"Unsupported locator strategy: "+c);};ca("_",ud);; return this._.apply(null,arguments);}).apply({navigator:typeof window!='undefined'?window.navigator:null,document:typeof window!='undefined'?window.document:null}, arguments);}
+seashell:"#fff5ee",sienna:"#a0522d",silver:"#c0c0c0",skyblue:"#87ceeb",slateblue:"#6a5acd",slategray:"#708090",slategrey:"#708090",snow:"#fffafa",springgreen:"#00ff7f",steelblue:"#4682b4",tan:"#d2b48c",teal:"#008080",thistle:"#d8bfd8",tomato:"#ff6347",turquoise:"#40e0d0",violet:"#ee82ee",wheat:"#f5deb3",white:"#ffffff",whitesmoke:"#f5f5f5",yellow:"#ffff00",yellowgreen:"#9acd32"};var Ya="backgroundColor borderTopColor borderRightColor borderBottomColor borderLeftColor color outlineColor".split(" "),Za=/#([0-9a-fA-F])([0-9a-fA-F])([0-9a-fA-F])/,$a=/^#(?:[0-9a-f]{3}){1,2}$/i,ab=/^(?:rgba)?\((\d{1,3}),\s?(\d{1,3}),\s?(\d{1,3}),\s?(0|1|0\.\d*)\)$/i,bb=/^(?:rgb)?\((0|[1-9]\d{0,2}),\s?(0|[1-9]\d{0,2}),\s?(0|[1-9]\d{0,2})\)$/i;function O(a,b){b=b.toLowerCase();return"style"==b?cb(a.style.cssText):Va&&"value"==b&&P(a,"INPUT")?a.value:Wa&&!0===a[b]?String(a.getAttribute(b)):(a=a.getAttributeNode(b))&&a.specified?a.value:null}var db=/[;]+(?=(?:(?:[^"]*"){2})*[^"]*$)(?=(?:(?:[^']*'){2})*[^']*$)(?=(?:[^()]*\([^()]*\))*[^()]*$)/;
+function cb(a){var b=[];w(a.split(db),function(c){var d=c.indexOf(":");0<d&&(c=[c.slice(0,d),c.slice(d+1)],2==c.length&&b.push(c[0].toLowerCase(),":",c[1],";"))});b=b.join("");return b=";"==b.charAt(b.length-1)?b:b+";"}function P(a,b){b&&"string"!==typeof b&&(b=b.toString());return a instanceof HTMLFormElement?!!a&&1==a.nodeType&&(!b||"FORM"==b):!!a&&1==a.nodeType&&(!b||a.tagName.toUpperCase()==b)};function eb(a,b,c,d){this.j=a;this.a=b;this.b=c;this.h=d}eb.prototype.ceil=function(){this.j=Math.ceil(this.j);this.a=Math.ceil(this.a);this.b=Math.ceil(this.b);this.h=Math.ceil(this.h);return this};eb.prototype.floor=function(){this.j=Math.floor(this.j);this.a=Math.floor(this.a);this.b=Math.floor(this.b);this.h=Math.floor(this.h);return this};eb.prototype.round=function(){this.j=Math.round(this.j);this.a=Math.round(this.a);this.b=Math.round(this.b);this.h=Math.round(this.h);return this};function Q(a,b,c,d){this.a=a;this.b=b;this.width=c;this.height=d}Q.prototype.ceil=function(){this.a=Math.ceil(this.a);this.b=Math.ceil(this.b);this.width=Math.ceil(this.width);this.height=Math.ceil(this.height);return this};Q.prototype.floor=function(){this.a=Math.floor(this.a);this.b=Math.floor(this.b);this.width=Math.floor(this.width);this.height=Math.floor(this.height);return this};
+Q.prototype.round=function(){this.a=Math.round(this.a);this.b=Math.round(this.b);this.width=Math.round(this.width);this.height=Math.round(this.height);return this};var fb="function"===typeof ShadowRoot;function gb(a){for(a=a.parentNode;a&&1!=a.nodeType&&9!=a.nodeType&&11!=a.nodeType;)a=a.parentNode;return P(a)?a:null}
+function R(a,b){b=ua(b);if("float"==b||"cssFloat"==b||"styleFloat"==b)b=Wa?"styleFloat":"cssFloat";a:{var c=b;var d=J(a);if(d.defaultView&&d.defaultView.getComputedStyle&&(d=d.defaultView.getComputedStyle(a,null))){c=d[c]||d.getPropertyValue(c)||"";break a}c=""}a=c||hb(a,b);if(null===a)a=null;else if(0<=ea(Ya,b)){b:{var e=a.match(ab);if(e&&(b=Number(e[1]),c=Number(e[2]),d=Number(e[3]),e=Number(e[4]),0<=b&&255>=b&&0<=c&&255>=c&&0<=d&&255>=d&&0<=e&&1>=e)){b=[b,c,d,e];break b}b=null}if(!b)b:{if(d=a.match(bb))if(b=
+Number(d[1]),c=Number(d[2]),d=Number(d[3]),0<=b&&255>=b&&0<=c&&255>=c&&0<=d&&255>=d){b=[b,c,d,1];break b}b=null}if(!b)b:{b=a.toLowerCase();c=Xa[b.toLowerCase()];if(!c&&(c="#"==b.charAt(0)?b:"#"+b,4==c.length&&(c=c.replace(Za,"#$1$1$2$2$3$3")),!$a.test(c))){b=null;break b}b=[parseInt(c.substr(1,2),16),parseInt(c.substr(3,2),16),parseInt(c.substr(5,2),16),1]}a=b?"rgba("+b.join(", ")+")":a}return a}
+function hb(a,b){var c=a.currentStyle||a.style,d=c[b];void 0===d&&l(c.getPropertyValue)&&(d=c.getPropertyValue(b));return"inherit"!=d?void 0!==d?d:null:(a=gb(a))?hb(a,b):null}
+function ib(a,b,c){function d(g){var k=S(g);return 0<k.height&&0<k.width?!0:P(g,"PATH")&&(0<k.height||0<k.width)?(g=R(g,"stroke-width"),!!g&&0<parseInt(g,10)):"hidden"!=R(g,"overflow")&&ia(g.childNodes,function(z){return 3==z.nodeType||P(z)&&d(z)})}function e(g){return jb(g)==T&&ja(g.childNodes,function(k){return!P(k)||e(k)||!d(k)})}if(!P(a))throw Error("Argument to isShown must be of type Element");if(P(a,"BODY"))return!0;if(P(a,"OPTION")||P(a,"OPTGROUP"))return a=La(a,function(g){return P(g,"SELECT")}),
+!!a&&ib(a,!0,c);var f=kb(a);if(f)return!!f.image&&0<f.rect.width&&0<f.rect.height&&ib(f.image,b,c);if(P(a,"INPUT")&&"hidden"==a.type.toLowerCase()||P(a,"NOSCRIPT"))return!1;f=R(a,"visibility");return"collapse"!=f&&"hidden"!=f&&c(a)&&(b||0!=lb(a))&&d(a)?!e(a):!1}
+function mb(a){function b(c){if(P(c)&&("none"==R(c,"display")||"hidden"==R(c,"content-visibility")))return!1;var d;if((d=c.parentNode)&&d.shadowRoot&&void 0!==c.assignedSlot)d=c.assignedSlot?c.assignedSlot.parentNode:null;else if(c.getDestinationInsertionPoints){var e=c.getDestinationInsertionPoints();0<e.length&&(d=e[e.length-1])}if(fb&&d instanceof ShadowRoot){if(d.host.shadowRoot&&d.host.shadowRoot!==d)return!1;d=d.host}return!d||9!=d.nodeType&&11!=d.nodeType?d&&P(d,"DETAILS")&&!d.open&&!P(c,"SUMMARY")?
+!1:!!d&&b(d):!0}return ib(a,!1,b)}var T="hidden";
+function jb(a){function b(m){function p(wa){if(wa==g)return!0;var Pa=R(wa,"display");return 0==Pa.lastIndexOf("inline",0)||"contents"==Pa||"absolute"==Qa&&"static"==R(wa,"position")?!1:!0}var Qa=R(m,"position");if("fixed"==Qa)return A=!0,m==g?null:g;for(m=gb(m);m&&!p(m);)m=gb(m);return m}function c(m){var p=m;if("visible"==z)if(m==g&&k)p=k;else if(m==k)return{x:"visible",y:"visible"};p={x:R(p,"overflow-x"),y:R(p,"overflow-y")};m==g&&(p.x="visible"==p.x?"auto":p.x,p.y="visible"==p.y?"auto":p.y);return p}
+function d(m){if(m==g){var p=(new Ia(f)).a;m=p.scrollingElement?p.scrollingElement:Ba||"CSS1Compat"!=p.compatMode?p.body||p.documentElement:p.documentElement;p=p.parentWindow||p.defaultView;m=E&&Ha("10")&&p.pageYOffset!=m.scrollTop?new G(m.scrollLeft,m.scrollTop):new G(p.pageXOffset||m.scrollLeft,p.pageYOffset||m.scrollTop)}else m=new G(m.scrollLeft,m.scrollTop);return m}var e=nb(a),f=J(a),g=f.documentElement,k=f.body,z=R(g,"overflow"),A;for(a=b(a);a;a=b(a)){var t=c(a);if("visible"!=t.x||"visible"!=
+t.y){var v=S(a);if(0==v.width||0==v.height)return T;var B=e.a<v.a,K=e.b<v.b;if(B&&"hidden"==t.x||K&&"hidden"==t.y)return T;if(B&&"visible"!=t.x||K&&"visible"!=t.y){B=d(a);K=e.b<v.b-B.y;if(e.a<v.a-B.x&&"visible"!=t.x||K&&"visible"!=t.x)return T;e=jb(a);return e==T?T:"scroll"}B=e.h>=v.a+v.width;v=e.j>=v.b+v.height;if(B&&"hidden"==t.x||v&&"hidden"==t.y)return T;if(B&&"visible"!=t.x||v&&"visible"!=t.y){if(A&&(t=d(a),e.h>=g.scrollWidth-t.x||e.a>=g.scrollHeight-t.y))return T;e=jb(a);return e==T?T:"scroll"}}}return"none"}
+function S(a){var b=kb(a);if(b)return b.rect;if(P(a,"HTML"))return a=J(a),a=((a?a.parentWindow||a.defaultView:window)||window).document,a="CSS1Compat"==a.compatMode?a.documentElement:a.body,a=new H(a.clientWidth,a.clientHeight),new Q(0,0,a.width,a.height);try{var c=a.getBoundingClientRect()}catch(d){return new Q(0,0,0,0)}b=new Q(c.left,c.top,c.right-c.left,c.bottom-c.top);E&&a.ownerDocument.body&&(a=J(a),b.a-=a.documentElement.clientLeft+a.body.clientLeft,b.b-=a.documentElement.clientTop+a.body.clientTop);
+return b}function kb(a){var b=P(a,"MAP");if(!b&&!P(a,"AREA"))return null;var c=b?a:P(a.parentNode,"MAP")?a.parentNode:null,d=null,e=null;c&&c.name&&(d=N.g('*[usemap="#'+c.name+'"]',J(c)))&&(e=S(d),b||"default"==a.shape.toLowerCase()||(a=ob(a),b=Math.min(Math.max(a.a,0),e.width),c=Math.min(Math.max(a.b,0),e.height),e=new Q(b+e.a,c+e.b,Math.min(a.width,e.width-b),Math.min(a.height,e.height-c))));return{image:d,rect:e||new Q(0,0,0,0)}}
+function ob(a){var b=a.shape.toLowerCase();a=a.coords.split(",");if("rect"==b&&4==a.length){b=a[0];var c=a[1];return new Q(b,c,a[2]-b,a[3]-c)}if("circle"==b&&3==a.length)return b=a[2],new Q(a[0]-b,a[1]-b,2*b,2*b);if("poly"==b&&2<a.length){b=a[0];c=a[1];for(var d=b,e=c,f=2;f+1<a.length;f+=2)b=Math.min(b,a[f]),d=Math.max(d,a[f]),c=Math.min(c,a[f+1]),e=Math.max(e,a[f+1]);return new Q(b,c,d-b,e-c)}return new Q(0,0,0,0)}function nb(a){a=S(a);return new eb(a.b,a.a+a.width,a.b+a.height,a.a)}
+function pb(a){return a.replace(/^[^\S\xa0]+|[^\S\xa0]+$/g,"")}function qb(a){var b=[];fb?rb(a,b):sb(a,b);a=ha(b,pb);return pb(a.join("\n")).replace(/\xa0/g," ")}
+function tb(a,b,c){if(P(a,"BR"))b.push("");else{var d=P(a,"TD"),e=R(a,"display"),f=!d&&!(0<=ea(ub,e)),g=void 0!==a.previousElementSibling?a.previousElementSibling:Ja(a.previousSibling);g=g?R(g,"display"):"";var k=R(a,"float")||R(a,"cssFloat")||R(a,"styleFloat");!f||"run-in"==g&&"none"==k||/^[\s\xa0]*$/.test(b[b.length-1]||"")||b.push("");var z=mb(a),A=null,t=null;z&&(A=R(a,"white-space"),t=R(a,"text-transform"));w(a.childNodes,function(v){c(v,b,z,A,t)});a=b[b.length-1]||"";!d&&"table-cell"!=e||!a||
+na(a)||(b[b.length-1]+=" ");f&&"run-in"!=e&&!/^[\s\xa0]*$/.test(a)&&b.push("")}}function sb(a,b){tb(a,b,function(c,d,e,f,g){3==c.nodeType&&e?vb(c,d,f,g):P(c)&&sb(c,d)})}var ub="inline inline-block inline-table none table-cell table-column table-column-group".split(" ");
+function vb(a,b,c,d){a=a.nodeValue.replace(/[\u200b\u200e\u200f]/g,"");a=a.replace(/(\r\n|\r|\n)/g,"\n");if("normal"==c||"nowrap"==c)a=a.replace(/\n/g," ");a="pre"==c||"pre-wrap"==c?a.replace(/[ \f\t\v\u2028\u2029]/g,"\u00a0"):a.replace(/[ \f\t\v\u2028\u2029]+/g," ");"capitalize"==d?(c=/(^|[^'_0-9A-Za-z\u00C0-\u02AF\u1E00-\u1EFF\u24B6-\u24E9\u0300-\u036F\u1AB0-\u1AFF\u1DC0-\u1DFF])([A-Za-z\u00C0-\u02AF\u1E00-\u1EFF\u24B6-\u24E9])/g,a=a.replace(c,function(e,f,g){return f+g.toUpperCase()}),c=/(^|[^'_0-9A-Za-z\u00C0-\u02AF\u1E00-\u1EFF\u24B6-\u24E9])([_*])([A-Za-z\u00C0-\u02AF\u1E00-\u1EFF\u24D0-\u24E9])/g,
+a=a.replace(c,function(e,f,g,k){return f+g+k.toUpperCase()})):"uppercase"==d?a=a.toUpperCase():"lowercase"==d&&(a=a.toLowerCase());c=b.pop()||"";na(c)&&0==a.lastIndexOf(" ",0)&&(a=a.substr(1));b.push(c+a)}function lb(a){if(Wa){if("relative"==R(a,"position"))return 1;a=R(a,"filter");return(a=a.match(/^alpha\(opacity=(\d*)\)/)||a.match(/^progid:DXImageTransform.Microsoft.Alpha\(Opacity=(\d*)\)/))?Number(a[1])/100:1}return wb(a)}
+function wb(a){var b=1,c=R(a,"opacity");c&&(b=Number(c));(a=gb(a))&&(b*=wb(a));return b}
+function xb(a,b,c,d,e){if(3==a.nodeType&&c)vb(a,b,d,e);else if(P(a))if(P(a,"CONTENT")||P(a,"SLOT")){for(var f=a;f.parentNode;)f=f.parentNode;f instanceof ShadowRoot?(f=P(a,"CONTENT")?a.getDistributedNodes():a.assignedNodes(),w(0<f.length?f:a.childNodes,function(g){xb(g,b,c,d,e)})):rb(a,b)}else if(P(a,"SHADOW")){for(f=a;f.parentNode;)f=f.parentNode;if(f instanceof ShadowRoot&&(a=f))for(a=a.olderShadowRoot;a;)w(a.childNodes,function(g){xb(g,b,c,d,e)}),a=a.olderShadowRoot}else rb(a,b)}
+function rb(a,b){a.shadowRoot&&w(a.shadowRoot.childNodes,function(c){xb(c,b,!0,null,null)});tb(a,b,function(c,d,e,f,g){var k=null;1==c.nodeType?k=c:3==c.nodeType&&(k=c);null!=k&&(null!=k.assignedSlot||k.getDestinationInsertionPoints&&0<k.getDestinationInsertionPoints().length)||xb(c,d,e,f,g)})};var yb={l:function(a,b){return!(!a.querySelectorAll||!a.querySelector)&&!/^\d.*/.test(b)},g:function(a,b){var c=I(b),d="string"===typeof a?c.a.getElementById(a):a;return d?O(d,"id")==a&&b!=d&&Ka(b,d)?d:ka(L(c,"*"),function(e){return O(e,"id")==a&&b!=e&&Ka(b,e)}):null},c:function(a,b){if(!a)return[];if(yb.l(b,a))try{return b.querySelectorAll("#"+yb.F(a))}catch(c){return[]}b=L(I(b),"*",null,b);return fa(b,function(c){return O(c,"id")==a})},F:function(a){return a.replace(/([\s'"\\#.:;,!?+<>=~*^$|%&@`{}\-\/\[\]\(\)])/g,
+"\\$1")}};var U={},zb={};U.v=function(a,b,c){try{var d=N.c("a",b)}catch(e){d=L(I(b),"A",null,b)}return ka(d,function(e){e=qb(e);e=e.replace(/^[\s]+|[\s]+$/g,"");return c&&-1!=e.indexOf(a)||e==a})};U.u=function(a,b,c){try{var d=N.c("a",b)}catch(e){d=L(I(b),"A",null,b)}return fa(d,function(e){e=qb(e);e=e.replace(/^[\s]+|[\s]+$/g,"");return c&&-1!=e.indexOf(a)||e==a})};U.g=function(a,b){return U.v(a,b,!1)};U.c=function(a,b){return U.u(a,b,!1)};zb.g=function(a,b){return U.v(a,b,!0)};
+zb.c=function(a,b){return U.u(a,b,!0)};var V={i:function(a,b){return function(c){var d=V.f(a);d=S(d);c=S(c);return b.call(null,d,c)}},C:function(a){return V.i(a,function(b,c){return c.b+c.height<=b.b})},D:function(a){return V.i(a,function(b,c){return c.b>=b.b+b.height})},H:function(a){return V.i(a,function(b,c){return c.a+c.width<=b.a})},J:function(a){return V.i(a,function(b,c){return c.a>=b.a+b.width})},L:function(a){return V.i(a,function(b,c){return c.a<b.a+b.width&&c.a+c.width>b.a&&c.b+c.height<=b.b})},M:function(a){return V.i(a,function(b,
+c){return c.a<b.a+b.width&&c.a+c.width>b.a&&c.b>=b.b+b.height})},N:function(a){return V.i(a,function(b,c){return c.b<b.b+b.height&&c.b+c.height>b.b&&c.a+c.width<=b.a})},O:function(a){return V.i(a,function(b,c){return c.b<b.b+b.height&&c.b+c.height>b.b&&c.a>=b.a+b.width})},I:function(a,b){var c;b?c=b:"number"==typeof a.distance&&(c=a.distance);c||(c=50);return function(d){var e=V.f(a);if(e===d)return!1;e=S(e);d=S(d);e=new Q(e.a-c,e.b-c,e.width+2*c,e.height+2*c);return e.a<=d.a+d.width&&d.a<=e.a+e.width&&
+e.b<=d.b+d.height&&d.b<=e.b+e.height}},f:function(a){if(n(a)&&1==a.nodeType)return a;if(l(a))return V.f(a.call(null));if(n(a)){var b;a:{if(b=Ab(a)){var c=Bb[b];if(c&&l(c.g)){b=c.g(a[b],ca.document);break a}}throw new q(61,"Unsupported locator strategy: "+b);}if(!b)throw new q(7,"No element has been found by "+JSON.stringify(a));return b}throw new q(61,"Selector is of wrong type: "+JSON.stringify(a));}};
+V.B={above:V.C,below:V.D,left:V.H,near:V.I,right:V.J,straightAbove:V.L,straightBelow:V.M,straightLeft:V.N,straightRight:V.O};V.A={above:V.f,below:V.f,left:V.f,near:V.f,right:V.f,straightAbove:V.f,straightBelow:V.f,straightLeft:V.f,straightRight:V.f};
+V.G=function(a,b){var c=[];w(a,function(e){e&&ja(b,function(f){var g=f.kind,k=V.B[g];if(!k)throw new q(61,"Cannot find filter suitable for "+g);return k.apply(null,f.args)(e)},null)&&c.push(e)},null);a=b[b.length-1];var d=V.A[a?a.kind:"unknown"];return d?(a=d.apply(null,a.args))?V.K(a,c):c:c};
+V.K=function(a,b){function c(f){f=S(f);return Math.sqrt(Math.pow(d-(f.a+Math.max(1,f.width)/2),2)+Math.pow(e-(f.b+Math.max(1,f.height)/2),2))}a=S(a);var d=a.a+Math.max(1,a.width)/2,e=a.b+Math.max(1,a.height)/2;la(b,function(f,g){return c(f)-c(g)});return b};V.g=function(a,b){a=V.c(a,b);return 0==a.length?null:a[0]};
+V.c=function(a,b){if(!a.hasOwnProperty("root")||!a.hasOwnProperty("filters"))throw new q(61,"Locator not suitable for relative locators: "+JSON.stringify(a));var c=a.filters,d=aa(c);if("array"!=d&&("object"!=d||"number"!=typeof c.length))throw new q(61,"Targets should be an array: "+JSON.stringify(a));var e;P(a.root)?e=[a.root]:e=Cb(a.root,b);return 0==e.length?[]:V.G(e,a.filters)};var Db={g:function(a,b){if(""===a)throw new q(32,'Unable to locate an element with the tagName ""');return b.getElementsByTagName(a)[0]||null},c:function(a,b){if(""===a)throw new q(32,'Unable to locate an element with the tagName ""');return b.getElementsByTagName(a)}};var W={};W.m=function(){var a={P:"http://www.w3.org/2000/svg"};return function(b){return a[b]||null}}();
+W.s=function(a,b,c){var d=J(a);if(!d.documentElement)return null;try{var e=d.createNSResolver?d.createNSResolver(d.documentElement):W.m;if(E&&!Ha(7))return d.evaluate.call(d,b,a,e,c,null);if(!E||9<=Number(F)){for(var f={},g=d.getElementsByTagName("*"),k=0;k<g.length;++k){var z=g[k],A=z.namespaceURI;if(A&&!f[A]){var t=z.lookupPrefix(A);if(!t){var v=A.match(".*/(\\w+)/?$");t=v?v[1]:"xhtml"}f[A]=t}}var B={},K;for(K in f)B[f[K]]=K;e=function(m){return B[m]||null}}try{return d.evaluate(b,a,e,c,null)}catch(m){if("TypeError"===
+m.name)return e=d.createNSResolver?d.createNSResolver(d.documentElement):W.m,d.evaluate(b,a,e,c,null);throw m;}}catch(m){if(!Aa||"NS_ERROR_ILLEGAL_VALUE"!=m.name)throw new q(32,"Unable to locate an element with the xpath expression "+b+" because of the following error:\n"+m);}};W.o=function(a,b){if(!a||1!=a.nodeType)throw new q(32,'The result of the xpath expression "'+b+'" is: '+a+". It should be an element.");};
+W.g=function(a,b){var c=function(){var d=W.s(b,a,9);return d?d.singleNodeValue||null:b.selectSingleNode?(d=J(b),d.setProperty&&d.setProperty("SelectionLanguage","XPath"),b.selectSingleNode(a)):null}();null===c||W.o(c,a);return c};
+W.c=function(a,b){var c=function(){var d=W.s(b,a,7);if(d){for(var e=d.snapshotLength,f=[],g=0;g<e;++g)f.push(d.snapshotItem(g));return f}return b.selectNodes?(d=J(b),d.setProperty&&d.setProperty("SelectionLanguage","XPath"),b.selectNodes(a)):[]}();w(c,function(d){W.o(d,a)});return c};var Bb={className:Ma,"class name":Ma,css:N,"css selector":N,relative:V,id:yb,linkText:U,"link text":U,name:{g:function(a,b){b=L(I(b),"*",null,b);return ka(b,function(c){return O(c,"name")==a})},c:function(a,b){b=L(I(b),"*",null,b);return fa(b,function(c){return O(c,"name")==a})}},partialLinkText:zb,"partial link text":zb,tagName:Db,"tag name":Db,xpath:W};function Ab(a){for(var b in a)if(a.hasOwnProperty(b))return b;return null}
+function Cb(a,b){var c=Ab(a);if(c){var d=Bb[c];if(d&&l(d.c))return d.c(a[c],b||ca.document)}throw new q(61,"Unsupported locator strategy: "+c);};var Eb=Cb,X=["se_exportedFunctionSymbol"],Y=h;X[0]in Y||"undefined"==typeof Y.execScript||Y.execScript("var "+X[0]);for(var Z;X.length&&(Z=X.shift());)X.length||void 0===Eb?Y[Z]&&Y[Z]!==Object.prototype[Z]?Y=Y[Z]:Y=Y[Z]={}:Y[Z]=Eb;; return this.se_exportedFunctionSymbol.apply(null,arguments);}).apply(window, arguments);}
diff -pruN 4.4.0-1/lib/selenium/webdriver/atoms/getAttribute.js 4.38.0-1/lib/selenium/webdriver/atoms/getAttribute.js
--- 4.4.0-1/lib/selenium/webdriver/atoms/getAttribute.js	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/atoms/getAttribute.js	2025-11-02 08:23:03.000000000 +0000
@@ -1,100 +1,6 @@
-function(){return (function(){var h=this||self;function aa(a){return"string"==typeof a}function ba(a,b){a=a.split(".");var c=h;a[0]in c||"undefined"==typeof c.execScript||c.execScript("var "+a[0]);for(var d;a.length&&(d=a.shift());)a.length||void 0===b?c[d]&&c[d]!==Object.prototype[d]?c=c[d]:c=c[d]={}:c[d]=b}
-function ca(a){var b=typeof a;if("object"==b)if(a){if(a instanceof Array)return"array";if(a instanceof Object)return b;var c=Object.prototype.toString.call(a);if("[object Window]"==c)return"object";if("[object Array]"==c||"number"==typeof a.length&&"undefined"!=typeof a.splice&&"undefined"!=typeof a.propertyIsEnumerable&&!a.propertyIsEnumerable("splice"))return"array";if("[object Function]"==c||"undefined"!=typeof a.call&&"undefined"!=typeof a.propertyIsEnumerable&&!a.propertyIsEnumerable("call"))return"function"}else return"null";
-else if("function"==b&&"undefined"==typeof a.call)return"object";return b}function da(a){var b=typeof a;return"object"==b&&null!=a||"function"==b}function ea(a,b,c){return a.call.apply(a.bind,arguments)}function fa(a,b,c){if(!a)throw Error();if(2<arguments.length){var d=Array.prototype.slice.call(arguments,2);return function(){var e=Array.prototype.slice.call(arguments);Array.prototype.unshift.apply(e,d);return a.apply(b,e)}}return function(){return a.apply(b,arguments)}}
-function ha(a,b,c){Function.prototype.bind&&-1!=Function.prototype.bind.toString().indexOf("native code")?ha=ea:ha=fa;return ha.apply(null,arguments)}function ia(a,b){var c=Array.prototype.slice.call(arguments,1);return function(){var d=c.slice();d.push.apply(d,arguments);return a.apply(this,d)}}function m(a,b){function c(){}c.prototype=b.prototype;a.H=b.prototype;a.prototype=new c;a.prototype.constructor=a}
-function ja(a,b,c){var d=arguments.callee.caller;if("undefined"!==typeof d.H){for(var e=Array(arguments.length-1),f=1;f<arguments.length;f++)e[f-1]=arguments[f];d.H.constructor.apply(a,e)}else{if("string"!=typeof b&&"symbol"!=typeof b)throw Error("method names provided to goog.base must be a string or a symbol");e=Array(arguments.length-2);for(f=2;f<arguments.length;f++)e[f-2]=arguments[f];f=!1;for(var g=a.constructor.prototype;g;g=Object.getPrototypeOf(g))if(g[b]===d)f=!0;else if(f){g[b].apply(a,
-e);return}if(a[b]===d)a.constructor.prototype[b].apply(a,e);else throw Error("goog.base called from a method of one name to a method of a different name");}};/*
-
- The MIT License
-
- Copyright (c) 2007 Cybozu Labs, Inc.
- Copyright (c) 2012 Google Inc.
-
- Permission is hereby granted, free of charge, to any person obtaining a copy
- of this software and associated documentation files (the "Software"), to
- deal in the Software without restriction, including without limitation the
- rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- sell copies of the Software, and to permit persons to whom the Software is
- furnished to do so, subject to the following conditions:
-
- The above copyright notice and this permission notice shall be included in
- all copies or substantial portions of the Software.
-
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- IN THE SOFTWARE.
-*/
-function ka(a,b,c){this.a=a;this.b=b||1;this.f=c||1};var la;var ma=Array.prototype.indexOf?function(a,b){return Array.prototype.indexOf.call(a,b,void 0)}:function(a,b){if("string"===typeof a)return"string"!==typeof b||1!=b.length?-1:a.indexOf(b,0);for(var c=0;c<a.length;c++)if(c in a&&a[c]===b)return c;return-1},n=Array.prototype.forEach?function(a,b){Array.prototype.forEach.call(a,b,void 0)}:function(a,b){for(var c=a.length,d="string"===typeof a?a.split(""):a,e=0;e<c;e++)e in d&&b.call(void 0,d[e],e,a)},na=Array.prototype.filter?function(a,b){return Array.prototype.filter.call(a,
-b,void 0)}:function(a,b){for(var c=a.length,d=[],e=0,f="string"===typeof a?a.split(""):a,g=0;g<c;g++)if(g in f){var k=f[g];b.call(void 0,k,g,a)&&(d[e++]=k)}return d},oa=Array.prototype.map?function(a,b){return Array.prototype.map.call(a,b,void 0)}:function(a,b){for(var c=a.length,d=Array(c),e="string"===typeof a?a.split(""):a,f=0;f<c;f++)f in e&&(d[f]=b.call(void 0,e[f],f,a));return d},pa=Array.prototype.reduce?function(a,b,c){return Array.prototype.reduce.call(a,b,c)}:function(a,b,c){var d=c;n(a,
-function(e,f){d=b.call(void 0,d,e,f,a)});return d},qa=Array.prototype.some?function(a,b){return Array.prototype.some.call(a,b,void 0)}:function(a,b){for(var c=a.length,d="string"===typeof a?a.split(""):a,e=0;e<c;e++)if(e in d&&b.call(void 0,d[e],e,a))return!0;return!1};function ra(a,b){a:{for(var c=a.length,d="string"===typeof a?a.split(""):a,e=0;e<c;e++)if(e in d&&b.call(void 0,d[e],e,a)){b=e;break a}b=-1}return 0>b?null:"string"===typeof a?a.charAt(b):a[b]}
-function sa(a){return Array.prototype.concat.apply([],arguments)}function ta(a,b,c){return 2>=arguments.length?Array.prototype.slice.call(a,b):Array.prototype.slice.call(a,b,c)};var ua=String.prototype.trim?function(a){return a.trim()}:function(a){return/^[\s\xa0]*([\s\S]*?)[\s\xa0]*$/.exec(a)[1]};
-function va(a,b){var c=0;a=ua(String(a)).split(".");b=ua(String(b)).split(".");for(var d=Math.max(a.length,b.length),e=0;0==c&&e<d;e++){var f=a[e]||"",g=b[e]||"";do{f=/(\d*)(\D*)(.*)/.exec(f)||["","","",""];g=/(\d*)(\D*)(.*)/.exec(g)||["","","",""];if(0==f[0].length&&0==g[0].length)break;c=wa(0==f[1].length?0:parseInt(f[1],10),0==g[1].length?0:parseInt(g[1],10))||wa(0==f[2].length,0==g[2].length)||wa(f[2],g[2]);f=f[3];g=g[3]}while(0==c)}return c}function wa(a,b){return a<b?-1:a>b?1:0};var p;a:{var xa=h.navigator;if(xa){var ya=xa.userAgent;if(ya){p=ya;break a}}p=""}function q(a){return-1!=p.indexOf(a)};function za(){return q("Firefox")||q("FxiOS")}function Aa(){return(q("Chrome")||q("CriOS"))&&!q("Edge")};function Ba(){return q("iPhone")&&!q("iPod")&&!q("iPad")};function Ca(a,b){var c=Da;return Object.prototype.hasOwnProperty.call(c,a)?c[a]:c[a]=b(a)};var Ea=q("Opera"),r=q("Trident")||q("MSIE"),Fa=q("Edge"),t=q("Gecko")&&!(-1!=p.toLowerCase().indexOf("webkit")&&!q("Edge"))&&!(q("Trident")||q("MSIE"))&&!q("Edge"),Ga=-1!=p.toLowerCase().indexOf("webkit")&&!q("Edge"),Ha=q("Macintosh"),Ia=q("Windows");function Ja(){var a=h.document;return a?a.documentMode:void 0}var Ka;
-a:{var La="",Ma=function(){var a=p;if(t)return/rv:([^\);]+)(\)|;)/.exec(a);if(Fa)return/Edge\/([\d\.]+)/.exec(a);if(r)return/\b(?:MSIE|rv)[: ]([^\);]+)(\)|;)/.exec(a);if(Ga)return/WebKit\/(\S+)/.exec(a);if(Ea)return/(?:Version)[ \/]?(\S+)/.exec(a)}();Ma&&(La=Ma?Ma[1]:"");if(r){var Na=Ja();if(null!=Na&&Na>parseFloat(La)){Ka=String(Na);break a}}Ka=La}var Da={};function Oa(a){return Ca(a,function(){return 0<=va(Ka,a)})}var w;w=h.document&&r?Ja():void 0;var x=r&&!(9<=Number(w)),Pa=r&&!(8<=Number(w));function Qa(a,b,c,d){this.a=a;this.nodeName=c;this.nodeValue=d;this.nodeType=2;this.parentNode=this.ownerElement=b}function Sa(a,b){var c=Pa&&"href"==b.nodeName?a.getAttribute(b.nodeName,2):b.nodeValue;return new Qa(b,a,b.nodeName,c)};function Ta(a){this.b=a;this.a=0}function Ua(a){a=a.match(Va);for(var b=0;b<a.length;b++)Wa.test(a[b])&&a.splice(b,1);return new Ta(a)}var Va=/\$?(?:(?![0-9-\.])(?:\*|[\w-\.]+):)?(?![0-9-\.])(?:\*|[\w-\.]+)|\/\/|\.\.|::|\d+(?:\.\d*)?|\.\d+|"[^"]*"|'[^']*'|[!<>]=|\s+|./g,Wa=/^\s/;function y(a,b){return a.b[a.a+(b||0)]}function z(a){return a.b[a.a++]}function Xa(a){return a.b.length<=a.a};function Ya(a){return a.scrollingElement?a.scrollingElement:Ga||"CSS1Compat"!=a.compatMode?a.body||a.documentElement:a.documentElement}function Za(a,b){if(!a||!b)return!1;if(a.contains&&1==b.nodeType)return a==b||a.contains(b);if("undefined"!=typeof a.compareDocumentPosition)return a==b||!!(a.compareDocumentPosition(b)&16);for(;b&&a!=b;)b=b.parentNode;return b==a}
-function $a(a,b){if(a==b)return 0;if(a.compareDocumentPosition)return a.compareDocumentPosition(b)&2?1:-1;if(r&&!(9<=Number(w))){if(9==a.nodeType)return-1;if(9==b.nodeType)return 1}if("sourceIndex"in a||a.parentNode&&"sourceIndex"in a.parentNode){var c=1==a.nodeType,d=1==b.nodeType;if(c&&d)return a.sourceIndex-b.sourceIndex;var e=a.parentNode,f=b.parentNode;return e==f?ab(a,b):!c&&Za(e,b)?-1*bb(a,b):!d&&Za(f,a)?bb(b,a):(c?a.sourceIndex:e.sourceIndex)-(d?b.sourceIndex:f.sourceIndex)}d=A(a);c=d.createRange();
-c.selectNode(a);c.collapse(!0);a=d.createRange();a.selectNode(b);a.collapse(!0);return c.compareBoundaryPoints(h.Range.START_TO_END,a)}function bb(a,b){var c=a.parentNode;if(c==b)return-1;for(;b.parentNode!=c;)b=b.parentNode;return ab(b,a)}function ab(a,b){for(;b=b.previousSibling;)if(b==a)return-1;return 1}function A(a){return 9==a.nodeType?a:a.ownerDocument||a.document}var cb={SCRIPT:1,STYLE:1,HEAD:1,IFRAME:1,OBJECT:1},db={IMG:" ",BR:"\n"};
-function eb(a,b,c){if(!(a.nodeName in cb))if(3==a.nodeType)c?b.push(String(a.nodeValue).replace(/(\r\n|\r|\n)/g,"")):b.push(a.nodeValue);else if(a.nodeName in db)b.push(db[a.nodeName]);else for(a=a.firstChild;a;)eb(a,b,c),a=a.nextSibling}function fb(a){this.a=a||h.document||document}fb.prototype.getElementsByTagName=function(a,b){return(b||this.a).getElementsByTagName(String(a))};function B(a){var b=null,c=a.nodeType;1==c&&(b=a.textContent,b=void 0==b||null==b?a.innerText:b,b=void 0==b||null==b?"":b);if("string"!=typeof b)if(x&&"title"==a.nodeName.toLowerCase()&&1==c)b=a.text;else if(9==c||1==c){a=9==c?a.documentElement:a.firstChild;c=0;var d=[];for(b="";a;){do 1!=a.nodeType&&(b+=a.nodeValue),x&&"title"==a.nodeName.toLowerCase()&&(b+=a.text),d[c++]=a;while(a=a.firstChild);for(;c&&!(a=d[--c].nextSibling););}}else b=a.nodeValue;return b}
-function C(a,b,c){if(null===b)return!0;try{if(!a.getAttribute)return!1}catch(d){return!1}Pa&&"class"==b&&(b="className");return null==c?!!a.getAttribute(b):a.getAttribute(b,2)==c}function gb(a,b,c,d,e){return(x?hb:ib).call(null,a,b,aa(c)?c:null,aa(d)?d:null,e||new D)}
-function hb(a,b,c,d,e){if(a instanceof jb||8==a.b||c&&null===a.b){var f=b.all;if(!f)return e;a=kb(a);if("*"!=a&&(f=b.getElementsByTagName(a),!f))return e;if(c){for(var g=[],k=0;b=f[k++];)C(b,c,d)&&g.push(b);f=g}for(k=0;b=f[k++];)"*"==a&&"!"==b.tagName||e.add(b);return e}lb(a,b,c,d,e);return e}
-function ib(a,b,c,d,e){b.getElementsByName&&d&&"name"==c&&!r?(b=b.getElementsByName(d),n(b,function(f){a.a(f)&&e.add(f)})):b.getElementsByClassName&&d&&"class"==c?(b=b.getElementsByClassName(d),n(b,function(f){f.className==d&&a.a(f)&&e.add(f)})):a instanceof E?lb(a,b,c,d,e):b.getElementsByTagName&&(b=b.getElementsByTagName(a.f()),n(b,function(f){C(f,c,d)&&e.add(f)}));return e}
-function mb(a,b,c,d,e){var f;if((a instanceof jb||8==a.b||c&&null===a.b)&&(f=b.childNodes)){var g=kb(a);if("*"!=g&&(f=na(f,function(k){return k.tagName&&k.tagName.toLowerCase()==g}),!f))return e;c&&(f=na(f,function(k){return C(k,c,d)}));n(f,function(k){"*"==g&&("!"==k.tagName||"*"==g&&1!=k.nodeType)||e.add(k)});return e}return nb(a,b,c,d,e)}function nb(a,b,c,d,e){for(b=b.firstChild;b;b=b.nextSibling)C(b,c,d)&&a.a(b)&&e.add(b);return e}
-function lb(a,b,c,d,e){for(b=b.firstChild;b;b=b.nextSibling)C(b,c,d)&&a.a(b)&&e.add(b),lb(a,b,c,d,e)}function kb(a){if(a instanceof E){if(8==a.b)return"!";if(null===a.b)return"*"}return a.f()};function D(){this.b=this.a=null;this.o=0}function ob(a){this.f=a;this.a=this.b=null}function pb(a,b){if(!a.a)return b;if(!b.a)return a;var c=a.a;b=b.a;for(var d=null,e,f=0;c&&b;){e=c.f;var g=b.f;e==g||e instanceof Qa&&g instanceof Qa&&e.a==g.a?(e=c,c=c.a,b=b.a):0<$a(c.f,b.f)?(e=b,b=b.a):(e=c,c=c.a);(e.b=d)?d.a=e:a.a=e;d=e;f++}for(e=c||b;e;)e.b=d,d=d.a=e,f++,e=e.a;a.b=d;a.o=f;return a}function qb(a,b){b=new ob(b);b.a=a.a;a.b?a.a.b=b:a.a=a.b=b;a.a=b;a.o++}
-D.prototype.add=function(a){a=new ob(a);a.b=this.b;this.a?this.b.a=a:this.a=this.b=a;this.b=a;this.o++};function rb(a){return(a=a.a)?a.f:null}function sb(a){return(a=rb(a))?B(a):""}function F(a,b){return new tb(a,!!b)}function tb(a,b){this.f=a;this.b=(this.v=b)?a.b:a.a;this.a=null}function G(a){var b=a.b;if(null==b)return null;var c=a.a=b;a.b=a.v?b.b:b.a;return c.f};function H(a){this.l=a;this.b=this.i=!1;this.f=null}function I(a){return"\n  "+a.toString().split("\n").join("\n  ")}function ub(a,b){a.i=b}function vb(a,b){a.b=b}function J(a,b){a=a.a(b);return a instanceof D?+sb(a):+a}function L(a,b){a=a.a(b);return a instanceof D?sb(a):""+a}function wb(a,b){a=a.a(b);return a instanceof D?!!a.o:!!a};function xb(a,b,c){H.call(this,a.l);this.c=a;this.j=b;this.u=c;this.i=b.i||c.i;this.b=b.b||c.b;this.c==yb&&(c.b||c.i||4==c.l||0==c.l||!b.f?b.b||b.i||4==b.l||0==b.l||!c.f||(this.f={name:c.f.name,A:b}):this.f={name:b.f.name,A:c})}m(xb,H);
-function zb(a,b,c,d,e){b=b.a(d);c=c.a(d);var f;if(b instanceof D&&c instanceof D){b=F(b);for(d=G(b);d;d=G(b))for(e=F(c),f=G(e);f;f=G(e))if(a(B(d),B(f)))return!0;return!1}if(b instanceof D||c instanceof D){b instanceof D?(e=b,d=c):(e=c,d=b);f=F(e);for(var g=typeof d,k=G(f);k;k=G(f)){switch(g){case "number":k=+B(k);break;case "boolean":k=!!B(k);break;case "string":k=B(k);break;default:throw Error("Illegal primitive type for comparison.");}if(e==b&&a(k,d)||e==c&&a(d,k))return!0}return!1}return e?"boolean"==
-typeof b||"boolean"==typeof c?a(!!b,!!c):"number"==typeof b||"number"==typeof c?a(+b,+c):a(b,c):a(+b,+c)}xb.prototype.a=function(a){return this.c.s(this.j,this.u,a)};xb.prototype.toString=function(){var a="Binary Expression: "+this.c;a+=I(this.j);return a+=I(this.u)};function Ab(a,b,c,d){this.L=a;this.G=b;this.l=c;this.s=d}Ab.prototype.toString=function(){return this.L};var Bb={};
-function M(a,b,c,d){if(Bb.hasOwnProperty(a))throw Error("Binary operator already created: "+a);a=new Ab(a,b,c,d);return Bb[a.toString()]=a}M("div",6,1,function(a,b,c){return J(a,c)/J(b,c)});M("mod",6,1,function(a,b,c){return J(a,c)%J(b,c)});M("*",6,1,function(a,b,c){return J(a,c)*J(b,c)});M("+",5,1,function(a,b,c){return J(a,c)+J(b,c)});M("-",5,1,function(a,b,c){return J(a,c)-J(b,c)});M("<",4,2,function(a,b,c){return zb(function(d,e){return d<e},a,b,c)});
-M(">",4,2,function(a,b,c){return zb(function(d,e){return d>e},a,b,c)});M("<=",4,2,function(a,b,c){return zb(function(d,e){return d<=e},a,b,c)});M(">=",4,2,function(a,b,c){return zb(function(d,e){return d>=e},a,b,c)});var yb=M("=",3,2,function(a,b,c){return zb(function(d,e){return d==e},a,b,c,!0)});M("!=",3,2,function(a,b,c){return zb(function(d,e){return d!=e},a,b,c,!0)});M("and",2,2,function(a,b,c){return wb(a,c)&&wb(b,c)});M("or",1,2,function(a,b,c){return wb(a,c)||wb(b,c)});function Cb(a,b){if(b.a.length&&4!=a.l)throw Error("Primary expression must evaluate to nodeset if filter has predicate(s).");H.call(this,a.l);this.c=a;this.j=b;this.i=a.i;this.b=a.b}m(Cb,H);Cb.prototype.a=function(a){a=this.c.a(a);return Db(this.j,a)};Cb.prototype.toString=function(){var a="Filter:"+I(this.c);return a+=I(this.j)};function Eb(a,b){if(b.length<a.F)throw Error("Function "+a.m+" expects at least"+a.F+" arguments, "+b.length+" given");if(null!==a.D&&b.length>a.D)throw Error("Function "+a.m+" expects at most "+a.D+" arguments, "+b.length+" given");a.K&&n(b,function(c,d){if(4!=c.l)throw Error("Argument "+d+" to function "+a.m+" is not of type Nodeset: "+c);});H.call(this,a.l);this.B=a;this.c=b;ub(this,a.i||qa(b,function(c){return c.i}));vb(this,a.J&&!b.length||a.I&&!!b.length||qa(b,function(c){return c.b}))}
-m(Eb,H);Eb.prototype.a=function(a){return this.B.s.apply(null,sa(a,this.c))};Eb.prototype.toString=function(){var a="Function: "+this.B;if(this.c.length){var b=pa(this.c,function(c,d){return c+I(d)},"Arguments:");a+=I(b)}return a};function Fb(a,b,c,d,e,f,g,k){this.m=a;this.l=b;this.i=c;this.J=d;this.I=!1;this.s=e;this.F=f;this.D=void 0!==g?g:f;this.K=!!k}Fb.prototype.toString=function(){return this.m};var Gb={};
-function N(a,b,c,d,e,f,g,k){if(Gb.hasOwnProperty(a))throw Error("Function already created: "+a+".");Gb[a]=new Fb(a,b,c,d,e,f,g,k)}N("boolean",2,!1,!1,function(a,b){return wb(b,a)},1);N("ceiling",1,!1,!1,function(a,b){return Math.ceil(J(b,a))},1);N("concat",3,!1,!1,function(a,b){return pa(ta(arguments,1),function(c,d){return c+L(d,a)},"")},2,null);N("contains",2,!1,!1,function(a,b,c){b=L(b,a);a=L(c,a);return-1!=b.indexOf(a)},2);N("count",1,!1,!1,function(a,b){return b.a(a).o},1,1,!0);
-N("false",2,!1,!1,function(){return!1},0);N("floor",1,!1,!1,function(a,b){return Math.floor(J(b,a))},1);N("id",4,!1,!1,function(a,b){function c(k){if(x){var l=e.all[k];if(l){if(l.nodeType&&k==l.id)return l;if(l.length)return ra(l,function(u){return k==u.id})}return null}return e.getElementById(k)}var d=a.a,e=9==d.nodeType?d:d.ownerDocument;a=L(b,a).split(/\s+/);var f=[];n(a,function(k){k=c(k);!k||0<=ma(f,k)||f.push(k)});f.sort($a);var g=new D;n(f,function(k){g.add(k)});return g},1);
-N("lang",2,!1,!1,function(){return!1},1);N("last",1,!0,!1,function(a){if(1!=arguments.length)throw Error("Function last expects ()");return a.f},0);N("local-name",3,!1,!0,function(a,b){return(a=b?rb(b.a(a)):a.a)?a.localName||a.nodeName.toLowerCase():""},0,1,!0);N("name",3,!1,!0,function(a,b){return(a=b?rb(b.a(a)):a.a)?a.nodeName.toLowerCase():""},0,1,!0);N("namespace-uri",3,!0,!1,function(){return""},0,1,!0);
-N("normalize-space",3,!1,!0,function(a,b){return(b?L(b,a):B(a.a)).replace(/[\s\xa0]+/g," ").replace(/^\s+|\s+$/g,"")},0,1);N("not",2,!1,!1,function(a,b){return!wb(b,a)},1);N("number",1,!1,!0,function(a,b){return b?J(b,a):+B(a.a)},0,1);N("position",1,!0,!1,function(a){return a.b},0);N("round",1,!1,!1,function(a,b){return Math.round(J(b,a))},1);N("starts-with",2,!1,!1,function(a,b,c){b=L(b,a);a=L(c,a);return 0==b.lastIndexOf(a,0)},2);N("string",3,!1,!0,function(a,b){return b?L(b,a):B(a.a)},0,1);
-N("string-length",1,!1,!0,function(a,b){return(b?L(b,a):B(a.a)).length},0,1);N("substring",3,!1,!1,function(a,b,c,d){c=J(c,a);if(isNaN(c)||Infinity==c||-Infinity==c)return"";d=d?J(d,a):Infinity;if(isNaN(d)||-Infinity===d)return"";c=Math.round(c)-1;var e=Math.max(c,0);a=L(b,a);return Infinity==d?a.substring(e):a.substring(e,c+Math.round(d))},2,3);N("substring-after",3,!1,!1,function(a,b,c){b=L(b,a);a=L(c,a);c=b.indexOf(a);return-1==c?"":b.substring(c+a.length)},2);
-N("substring-before",3,!1,!1,function(a,b,c){b=L(b,a);a=L(c,a);a=b.indexOf(a);return-1==a?"":b.substring(0,a)},2);N("sum",1,!1,!1,function(a,b){a=F(b.a(a));b=0;for(var c=G(a);c;c=G(a))b+=+B(c);return b},1,1,!0);N("translate",3,!1,!1,function(a,b,c,d){b=L(b,a);c=L(c,a);var e=L(d,a);a={};for(d=0;d<c.length;d++){var f=c.charAt(d);f in a||(a[f]=e.charAt(d))}c="";for(d=0;d<b.length;d++)f=b.charAt(d),c+=f in a?a[f]:f;return c},3);N("true",2,!1,!1,function(){return!0},0);function E(a,b){this.j=a;this.c=void 0!==b?b:null;this.b=null;switch(a){case "comment":this.b=8;break;case "text":this.b=3;break;case "processing-instruction":this.b=7;break;case "node":break;default:throw Error("Unexpected argument");}}function Hb(a){return"comment"==a||"text"==a||"processing-instruction"==a||"node"==a}E.prototype.a=function(a){return null===this.b||this.b==a.nodeType};E.prototype.f=function(){return this.j};
-E.prototype.toString=function(){var a="Kind Test: "+this.j;null===this.c||(a+=I(this.c));return a};function Ib(a){H.call(this,3);this.c=a.substring(1,a.length-1)}m(Ib,H);Ib.prototype.a=function(){return this.c};Ib.prototype.toString=function(){return"Literal: "+this.c};function jb(a,b){this.m=a.toLowerCase();a="*"==this.m?"*":"http://www.w3.org/1999/xhtml";this.c=b?b.toLowerCase():a}jb.prototype.a=function(a){var b=a.nodeType;if(1!=b&&2!=b)return!1;b=void 0!==a.localName?a.localName:a.nodeName;return"*"!=this.m&&this.m!=b.toLowerCase()?!1:"*"==this.c?!0:this.c==(a.namespaceURI?a.namespaceURI.toLowerCase():"http://www.w3.org/1999/xhtml")};jb.prototype.f=function(){return this.m};
-jb.prototype.toString=function(){return"Name Test: "+("http://www.w3.org/1999/xhtml"==this.c?"":this.c+":")+this.m};function Jb(a){H.call(this,1);this.c=a}m(Jb,H);Jb.prototype.a=function(){return this.c};Jb.prototype.toString=function(){return"Number: "+this.c};function Kb(a,b){H.call(this,a.l);this.j=a;this.c=b;this.i=a.i;this.b=a.b;1==this.c.length&&(a=this.c[0],a.C||a.c!=Lb||(a=a.u,"*"!=a.f()&&(this.f={name:a.f(),A:null})))}m(Kb,H);function Mb(){H.call(this,4)}m(Mb,H);Mb.prototype.a=function(a){var b=new D;a=a.a;9==a.nodeType?b.add(a):b.add(a.ownerDocument);return b};Mb.prototype.toString=function(){return"Root Helper Expression"};function Nb(){H.call(this,4)}m(Nb,H);Nb.prototype.a=function(a){var b=new D;b.add(a.a);return b};Nb.prototype.toString=function(){return"Context Helper Expression"};
-function Ob(a){return"/"==a||"//"==a}Kb.prototype.a=function(a){var b=this.j.a(a);if(!(b instanceof D))throw Error("Filter expression must evaluate to nodeset.");a=this.c;for(var c=0,d=a.length;c<d&&b.o;c++){var e=a[c],f=F(b,e.c.v);if(e.i||e.c!=Pb)if(e.i||e.c!=Qb){var g=G(f);for(b=e.a(new ka(g));null!=(g=G(f));)g=e.a(new ka(g)),b=pb(b,g)}else g=G(f),b=e.a(new ka(g));else{for(g=G(f);(b=G(f))&&(!g.contains||g.contains(b))&&b.compareDocumentPosition(g)&8;g=b);b=e.a(new ka(g))}}return b};
-Kb.prototype.toString=function(){var a="Path Expression:"+I(this.j);if(this.c.length){var b=pa(this.c,function(c,d){return c+I(d)},"Steps:");a+=I(b)}return a};function Rb(a,b){this.a=a;this.v=!!b}
-function Db(a,b,c){for(c=c||0;c<a.a.length;c++)for(var d=a.a[c],e=F(b),f=b.o,g,k=0;g=G(e);k++){var l=a.v?f-k:k+1;g=d.a(new ka(g,l,f));if("number"==typeof g)l=l==g;else if("string"==typeof g||"boolean"==typeof g)l=!!g;else if(g instanceof D)l=0<g.o;else throw Error("Predicate.evaluate returned an unexpected type.");if(!l){l=e;g=l.f;var u=l.a;if(!u)throw Error("Next must be called at least once before remove.");var K=u.b;u=u.a;K?K.a=u:g.a=u;u?u.b=K:g.b=K;g.o--;l.a=null}}return b}
-Rb.prototype.toString=function(){return pa(this.a,function(a,b){return a+I(b)},"Predicates:")};function O(a,b,c,d){H.call(this,4);this.c=a;this.u=b;this.j=c||new Rb([]);this.C=!!d;b=this.j;b=0<b.a.length?b.a[0].f:null;a.M&&b&&(a=b.name,a=x?a.toLowerCase():a,this.f={name:a,A:b.A});a:{a=this.j;for(b=0;b<a.a.length;b++)if(c=a.a[b],c.i||1==c.l||0==c.l){a=!0;break a}a=!1}this.i=a}m(O,H);
-O.prototype.a=function(a){var b=a.a,c=this.f,d=null,e=null,f=0;c&&(d=c.name,e=c.A?L(c.A,a):null,f=1);if(this.C)if(this.i||this.c!=Sb)if(b=F((new O(Tb,new E("node"))).a(a)),c=G(b))for(a=this.s(c,d,e,f);null!=(c=G(b));)a=pb(a,this.s(c,d,e,f));else a=new D;else a=gb(this.u,b,d,e),a=Db(this.j,a,f);else a=this.s(a.a,d,e,f);return a};O.prototype.s=function(a,b,c,d){a=this.c.B(this.u,a,b,c);return a=Db(this.j,a,d)};
-O.prototype.toString=function(){var a="Step:"+I("Operator: "+(this.C?"//":"/"));this.c.m&&(a+=I("Axis: "+this.c));a+=I(this.u);if(this.j.a.length){var b=pa(this.j.a,function(c,d){return c+I(d)},"Predicates:");a+=I(b)}return a};function Ub(a,b,c,d){this.m=a;this.B=b;this.v=c;this.M=d}Ub.prototype.toString=function(){return this.m};var Vb={};function P(a,b,c,d){if(Vb.hasOwnProperty(a))throw Error("Axis already created: "+a);b=new Ub(a,b,c,!!d);return Vb[a]=b}
-P("ancestor",function(a,b){for(var c=new D;b=b.parentNode;)a.a(b)&&qb(c,b);return c},!0);P("ancestor-or-self",function(a,b){var c=new D;do a.a(b)&&qb(c,b);while(b=b.parentNode);return c},!0);
-var Lb=P("attribute",function(a,b){var c=new D,d=a.f();if("style"==d&&x&&b.style)return c.add(new Qa(b.style,b,"style",b.style.cssText)),c;var e=b.attributes;if(e)if(a instanceof E&&null===a.b||"*"==d)for(a=0;d=e[a];a++)x?d.nodeValue&&c.add(Sa(b,d)):c.add(d);else(d=e.getNamedItem(d))&&(x?d.nodeValue&&c.add(Sa(b,d)):c.add(d));return c},!1),Sb=P("child",function(a,b,c,d,e){return(x?mb:nb).call(null,a,b,aa(c)?c:null,aa(d)?d:null,e||new D)},!1,!0);P("descendant",gb,!1,!0);
-var Tb=P("descendant-or-self",function(a,b,c,d){var e=new D;C(b,c,d)&&a.a(b)&&e.add(b);return gb(a,b,c,d,e)},!1,!0),Pb=P("following",function(a,b,c,d){var e=new D;do for(var f=b;f=f.nextSibling;)C(f,c,d)&&a.a(f)&&e.add(f),e=gb(a,f,c,d,e);while(b=b.parentNode);return e},!1,!0);P("following-sibling",function(a,b){for(var c=new D;b=b.nextSibling;)a.a(b)&&c.add(b);return c},!1);P("namespace",function(){return new D},!1);
-var Wb=P("parent",function(a,b){var c=new D;if(9==b.nodeType)return c;if(2==b.nodeType)return c.add(b.ownerElement),c;b=b.parentNode;a.a(b)&&c.add(b);return c},!1),Qb=P("preceding",function(a,b,c,d){var e=new D,f=[];do f.unshift(b);while(b=b.parentNode);for(var g=1,k=f.length;g<k;g++){var l=[];for(b=f[g];b=b.previousSibling;)l.unshift(b);for(var u=0,K=l.length;u<K;u++)b=l[u],C(b,c,d)&&a.a(b)&&e.add(b),e=gb(a,b,c,d,e)}return e},!0,!0);
-P("preceding-sibling",function(a,b){for(var c=new D;b=b.previousSibling;)a.a(b)&&qb(c,b);return c},!0);var Xb=P("self",function(a,b){var c=new D;a.a(b)&&c.add(b);return c},!1);function Yb(a){H.call(this,1);this.c=a;this.i=a.i;this.b=a.b}m(Yb,H);Yb.prototype.a=function(a){return-J(this.c,a)};Yb.prototype.toString=function(){return"Unary Expression: -"+I(this.c)};function Zb(a){H.call(this,4);this.c=a;ub(this,qa(this.c,function(b){return b.i}));vb(this,qa(this.c,function(b){return b.b}))}m(Zb,H);Zb.prototype.a=function(a){var b=new D;n(this.c,function(c){c=c.a(a);if(!(c instanceof D))throw Error("Path expression must evaluate to NodeSet.");b=pb(b,c)});return b};Zb.prototype.toString=function(){return pa(this.c,function(a,b){return a+I(b)},"Union Expression:")};function $b(a,b){this.a=a;this.b=b}function ac(a){for(var b,c=[];;){Q(a,"Missing right hand side of binary expression.");b=bc(a);var d=z(a.a);if(!d)break;var e=(d=Bb[d]||null)&&d.G;if(!e){a.a.a--;break}for(;c.length&&e<=c[c.length-1].G;)b=new xb(c.pop(),c.pop(),b);c.push(b,d)}for(;c.length;)b=new xb(c.pop(),c.pop(),b);return b}function Q(a,b){if(Xa(a.a))throw Error(b);}function cc(a,b){a=z(a.a);if(a!=b)throw Error("Bad token, expected: "+b+" got: "+a);}
-function dc(a){a=z(a.a);if(")"!=a)throw Error("Bad token: "+a);}function ec(a){a=z(a.a);if(2>a.length)throw Error("Unclosed literal string");return new Ib(a)}
-function fc(a){var b=[];if(Ob(y(a.a))){var c=z(a.a);var d=y(a.a);if("/"==c&&(Xa(a.a)||"."!=d&&".."!=d&&"@"!=d&&"*"!=d&&!/(?![0-9])[\w]/.test(d)))return new Mb;d=new Mb;Q(a,"Missing next location step.");c=gc(a,c);b.push(c)}else{a:{c=y(a.a);d=c.charAt(0);switch(d){case "$":throw Error("Variable reference not allowed in HTML XPath");case "(":z(a.a);c=ac(a);Q(a,'unclosed "("');cc(a,")");break;case '"':case "'":c=ec(a);break;default:if(isNaN(+c))if(!Hb(c)&&/(?![0-9])[\w]/.test(d)&&"("==y(a.a,1)){c=z(a.a);
-c=Gb[c]||null;z(a.a);for(d=[];")"!=y(a.a);){Q(a,"Missing function argument list.");d.push(ac(a));if(","!=y(a.a))break;z(a.a)}Q(a,"Unclosed function argument list.");dc(a);c=new Eb(c,d)}else{c=null;break a}else c=new Jb(+z(a.a))}"["==y(a.a)&&(d=new Rb(hc(a)),c=new Cb(c,d))}if(c)if(Ob(y(a.a)))d=c;else return c;else c=gc(a,"/"),d=new Nb,b.push(c)}for(;Ob(y(a.a));)c=z(a.a),Q(a,"Missing next location step."),c=gc(a,c),b.push(c);return new Kb(d,b)}
-function gc(a,b){if("/"!=b&&"//"!=b)throw Error('Step op should be "/" or "//"');if("."==y(a.a)){var c=new O(Xb,new E("node"));z(a.a);return c}if(".."==y(a.a))return c=new O(Wb,new E("node")),z(a.a),c;if("@"==y(a.a)){var d=Lb;z(a.a);Q(a,"Missing attribute name")}else if("::"==y(a.a,1)){if(!/(?![0-9])[\w]/.test(y(a.a).charAt(0)))throw Error("Bad token: "+z(a.a));var e=z(a.a);d=Vb[e]||null;if(!d)throw Error("No axis with name: "+e);z(a.a);Q(a,"Missing node name")}else d=Sb;e=y(a.a);if(/(?![0-9])[\w\*]/.test(e.charAt(0)))if("("==
-y(a.a,1)){if(!Hb(e))throw Error("Invalid node type: "+e);e=z(a.a);if(!Hb(e))throw Error("Invalid type name: "+e);cc(a,"(");Q(a,"Bad nodetype");var f=y(a.a).charAt(0),g=null;if('"'==f||"'"==f)g=ec(a);Q(a,"Bad nodetype");dc(a);e=new E(e,g)}else if(e=z(a.a),f=e.indexOf(":"),-1==f)e=new jb(e);else{g=e.substring(0,f);if("*"==g)var k="*";else if(k=a.b(g),!k)throw Error("Namespace prefix not declared: "+g);e=e.substr(f+1);e=new jb(e,k)}else throw Error("Bad token: "+z(a.a));a=new Rb(hc(a),d.v);return c||
-new O(d,e,a,"//"==b)}function hc(a){for(var b=[];"["==y(a.a);){z(a.a);Q(a,"Missing predicate expression.");var c=ac(a);b.push(c);Q(a,"Unclosed predicate expression.");cc(a,"]")}return b}function bc(a){if("-"==y(a.a))return z(a.a),new Yb(bc(a));var b=fc(a);if("|"!=y(a.a))a=b;else{for(b=[b];"|"==z(a.a);)Q(a,"Missing next union location path."),b.push(fc(a));a.a.a--;a=new Zb(b)}return a};function ic(a){switch(a.nodeType){case 1:return ia(jc,a);case 9:return ic(a.documentElement);case 11:case 10:case 6:case 12:return kc;default:return a.parentNode?ic(a.parentNode):kc}}function kc(){return null}function jc(a,b){if(a.prefix==b)return a.namespaceURI||"http://www.w3.org/1999/xhtml";var c=a.getAttributeNode("xmlns:"+b);return c&&c.specified?c.value||null:a.parentNode&&9!=a.parentNode.nodeType?jc(a.parentNode,b):null};function lc(a,b){if(!a.length)throw Error("Empty XPath expression.");a=Ua(a);if(Xa(a))throw Error("Invalid XPath expression.");b?"function"==ca(b)||(b=ha(b.lookupNamespaceURI,b)):b=function(){return null};var c=ac(new $b(a,b));if(!Xa(a))throw Error("Bad token: "+z(a));this.evaluate=function(d,e){d=c.a(new ka(d));return new T(d,e)}}
-function T(a,b){if(0==b)if(a instanceof D)b=4;else if("string"==typeof a)b=2;else if("number"==typeof a)b=1;else if("boolean"==typeof a)b=3;else throw Error("Unexpected evaluation result.");if(2!=b&&1!=b&&3!=b&&!(a instanceof D))throw Error("value could not be converted to the specified type");this.resultType=b;switch(b){case 2:this.stringValue=a instanceof D?sb(a):""+a;break;case 1:this.numberValue=a instanceof D?+sb(a):+a;break;case 3:this.booleanValue=a instanceof D?0<a.o:!!a;break;case 4:case 5:case 6:case 7:var c=
-F(a);var d=[];for(var e=G(c);e;e=G(c))d.push(e instanceof Qa?e.a:e);this.snapshotLength=a.o;this.invalidIteratorState=!1;break;case 8:case 9:a=rb(a);this.singleNodeValue=a instanceof Qa?a.a:a;break;default:throw Error("Unknown XPathResult type.");}var f=0;this.iterateNext=function(){if(4!=b&&5!=b)throw Error("iterateNext called with wrong result type");return f>=d.length?null:d[f++]};this.snapshotItem=function(g){if(6!=b&&7!=b)throw Error("snapshotItem called with wrong result type");return g>=d.length||
-0>g?null:d[g]}}T.ANY_TYPE=0;T.NUMBER_TYPE=1;T.STRING_TYPE=2;T.BOOLEAN_TYPE=3;T.UNORDERED_NODE_ITERATOR_TYPE=4;T.ORDERED_NODE_ITERATOR_TYPE=5;T.UNORDERED_NODE_SNAPSHOT_TYPE=6;T.ORDERED_NODE_SNAPSHOT_TYPE=7;T.ANY_UNORDERED_NODE_TYPE=8;T.FIRST_ORDERED_NODE_TYPE=9;function mc(a){this.lookupNamespaceURI=ic(a)}
-function nc(a,b){a=a||h;var c=a.Document&&a.Document.prototype||a.document;if(!c.evaluate||b)a.XPathResult=T,c.evaluate=function(d,e,f,g){return(new lc(d,f)).evaluate(e,g)},c.createExpression=function(d,e){return new lc(d,e)},c.createNSResolver=function(d){return new mc(d)}}ba("wgxpath.install",nc);ba("wgxpath.install",nc);var oc=window;function U(a,b){this.code=a;this.a=V[a]||pc;this.message=b||"";a=this.a.replace(/((?:^|\s+)[a-z])/g,function(c){return c.toUpperCase().replace(/^[\s\xa0]+/g,"")});b=a.length-5;if(0>b||a.indexOf("Error",b)!=b)a+="Error";this.name=a;a=Error(this.message);a.name=this.name;this.stack=a.stack||""}m(U,Error);var pc="unknown error",V={15:"element not selectable",11:"element not visible"};V[31]=pc;V[30]=pc;V[24]="invalid cookie domain";V[29]="invalid element coordinates";V[12]="invalid element state";
-V[32]="invalid selector";V[51]="invalid selector";V[52]="invalid selector";V[17]="javascript error";V[405]="unsupported operation";V[34]="move target out of bounds";V[27]="no such alert";V[7]="no such element";V[8]="no such frame";V[23]="no such window";V[28]="script timeout";V[33]="session not created";V[10]="stale element reference";V[21]="timeout";V[25]="unable to set cookie";V[26]="unexpected alert open";V[13]=pc;V[9]="unknown command";var qc=za(),rc=Ba()||q("iPod"),sc=q("iPad"),tc=q("Android")&&!(Aa()||za()||q("Opera")||q("Silk")),uc=Aa(),vc=q("Safari")&&!(Aa()||q("Coast")||q("Opera")||q("Edge")||q("Edg/")||q("OPR")||za()||q("Silk")||q("Android"))&&!(Ba()||q("iPad")||q("iPod"));function wc(a){return(a=a.exec(p))?a[1]:""}var xc=function(){if(qc)return wc(/Firefox\/([0-9.]+)/);if(r||Fa||Ea)return Ka;if(uc)return Ba()||q("iPad")||q("iPod")?wc(/CriOS\/([0-9.]+)/):wc(/Chrome\/([0-9.]+)/);if(vc&&!(Ba()||q("iPad")||q("iPod")))return wc(/Version\/([0-9.]+)/);if(rc||sc){var a=/Version\/(\S+).*Mobile\/(\S+)/.exec(p);if(a)return a[1]+"."+a[2]}else if(tc)return(a=wc(/Android\s+([0-9.]+)/))?a:wc(/Version\/([0-9.]+)/);return""}();var yc=sc||rc,zc;if(tc){var Ac=/Android\s+([0-9\.]+)/.exec(p);zc=Ac?Ac[1]:"0"}else zc="0";var Bc=zc,Cc=r&&!(8<=Number(w)),Dc=r&&!(9<=Number(w));function Ec(a,b){b=b.toLowerCase();return"style"==b?Fc(a.style.cssText):Cc&&"value"==b&&Gc(a,"INPUT")?a.value:Dc&&!0===a[b]?String(a.getAttribute(b)):(a=a.getAttributeNode(b))&&a.specified?a.value:null}var Hc=/[;]+(?=(?:(?:[^"]*"){2})*[^"]*$)(?=(?:(?:[^']*'){2})*[^']*$)(?=(?:[^()]*\([^()]*\))*[^()]*$)/;
-function Fc(a){var b=[];n(a.split(Hc),function(c){var d=c.indexOf(":");0<d&&(c=[c.slice(0,d),c.slice(d+1)],2==c.length&&b.push(c[0].toLowerCase(),":",c[1],";"))});b=b.join("");return b=";"==b.charAt(b.length-1)?b:b+";"}function Ic(a,b){Cc&&"value"==b&&Gc(a,"OPTION")&&null===Ec(a,"value")?(b=[],eb(a,b,!1),a=b.join("")):a=a[b];return a}function Gc(a,b){b&&"string"!==typeof b&&(b=b.toString());return!!a&&1==a.nodeType&&(!b||a.tagName.toUpperCase()==b)}
-function Jc(a){return Gc(a,"OPTION")?!0:Gc(a,"INPUT")?(a=a.type.toLowerCase(),"checkbox"==a||"radio"==a):!1};function Kc(a){a=a?A(a):document;return!r||9<=Number(w)||"CSS1Compat"==(a?new fb(A(a)):la||(la=new fb)).a.compatMode?a.documentElement:a.body};var Lc=!(r&&!(r?0<=va(w,10):Oa(10))),Mc=tc?!(tc?0<=va(Bc,4):0<=va(xc,4)):!yc,Nc=r&&oc.navigator.msPointerEnabled;function Oc(a,b,c){this.a=a;this.b=b;this.f=c}Oc.prototype.create=function(a){a=A(a).createEvent("HTMLEvents");a.initEvent(this.a,this.b,this.f);return a};Oc.prototype.toString=function(){return this.a};function W(a,b,c){ja(this,a,b,c)}m(W,Oc);
-W.prototype.create=function(a,b){if(!t&&this==Pc)throw new U(9,"Browser does not support a mouse pixel scroll event.");var c=A(a),d=c?c.parentWindow||c.defaultView:window;var e=c.createEvent("MouseEvents");var f=1;this==Qc&&(t||(e.wheelDelta=b.wheelDelta),t&&(f=b.wheelDelta/-40));t&&this==Pc&&(f=b.wheelDelta);e.initMouseEvent(this.a,this.b,this.f,d,f,b.clientX,b.clientY,b.clientX,b.clientY,b.ctrlKey,b.altKey,b.shiftKey,b.metaKey,b.button,b.relatedTarget);if(r&&0===e.pageX&&0===e.pageY&&Object.defineProperty){a=
-Ya((a?new fb(A(a)):la||(la=new fb)).a);c=Kc(c);var g=b.clientX+a.scrollLeft-c.clientLeft,k=b.clientY+a.scrollTop-c.clientTop;Object.defineProperty(e,"pageX",{get:function(){return g}});Object.defineProperty(e,"pageY",{get:function(){return k}})}return e};function Rc(a,b,c){ja(this,a,b,c)}m(Rc,Oc);
-Rc.prototype.create=function(a,b){var c=A(a);if(t&&!(r?0<=va(w,93):Oa(93))){a=c?c.parentWindow||c.defaultView:window;var d=b.charCode?0:b.keyCode;c=c.createEvent("KeyboardEvent");c.initKeyEvent(this.a,this.b,this.f,a,b.ctrlKey,b.altKey,b.shiftKey,b.metaKey,d,b.charCode);this.a==Sc&&b.preventDefault&&c.preventDefault()}else if(c=c.createEvent("Events"),c.initEvent(this.a,this.b,this.f),c.altKey=b.altKey,c.ctrlKey=b.ctrlKey,c.metaKey=b.metaKey,c.shiftKey=b.shiftKey,c.keyCode=b.charCode||b.keyCode,Ga||
-Fa)c.charCode=this==Sc?c.keyCode:0;return c};function Tc(a,b,c){ja(this,a,b,c)}m(Tc,Oc);
-Tc.prototype.create=function(a,b){function c(R){R=oa(R,function(v){return g.createTouch(k,a,v.identifier,v.pageX,v.pageY,v.screenX,v.screenY)});return g.createTouchList.apply(g,R)}function d(R){var v=oa(R,function(S){return{identifier:S.identifier,screenX:S.screenX,screenY:S.screenY,clientX:S.clientX,clientY:S.clientY,pageX:S.pageX,pageY:S.pageY,target:a}});v.item=function(S){return v[S]};return v}function e(R){return oa(R,function(v){return new Touch({identifier:v.identifier,screenX:v.screenX,screenY:v.screenY,
-clientX:v.clientX,clientY:v.clientY,pageX:v.pageX,pageY:v.pageY,target:a})})}function f(R,v){switch(R){case 1:return d(v);case 2:return c(v);case 3:return e(v)}return null}if(!Lc)throw new U(9,"Browser does not support firing touch events.");var g=A(a),k=g?g.parentWindow||g.defaultView:window;if(Mc)var l=1;else if(TouchEvent.prototype.initTouchEvent)l=2;else if(TouchEvent&&0<TouchEvent.length)l=3;else throw new U(9,"Not able to create touch events in this browser");var u=f(l,b.changedTouches),K=b.touches==
-b.changedTouches?u:f(l,b.touches),Ra=b.targetTouches==b.changedTouches?u:f(l,b.targetTouches);if(1==l)l=g.createEvent("MouseEvents"),l.initMouseEvent(this.a,this.b,this.f,k,1,0,0,b.clientX,b.clientY,b.ctrlKey,b.altKey,b.shiftKey,b.metaKey,0,b.relatedTarget),l.touches=K,l.targetTouches=Ra,l.changedTouches=u,l.scale=b.scale,l.rotation=b.rotation;else if(2==l)l=g.createEvent("TouchEvent"),0==l.initTouchEvent.length?l.initTouchEvent(K,Ra,u,this.a,k,0,0,b.clientX,b.clientY,b.ctrlKey,b.altKey,b.shiftKey,
-b.metaKey):l.initTouchEvent(this.a,this.b,this.f,k,1,0,0,b.clientX,b.clientY,b.ctrlKey,b.altKey,b.shiftKey,b.metaKey,K,Ra,u,b.scale,b.rotation),l.relatedTarget=b.relatedTarget;else if(3==l)l=new TouchEvent(this.a,{touches:K,targetTouches:Ra,changedTouches:u,bubbles:this.b,cancelable:this.f,ctrlKey:b.ctrlKey,shiftKey:b.shiftKey,altKey:b.altKey,metaKey:b.metaKey});else throw new U(9,"Illegal TouchEventStrategy_ value (this is a bug)");return l};function X(a,b,c){ja(this,a,b,c)}m(X,Oc);
-X.prototype.create=function(a,b){if(!Nc)throw new U(9,"Browser does not support MSGesture events.");var c=A(a);a=c?c.parentWindow||c.defaultView:window;c=c.createEvent("MSGestureEvent");c.initGestureEvent(this.a,this.b,this.f,a,1,0,0,b.clientX,b.clientY,0,0,b.translationX,b.translationY,b.scale,b.expansion,b.rotation,b.velocityX,b.velocityY,b.velocityExpansion,b.velocityAngular,(new Date).getTime(),b.relatedTarget);return c};function Y(a,b,c){ja(this,a,b,c)}m(Y,Oc);
-Y.prototype.create=function(a,b){if(!Nc)throw new U(9,"Browser does not support MSPointer events.");var c=A(a);a=c?c.parentWindow||c.defaultView:window;c=c.createEvent("MSPointerEvent");c.initPointerEvent(this.a,this.b,this.f,a,0,0,0,b.clientX,b.clientY,b.ctrlKey,b.altKey,b.shiftKey,b.metaKey,b.button,b.relatedTarget,0,0,b.width,b.height,b.pressure,b.rotation,b.tiltX,b.tiltY,b.pointerId,b.pointerType,0,b.isPrimary);return c};new W("click",!0,!0);new W("contextmenu",!0,!0);new W("dblclick",!0,!0);
-new W("mousedown",!0,!0);new W("mousemove",!0,!1);new W("mouseout",!0,!0);new W("mouseover",!0,!0);new W("mouseup",!0,!0);var Qc=new W(t?"DOMMouseScroll":"mousewheel",!0,!0),Pc=new W("MozMousePixelScroll",!0,!0);new Rc("keydown",!0,!0);var Sc=new Rc("keypress",!0,!0);new Rc("keyup",!0,!0);new Tc("touchend",!0,!0);new Tc("touchmove",!0,!0);new Tc("touchstart",!0,!0);new X("MSGestureChange",!0,!0);new X("MSGestureEnd",!0,!0);new X("MSGestureHold",!0,!0);new X("MSGestureStart",!0,!0);
-new X("MSGestureTap",!0,!0);new X("MSInertiaStart",!0,!0);new Y("MSGotPointerCapture",!0,!1);new Y("MSLostPointerCapture",!0,!1);new Y("MSPointerCancel",!0,!0);new Y("MSPointerDown",!0,!0);new Y("MSPointerMove",!0,!0);new Y("MSPointerOver",!0,!0);new Y("MSPointerOut",!0,!0);new Y("MSPointerUp",!0,!0);function Uc(a,b){this.b={};this.a=[];this.f=0;var c=arguments.length;if(1<c){if(c%2)throw Error("Uneven number of arguments");for(var d=0;d<c;d+=2)this.set(arguments[d],arguments[d+1])}else if(a)if(a instanceof Uc)for(c=Vc(a),d=0;d<c.length;d++)this.set(c[d],a.get(c[d]));else for(d in a)this.set(d,a[d])}
-function Vc(a){if(a.f!=a.a.length){for(var b=0,c=0;b<a.a.length;){var d=a.a[b];Object.prototype.hasOwnProperty.call(a.b,d)&&(a.a[c++]=d);b++}a.a.length=c}if(a.f!=a.a.length){var e={};for(c=b=0;b<a.a.length;)d=a.a[b],Object.prototype.hasOwnProperty.call(e,d)||(a.a[c++]=d,e[d]=1),b++;a.a.length=c}return a.a.concat()}Uc.prototype.get=function(a,b){return Object.prototype.hasOwnProperty.call(this.b,a)?this.b[a]:b};
-Uc.prototype.set=function(a,b){Object.prototype.hasOwnProperty.call(this.b,a)||(this.f++,this.a.push(a));this.b[a]=b};var Wc={};function Z(a,b,c){da(a)&&(a=t?a.g:a.h);a=new Xc(a);!b||b in Wc&&!c||(Wc[b]={key:a,shift:!1},c&&(Wc[c]={key:a,shift:!0}));return a}function Xc(a){this.code=a}Z(8);Z(9);Z(13);var Yc=Z(16),Zc=Z(17),$c=Z(18);Z(19);Z(20);Z(27);Z(32," ");Z(33);Z(34);Z(35);Z(36);Z(37);Z(38);Z(39);Z(40);Z(44);Z(45);Z(46);Z(48,"0",")");Z(49,"1","!");Z(50,"2","@");Z(51,"3","#");Z(52,"4","$");Z(53,"5","%");Z(54,"6","^");Z(55,"7","&");Z(56,"8","*");Z(57,"9","(");Z(65,"a","A");Z(66,"b","B");Z(67,"c","C");Z(68,"d","D");
-Z(69,"e","E");Z(70,"f","F");Z(71,"g","G");Z(72,"h","H");Z(73,"i","I");Z(74,"j","J");Z(75,"k","K");Z(76,"l","L");Z(77,"m","M");Z(78,"n","N");Z(79,"o","O");Z(80,"p","P");Z(81,"q","Q");Z(82,"r","R");Z(83,"s","S");Z(84,"t","T");Z(85,"u","U");Z(86,"v","V");Z(87,"w","W");Z(88,"x","X");Z(89,"y","Y");Z(90,"z","Z");var ad=Z(Ia?{g:91,h:91}:Ha?{g:224,h:91}:{g:0,h:91});Z(Ia?{g:92,h:92}:Ha?{g:224,h:93}:{g:0,h:92});Z(Ia?{g:93,h:93}:Ha?{g:0,h:0}:{g:93,h:null});Z({g:96,h:96},"0");Z({g:97,h:97},"1");
-Z({g:98,h:98},"2");Z({g:99,h:99},"3");Z({g:100,h:100},"4");Z({g:101,h:101},"5");Z({g:102,h:102},"6");Z({g:103,h:103},"7");Z({g:104,h:104},"8");Z({g:105,h:105},"9");Z({g:106,h:106},"*");Z({g:107,h:107},"+");Z({g:109,h:109},"-");Z({g:110,h:110},".");Z({g:111,h:111},"/");Z(144);Z(112);Z(113);Z(114);Z(115);Z(116);Z(117);Z(118);Z(119);Z(120);Z(121);Z(122);Z(123);Z({g:107,h:187},"=","+");Z(108,",");Z({g:109,h:189},"-","_");Z(188,",","<");Z(190,".",">");Z(191,"/","?");Z(192,"`","~");Z(219,"[","{");
-Z(220,"\\","|");Z(221,"]","}");Z({g:59,h:186},";",":");Z(222,"'",'"');var bd=new Uc;bd.set(1,Yc);bd.set(2,Zc);bd.set(4,$c);bd.set(8,ad);(function(a){var b=new Uc;n(Vc(a),function(c){b.set(a.get(c).code,c)});return b})(bd);var cd={"class":"className",readonly:"readOnly"},dd="allowfullscreen allowpaymentrequest allowusermedia async autofocus autoplay checked compact complete controls declare default defaultchecked defaultselected defer disabled ended formnovalidate hidden indeterminate iscontenteditable ismap itemscope loop multiple muted nohref nomodule noresize noshade novalidate nowrap open paused playsinline pubdate readonly required reversed scoped seamless seeking selected truespeed typemustmatch willvalidate".split(" ");ba("_",function(a,b){var c=null,d=b.toLowerCase();if("style"==d)return(c=a.style)&&!aa(c)&&(c=c.cssText),c;if(("selected"==d||"checked"==d)&&Jc(a)){if(!Jc(a))throw new U(15,"Element is not selectable");b="selected";c=a.type&&a.type.toLowerCase();if("checkbox"==c||"radio"==c)b="checked";return Ic(a,b)?"true":null}var e=Gc(a,"A");if(Gc(a,"IMG")&&"src"==d||e&&"href"==d)return(c=Ec(a,d))&&(c=Ic(a,d)),c;if("spellcheck"==d){c=Ec(a,d);if(null!==c){if("false"==c.toLowerCase())return"false";if("true"==c.toLowerCase())return"true"}return Ic(a,
-d)+""}e=cd[b]||b;if(0<=ma(dd,d))return(c=null!==Ec(a,b)||Ic(a,e))?"true":null;try{var f=Ic(a,e)}catch(g){}null==f||da(f)?c=Ec(a,b):c=f;return null!=c?c.toString():null});; return this._.apply(null,arguments);}).apply({navigator:typeof window!='undefined'?window.navigator:null,document:typeof window!='undefined'?window.document:null}, arguments);}
+function(){return (function(){var d=this||self;function f(a,b){function c(){}c.prototype=b.prototype;a.prototype=new c;a.prototype.constructor=a};var h=Array.prototype.indexOf?function(a,b){return Array.prototype.indexOf.call(a,b,void 0)}:function(a,b){if("string"===typeof a)return"string"!==typeof b||1!=b.length?-1:a.indexOf(b,0);for(var c=0;c<a.length;c++)if(c in a&&a[c]===b)return c;return-1},k=Array.prototype.forEach?function(a,b){Array.prototype.forEach.call(a,b,void 0)}:function(a,b){for(var c=a.length,e="string"===typeof a?a.split(""):a,g=0;g<c;g++)g in e&&b.call(void 0,e[g],g,a)};function l(a,b){this.code=a;this.a=m[a]||n;this.message=b||"";a=this.a.replace(/((?:^|\s+)[a-z])/g,function(c){return c.toUpperCase().replace(/^[\s\xa0]+/g,"")});b=a.length-5;if(0>b||a.indexOf("Error",b)!=b)a+="Error";this.name=a;a=Error(this.message);a.name=this.name;this.stack=a.stack||""}f(l,Error);var n="unknown error",m={15:"element not selectable",11:"element not visible"};m[31]=n;m[30]=n;m[24]="invalid cookie domain";m[29]="invalid element coordinates";m[12]="invalid element state";m[32]="invalid selector";
+m[51]="invalid selector";m[52]="invalid selector";m[17]="javascript error";m[405]="unsupported operation";m[34]="move target out of bounds";m[27]="no such alert";m[7]="no such element";m[8]="no such frame";m[23]="no such window";m[28]="script timeout";m[33]="session not created";m[10]="stale element reference";m[21]="timeout";m[25]="unable to set cookie";m[26]="unexpected alert open";m[13]=n;m[9]="unknown command";var p;a:{var q=d.navigator;if(q){var r=q.userAgent;if(r){p=r;break a}}p=""}function t(a){return-1!=p.indexOf(a)};function u(){return t("Firefox")||t("FxiOS")}function v(){return(t("Chrome")||t("CriOS"))&&!t("Edge")};function w(){return t("iPhone")&&!t("iPod")&&!t("iPad")};var y=t("Opera"),z=t("Trident")||t("MSIE"),A=t("Edge"),B=t("Gecko")&&!(-1!=p.toLowerCase().indexOf("webkit")&&!t("Edge"))&&!(t("Trident")||t("MSIE"))&&!t("Edge"),C=-1!=p.toLowerCase().indexOf("webkit")&&!t("Edge");function D(){var a=d.document;return a?a.documentMode:void 0}var E;
+a:{var F="",G=function(){var a=p;if(B)return/rv:([^\);]+)(\)|;)/.exec(a);if(A)return/Edge\/([\d\.]+)/.exec(a);if(z)return/\b(?:MSIE|rv)[: ]([^\);]+)(\)|;)/.exec(a);if(C)return/WebKit\/(\S+)/.exec(a);if(y)return/(?:Version)[ \/]?(\S+)/.exec(a)}();G&&(F=G?G[1]:"");if(z){var H=D();if(null!=H&&H>parseFloat(F)){E=String(H);break a}}E=F}var I;I=d.document&&z?D():void 0;var J=u(),K=w()||t("iPod"),L=t("iPad"),M=t("Android")&&!(v()||u()||t("Opera")||t("Silk")),N=v(),aa=t("Safari")&&!(v()||t("Coast")||t("Opera")||t("Edge")||t("Edg/")||t("OPR")||u()||t("Silk")||t("Android"))&&!(w()||t("iPad")||t("iPod"));function O(a){return(a=a.exec(p))?a[1]:""}(function(){if(J)return O(/Firefox\/([0-9.]+)/);if(z||A||y)return E;if(N)return w()||t("iPad")||t("iPod")?O(/CriOS\/([0-9.]+)/):O(/Chrome\/([0-9.]+)/);if(aa&&!(w()||t("iPad")||t("iPod")))return O(/Version\/([0-9.]+)/);if(K||L){var a=/Version\/(\S+).*Mobile\/(\S+)/.exec(p);if(a)return a[1]+"."+a[2]}else if(M)return(a=O(/Android\s+([0-9.]+)/))?a:O(/Version\/([0-9.]+)/);return""})();var P=z&&!(8<=Number(I)),ba=z&&!(9<=Number(I));var ca={SCRIPT:1,STYLE:1,HEAD:1,IFRAME:1,OBJECT:1},Q={IMG:" ",BR:"\n"};function R(a,b,c){if(!(a.nodeName in ca))if(3==a.nodeType)c?b.push(String(a.nodeValue).replace(/(\r\n|\r|\n)/g,"")):b.push(a.nodeValue);else if(a.nodeName in Q)b.push(Q[a.nodeName]);else for(a=a.firstChild;a;)R(a,b,c),a=a.nextSibling};function S(a,b){b=b.toLowerCase();return"style"==b?da(a.style.cssText):P&&"value"==b&&T(a,"INPUT")?a.value:ba&&!0===a[b]?String(a.getAttribute(b)):(a=a.getAttributeNode(b))&&a.specified?a.value:null}var ea=/[;]+(?=(?:(?:[^"]*"){2})*[^"]*$)(?=(?:(?:[^']*'){2})*[^']*$)(?=(?:[^()]*\([^()]*\))*[^()]*$)/;
+function da(a){var b=[];k(a.split(ea),function(c){var e=c.indexOf(":");0<e&&(c=[c.slice(0,e),c.slice(e+1)],2==c.length&&b.push(c[0].toLowerCase(),":",c[1],";"))});b=b.join("");return b=";"==b.charAt(b.length-1)?b:b+";"}function U(a,b){P&&"value"==b&&T(a,"OPTION")&&null===S(a,"value")?(b=[],R(a,b,!1),a=b.join("")):a=a[b];return a}
+function T(a,b){b&&"string"!==typeof b&&(b=b.toString());return a instanceof HTMLFormElement?!!a&&1==a.nodeType&&(!b||"FORM"==b):!!a&&1==a.nodeType&&(!b||a.tagName.toUpperCase()==b)}function V(a){return T(a,"OPTION")?!0:T(a,"INPUT")?(a=a.type.toLowerCase(),"checkbox"==a||"radio"==a):!1};var fa={"class":"className",readonly:"readOnly"},ha="allowfullscreen allowpaymentrequest allowusermedia async autofocus autoplay checked compact complete controls declare default defaultchecked defaultselected defer disabled ended formnovalidate hidden indeterminate iscontenteditable ismap itemscope loop multiple muted nohref nomodule noresize noshade novalidate nowrap open paused playsinline pubdate readonly required reversed scoped seamless seeking selected truespeed typemustmatch willvalidate".split(" ");function W(a,b){var c=null,e=b.toLowerCase();if("style"==e)return(c=a.style)&&"string"!=typeof c&&(c=c.cssText),c;if(("selected"==e||"checked"==e)&&V(a)){if(!V(a))throw new l(15,"Element is not selectable");b="selected";c=a.type&&a.type.toLowerCase();if("checkbox"==c||"radio"==c)b="checked";return U(a,b)?"true":null}var g=T(a,"A");if(T(a,"IMG")&&"src"==e||g&&"href"==e)return(c=S(a,e))&&(c=U(a,e)),c;if("spellcheck"==e){c=S(a,e);if(null!==c){if("false"==c.toLowerCase())return"false";if("true"==c.toLowerCase())return"true"}return U(a,
+e)+""}g=fa[b]||b;if(0<=h(ha,e))return(c=null!==S(a,b)||U(a,g))?"true":null;try{var x=U(a,g)}catch(ia){}(e=null==x)||(e=typeof x,e="object"==e&&null!=x||"function"==e);e?c=S(a,b):c=x;return null!=c?c.toString():null}var X=["se_exportedFunctionSymbol"],Y=d;X[0]in Y||"undefined"==typeof Y.execScript||Y.execScript("var "+X[0]);for(var Z;X.length&&(Z=X.shift());)X.length||void 0===W?Y[Z]&&Y[Z]!==Object.prototype[Z]?Y=Y[Z]:Y=Y[Z]={}:Y[Z]=W;; return this.se_exportedFunctionSymbol.apply(null,arguments);}).apply(window, arguments);}
diff -pruN 4.4.0-1/lib/selenium/webdriver/atoms/isDisplayed.js 4.38.0-1/lib/selenium/webdriver/atoms/isDisplayed.js
--- 4.4.0-1/lib/selenium/webdriver/atoms/isDisplayed.js	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/atoms/isDisplayed.js	2025-11-02 08:23:03.000000000 +0000
@@ -1,100 +1,28 @@
-function(){return (function(){var k=this||self;function aa(a){return"string"==typeof a}function ba(a,b){a=a.split(".");var c=k;a[0]in c||"undefined"==typeof c.execScript||c.execScript("var "+a[0]);for(var d;a.length&&(d=a.shift());)a.length||void 0===b?c[d]&&c[d]!==Object.prototype[d]?c=c[d]:c=c[d]={}:c[d]=b}
-function ca(a){var b=typeof a;if("object"==b)if(a){if(a instanceof Array)return"array";if(a instanceof Object)return b;var c=Object.prototype.toString.call(a);if("[object Window]"==c)return"object";if("[object Array]"==c||"number"==typeof a.length&&"undefined"!=typeof a.splice&&"undefined"!=typeof a.propertyIsEnumerable&&!a.propertyIsEnumerable("splice"))return"array";if("[object Function]"==c||"undefined"!=typeof a.call&&"undefined"!=typeof a.propertyIsEnumerable&&!a.propertyIsEnumerable("call"))return"function"}else return"null";
-else if("function"==b&&"undefined"==typeof a.call)return"object";return b}function da(a,b,c){return a.call.apply(a.bind,arguments)}function ea(a,b,c){if(!a)throw Error();if(2<arguments.length){var d=Array.prototype.slice.call(arguments,2);return function(){var e=Array.prototype.slice.call(arguments);Array.prototype.unshift.apply(e,d);return a.apply(b,e)}}return function(){return a.apply(b,arguments)}}
-function fa(a,b,c){Function.prototype.bind&&-1!=Function.prototype.bind.toString().indexOf("native code")?fa=da:fa=ea;return fa.apply(null,arguments)}function ha(a,b){var c=Array.prototype.slice.call(arguments,1);return function(){var d=c.slice();d.push.apply(d,arguments);return a.apply(this,d)}}function l(a,b){function c(){}c.prototype=b.prototype;a.prototype=new c;a.prototype.constructor=a};/*
-
- The MIT License
-
- Copyright (c) 2007 Cybozu Labs, Inc.
- Copyright (c) 2012 Google Inc.
-
- Permission is hereby granted, free of charge, to any person obtaining a copy
- of this software and associated documentation files (the "Software"), to
- deal in the Software without restriction, including without limitation the
- rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- sell copies of the Software, and to permit persons to whom the Software is
- furnished to do so, subject to the following conditions:
-
- The above copyright notice and this permission notice shall be included in
- all copies or substantial portions of the Software.
-
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- IN THE SOFTWARE.
-*/
-function ia(a,b,c){this.a=a;this.b=b||1;this.f=c||1};var ja=Array.prototype.indexOf?function(a,b){return Array.prototype.indexOf.call(a,b,void 0)}:function(a,b){if("string"===typeof a)return"string"!==typeof b||1!=b.length?-1:a.indexOf(b,0);for(var c=0;c<a.length;c++)if(c in a&&a[c]===b)return c;return-1},n=Array.prototype.forEach?function(a,b){Array.prototype.forEach.call(a,b,void 0)}:function(a,b){for(var c=a.length,d="string"===typeof a?a.split(""):a,e=0;e<c;e++)e in d&&b.call(void 0,d[e],e,a)},ka=Array.prototype.filter?function(a,b){return Array.prototype.filter.call(a,
-b,void 0)}:function(a,b){for(var c=a.length,d=[],e=0,f="string"===typeof a?a.split(""):a,g=0;g<c;g++)if(g in f){var h=f[g];b.call(void 0,h,g,a)&&(d[e++]=h)}return d},la=Array.prototype.reduce?function(a,b,c){return Array.prototype.reduce.call(a,b,c)}:function(a,b,c){var d=c;n(a,function(e,f){d=b.call(void 0,d,e,f,a)});return d},ma=Array.prototype.some?function(a,b){return Array.prototype.some.call(a,b,void 0)}:function(a,b){for(var c=a.length,d="string"===typeof a?a.split(""):a,e=0;e<c;e++)if(e in
-d&&b.call(void 0,d[e],e,a))return!0;return!1},na=Array.prototype.every?function(a,b){return Array.prototype.every.call(a,b,void 0)}:function(a,b){for(var c=a.length,d="string"===typeof a?a.split(""):a,e=0;e<c;e++)if(e in d&&!b.call(void 0,d[e],e,a))return!1;return!0};function oa(a,b){a:{for(var c=a.length,d="string"===typeof a?a.split(""):a,e=0;e<c;e++)if(e in d&&b.call(void 0,d[e],e,a)){b=e;break a}b=-1}return 0>b?null:"string"===typeof a?a.charAt(b):a[b]}
-function pa(a){return Array.prototype.concat.apply([],arguments)}function qa(a,b,c){return 2>=arguments.length?Array.prototype.slice.call(a,b):Array.prototype.slice.call(a,b,c)};var ra=String.prototype.trim?function(a){return a.trim()}:function(a){return/^[\s\xa0]*([\s\S]*?)[\s\xa0]*$/.exec(a)[1]};function sa(a,b){return a<b?-1:a>b?1:0};var t;a:{var ta=k.navigator;if(ta){var ua=ta.userAgent;if(ua){t=ua;break a}}t=""}function u(a){return-1!=t.indexOf(a)};function va(){return u("Firefox")||u("FxiOS")}function wa(){return(u("Chrome")||u("CriOS"))&&!u("Edge")};function xa(a){return String(a).replace(/\-([a-z])/g,function(b,c){return c.toUpperCase()})};function ya(){return u("iPhone")&&!u("iPod")&&!u("iPad")};function za(a,b){var c=Aa;return Object.prototype.hasOwnProperty.call(c,a)?c[a]:c[a]=b(a)};var Ba=u("Opera"),v=u("Trident")||u("MSIE"),Ca=u("Edge"),Da=u("Gecko")&&!(-1!=t.toLowerCase().indexOf("webkit")&&!u("Edge"))&&!(u("Trident")||u("MSIE"))&&!u("Edge"),Ea=-1!=t.toLowerCase().indexOf("webkit")&&!u("Edge");function Fa(){var a=k.document;return a?a.documentMode:void 0}var Ga;
-a:{var Ha="",Ia=function(){var a=t;if(Da)return/rv:([^\);]+)(\)|;)/.exec(a);if(Ca)return/Edge\/([\d\.]+)/.exec(a);if(v)return/\b(?:MSIE|rv)[: ]([^\);]+)(\)|;)/.exec(a);if(Ea)return/WebKit\/(\S+)/.exec(a);if(Ba)return/(?:Version)[ \/]?(\S+)/.exec(a)}();Ia&&(Ha=Ia?Ia[1]:"");if(v){var Ja=Fa();if(null!=Ja&&Ja>parseFloat(Ha)){Ga=String(Ja);break a}}Ga=Ha}var Aa={};
-function Ka(a){return za(a,function(){for(var b=0,c=ra(String(Ga)).split("."),d=ra(String(a)).split("."),e=Math.max(c.length,d.length),f=0;0==b&&f<e;f++){var g=c[f]||"",h=d[f]||"";do{g=/(\d*)(\D*)(.*)/.exec(g)||["","","",""];h=/(\d*)(\D*)(.*)/.exec(h)||["","","",""];if(0==g[0].length&&0==h[0].length)break;b=sa(0==g[1].length?0:parseInt(g[1],10),0==h[1].length?0:parseInt(h[1],10))||sa(0==g[2].length,0==h[2].length)||sa(g[2],h[2]);g=g[3];h=h[3]}while(0==b)}return 0<=b})}var La;
-La=k.document&&v?Fa():void 0;var x=v&&!(9<=Number(La)),Ma=v&&!(8<=Number(La));function Na(a,b,c,d){this.a=a;this.nodeName=c;this.nodeValue=d;this.nodeType=2;this.parentNode=this.ownerElement=b}function Oa(a,b){var c=Ma&&"href"==b.nodeName?a.getAttribute(b.nodeName,2):b.nodeValue;return new Na(b,a,b.nodeName,c)};function Pa(a){this.b=a;this.a=0}function Qa(a){a=a.match(Ra);for(var b=0;b<a.length;b++)Sa.test(a[b])&&a.splice(b,1);return new Pa(a)}var Ra=/\$?(?:(?![0-9-\.])(?:\*|[\w-\.]+):)?(?![0-9-\.])(?:\*|[\w-\.]+)|\/\/|\.\.|::|\d+(?:\.\d*)?|\.\d+|"[^"]*"|'[^']*'|[!<>]=|\s+|./g,Sa=/^\s/;function y(a,b){return a.b[a.a+(b||0)]}function z(a){return a.b[a.a++]}function Ta(a){return a.b.length<=a.a};function Ua(a,b){this.x=void 0!==a?a:0;this.y=void 0!==b?b:0}Ua.prototype.ceil=function(){this.x=Math.ceil(this.x);this.y=Math.ceil(this.y);return this};Ua.prototype.floor=function(){this.x=Math.floor(this.x);this.y=Math.floor(this.y);return this};Ua.prototype.round=function(){this.x=Math.round(this.x);this.y=Math.round(this.y);return this};function Va(a,b){this.width=a;this.height=b}Va.prototype.aspectRatio=function(){return this.width/this.height};Va.prototype.ceil=function(){this.width=Math.ceil(this.width);this.height=Math.ceil(this.height);return this};Va.prototype.floor=function(){this.width=Math.floor(this.width);this.height=Math.floor(this.height);return this};Va.prototype.round=function(){this.width=Math.round(this.width);this.height=Math.round(this.height);return this};function Wa(a,b){if(!a||!b)return!1;if(a.contains&&1==b.nodeType)return a==b||a.contains(b);if("undefined"!=typeof a.compareDocumentPosition)return a==b||!!(a.compareDocumentPosition(b)&16);for(;b&&a!=b;)b=b.parentNode;return b==a}
-function Xa(a,b){if(a==b)return 0;if(a.compareDocumentPosition)return a.compareDocumentPosition(b)&2?1:-1;if(v&&!(9<=Number(La))){if(9==a.nodeType)return-1;if(9==b.nodeType)return 1}if("sourceIndex"in a||a.parentNode&&"sourceIndex"in a.parentNode){var c=1==a.nodeType,d=1==b.nodeType;if(c&&d)return a.sourceIndex-b.sourceIndex;var e=a.parentNode,f=b.parentNode;return e==f?Ya(a,b):!c&&Wa(e,b)?-1*Za(a,b):!d&&Wa(f,a)?Za(b,a):(c?a.sourceIndex:e.sourceIndex)-(d?b.sourceIndex:f.sourceIndex)}d=A(a);c=d.createRange();
-c.selectNode(a);c.collapse(!0);a=d.createRange();a.selectNode(b);a.collapse(!0);return c.compareBoundaryPoints(k.Range.START_TO_END,a)}function Za(a,b){var c=a.parentNode;if(c==b)return-1;for(;b.parentNode!=c;)b=b.parentNode;return Ya(b,a)}function Ya(a,b){for(;b=b.previousSibling;)if(b==a)return-1;return 1}function A(a){return 9==a.nodeType?a:a.ownerDocument||a.document}function $a(a,b){a&&(a=a.parentNode);for(var c=0;a;){if(b(a))return a;a=a.parentNode;c++}return null}
-function ab(a){this.a=a||k.document||document}ab.prototype.getElementsByTagName=function(a,b){return(b||this.a).getElementsByTagName(String(a))};function B(a){var b=null,c=a.nodeType;1==c&&(b=a.textContent,b=void 0==b||null==b?a.innerText:b,b=void 0==b||null==b?"":b);if("string"!=typeof b)if(x&&"title"==a.nodeName.toLowerCase()&&1==c)b=a.text;else if(9==c||1==c){a=9==c?a.documentElement:a.firstChild;c=0;var d=[];for(b="";a;){do 1!=a.nodeType&&(b+=a.nodeValue),x&&"title"==a.nodeName.toLowerCase()&&(b+=a.text),d[c++]=a;while(a=a.firstChild);for(;c&&!(a=d[--c].nextSibling););}}else b=a.nodeValue;return b}
-function C(a,b,c){if(null===b)return!0;try{if(!a.getAttribute)return!1}catch(d){return!1}Ma&&"class"==b&&(b="className");return null==c?!!a.getAttribute(b):a.getAttribute(b,2)==c}function bb(a,b,c,d,e){return(x?cb:db).call(null,a,b,aa(c)?c:null,aa(d)?d:null,e||new E)}
-function cb(a,b,c,d,e){if(a instanceof F||8==a.b||c&&null===a.b){var f=b.all;if(!f)return e;a=eb(a);if("*"!=a&&(f=b.getElementsByTagName(a),!f))return e;if(c){for(var g=[],h=0;b=f[h++];)C(b,c,d)&&g.push(b);f=g}for(h=0;b=f[h++];)"*"==a&&"!"==b.tagName||e.add(b);return e}gb(a,b,c,d,e);return e}
-function db(a,b,c,d,e){b.getElementsByName&&d&&"name"==c&&!v?(b=b.getElementsByName(d),n(b,function(f){a.a(f)&&e.add(f)})):b.getElementsByClassName&&d&&"class"==c?(b=b.getElementsByClassName(d),n(b,function(f){f.className==d&&a.a(f)&&e.add(f)})):a instanceof G?gb(a,b,c,d,e):b.getElementsByTagName&&(b=b.getElementsByTagName(a.f()),n(b,function(f){C(f,c,d)&&e.add(f)}));return e}
-function hb(a,b,c,d,e){var f;if((a instanceof F||8==a.b||c&&null===a.b)&&(f=b.childNodes)){var g=eb(a);if("*"!=g&&(f=ka(f,function(h){return h.tagName&&h.tagName.toLowerCase()==g}),!f))return e;c&&(f=ka(f,function(h){return C(h,c,d)}));n(f,function(h){"*"==g&&("!"==h.tagName||"*"==g&&1!=h.nodeType)||e.add(h)});return e}return ib(a,b,c,d,e)}function ib(a,b,c,d,e){for(b=b.firstChild;b;b=b.nextSibling)C(b,c,d)&&a.a(b)&&e.add(b);return e}
-function gb(a,b,c,d,e){for(b=b.firstChild;b;b=b.nextSibling)C(b,c,d)&&a.a(b)&&e.add(b),gb(a,b,c,d,e)}function eb(a){if(a instanceof G){if(8==a.b)return"!";if(null===a.b)return"*"}return a.f()};function E(){this.b=this.a=null;this.l=0}function jb(a){this.f=a;this.a=this.b=null}function kb(a,b){if(!a.a)return b;if(!b.a)return a;var c=a.a;b=b.a;for(var d=null,e,f=0;c&&b;){e=c.f;var g=b.f;e==g||e instanceof Na&&g instanceof Na&&e.a==g.a?(e=c,c=c.a,b=b.a):0<Xa(c.f,b.f)?(e=b,b=b.a):(e=c,c=c.a);(e.b=d)?d.a=e:a.a=e;d=e;f++}for(e=c||b;e;)e.b=d,d=d.a=e,f++,e=e.a;a.b=d;a.l=f;return a}function lb(a,b){b=new jb(b);b.a=a.a;a.b?a.a.b=b:a.a=a.b=b;a.a=b;a.l++}
-E.prototype.add=function(a){a=new jb(a);a.b=this.b;this.a?this.b.a=a:this.a=this.b=a;this.b=a;this.l++};function mb(a){return(a=a.a)?a.f:null}function nb(a){return(a=mb(a))?B(a):""}function H(a,b){return new ob(a,!!b)}function ob(a,b){this.f=a;this.b=(this.s=b)?a.b:a.a;this.a=null}function I(a){var b=a.b;if(null==b)return null;var c=a.a=b;a.b=a.s?b.b:b.a;return c.f};function J(a){this.i=a;this.b=this.g=!1;this.f=null}function K(a){return"\n  "+a.toString().split("\n").join("\n  ")}function pb(a,b){a.g=b}function qb(a,b){a.b=b}function N(a,b){a=a.a(b);return a instanceof E?+nb(a):+a}function O(a,b){a=a.a(b);return a instanceof E?nb(a):""+a}function rb(a,b){a=a.a(b);return a instanceof E?!!a.l:!!a};function sb(a,b,c){J.call(this,a.i);this.c=a;this.h=b;this.o=c;this.g=b.g||c.g;this.b=b.b||c.b;this.c==tb&&(c.b||c.g||4==c.i||0==c.i||!b.f?b.b||b.g||4==b.i||0==b.i||!c.f||(this.f={name:c.f.name,u:b}):this.f={name:b.f.name,u:c})}l(sb,J);
-function ub(a,b,c,d,e){b=b.a(d);c=c.a(d);var f;if(b instanceof E&&c instanceof E){b=H(b);for(d=I(b);d;d=I(b))for(e=H(c),f=I(e);f;f=I(e))if(a(B(d),B(f)))return!0;return!1}if(b instanceof E||c instanceof E){b instanceof E?(e=b,d=c):(e=c,d=b);f=H(e);for(var g=typeof d,h=I(f);h;h=I(f)){switch(g){case "number":h=+B(h);break;case "boolean":h=!!B(h);break;case "string":h=B(h);break;default:throw Error("Illegal primitive type for comparison.");}if(e==b&&a(h,d)||e==c&&a(d,h))return!0}return!1}return e?"boolean"==
-typeof b||"boolean"==typeof c?a(!!b,!!c):"number"==typeof b||"number"==typeof c?a(+b,+c):a(b,c):a(+b,+c)}sb.prototype.a=function(a){return this.c.m(this.h,this.o,a)};sb.prototype.toString=function(){var a="Binary Expression: "+this.c;a+=K(this.h);return a+=K(this.o)};function vb(a,b,c,d){this.I=a;this.D=b;this.i=c;this.m=d}vb.prototype.toString=function(){return this.I};var wb={};
-function P(a,b,c,d){if(wb.hasOwnProperty(a))throw Error("Binary operator already created: "+a);a=new vb(a,b,c,d);return wb[a.toString()]=a}P("div",6,1,function(a,b,c){return N(a,c)/N(b,c)});P("mod",6,1,function(a,b,c){return N(a,c)%N(b,c)});P("*",6,1,function(a,b,c){return N(a,c)*N(b,c)});P("+",5,1,function(a,b,c){return N(a,c)+N(b,c)});P("-",5,1,function(a,b,c){return N(a,c)-N(b,c)});P("<",4,2,function(a,b,c){return ub(function(d,e){return d<e},a,b,c)});
-P(">",4,2,function(a,b,c){return ub(function(d,e){return d>e},a,b,c)});P("<=",4,2,function(a,b,c){return ub(function(d,e){return d<=e},a,b,c)});P(">=",4,2,function(a,b,c){return ub(function(d,e){return d>=e},a,b,c)});var tb=P("=",3,2,function(a,b,c){return ub(function(d,e){return d==e},a,b,c,!0)});P("!=",3,2,function(a,b,c){return ub(function(d,e){return d!=e},a,b,c,!0)});P("and",2,2,function(a,b,c){return rb(a,c)&&rb(b,c)});P("or",1,2,function(a,b,c){return rb(a,c)||rb(b,c)});function xb(a,b){if(b.a.length&&4!=a.i)throw Error("Primary expression must evaluate to nodeset if filter has predicate(s).");J.call(this,a.i);this.c=a;this.h=b;this.g=a.g;this.b=a.b}l(xb,J);xb.prototype.a=function(a){a=this.c.a(a);return yb(this.h,a)};xb.prototype.toString=function(){var a="Filter:"+K(this.c);return a+=K(this.h)};function zb(a,b){if(b.length<a.C)throw Error("Function "+a.j+" expects at least"+a.C+" arguments, "+b.length+" given");if(null!==a.B&&b.length>a.B)throw Error("Function "+a.j+" expects at most "+a.B+" arguments, "+b.length+" given");a.H&&n(b,function(c,d){if(4!=c.i)throw Error("Argument "+d+" to function "+a.j+" is not of type Nodeset: "+c);});J.call(this,a.i);this.v=a;this.c=b;pb(this,a.g||ma(b,function(c){return c.g}));qb(this,a.G&&!b.length||a.F&&!!b.length||ma(b,function(c){return c.b}))}
-l(zb,J);zb.prototype.a=function(a){return this.v.m.apply(null,pa(a,this.c))};zb.prototype.toString=function(){var a="Function: "+this.v;if(this.c.length){var b=la(this.c,function(c,d){return c+K(d)},"Arguments:");a+=K(b)}return a};function Ab(a,b,c,d,e,f,g,h){this.j=a;this.i=b;this.g=c;this.G=d;this.F=!1;this.m=e;this.C=f;this.B=void 0!==g?g:f;this.H=!!h}Ab.prototype.toString=function(){return this.j};var Bb={};
-function Q(a,b,c,d,e,f,g,h){if(Bb.hasOwnProperty(a))throw Error("Function already created: "+a+".");Bb[a]=new Ab(a,b,c,d,e,f,g,h)}Q("boolean",2,!1,!1,function(a,b){return rb(b,a)},1);Q("ceiling",1,!1,!1,function(a,b){return Math.ceil(N(b,a))},1);Q("concat",3,!1,!1,function(a,b){return la(qa(arguments,1),function(c,d){return c+O(d,a)},"")},2,null);Q("contains",2,!1,!1,function(a,b,c){b=O(b,a);a=O(c,a);return-1!=b.indexOf(a)},2);Q("count",1,!1,!1,function(a,b){return b.a(a).l},1,1,!0);
-Q("false",2,!1,!1,function(){return!1},0);Q("floor",1,!1,!1,function(a,b){return Math.floor(N(b,a))},1);Q("id",4,!1,!1,function(a,b){function c(h){if(x){var m=e.all[h];if(m){if(m.nodeType&&h==m.id)return m;if(m.length)return oa(m,function(w){return h==w.id})}return null}return e.getElementById(h)}var d=a.a,e=9==d.nodeType?d:d.ownerDocument;a=O(b,a).split(/\s+/);var f=[];n(a,function(h){h=c(h);!h||0<=ja(f,h)||f.push(h)});f.sort(Xa);var g=new E;n(f,function(h){g.add(h)});return g},1);
-Q("lang",2,!1,!1,function(){return!1},1);Q("last",1,!0,!1,function(a){if(1!=arguments.length)throw Error("Function last expects ()");return a.f},0);Q("local-name",3,!1,!0,function(a,b){return(a=b?mb(b.a(a)):a.a)?a.localName||a.nodeName.toLowerCase():""},0,1,!0);Q("name",3,!1,!0,function(a,b){return(a=b?mb(b.a(a)):a.a)?a.nodeName.toLowerCase():""},0,1,!0);Q("namespace-uri",3,!0,!1,function(){return""},0,1,!0);
-Q("normalize-space",3,!1,!0,function(a,b){return(b?O(b,a):B(a.a)).replace(/[\s\xa0]+/g," ").replace(/^\s+|\s+$/g,"")},0,1);Q("not",2,!1,!1,function(a,b){return!rb(b,a)},1);Q("number",1,!1,!0,function(a,b){return b?N(b,a):+B(a.a)},0,1);Q("position",1,!0,!1,function(a){return a.b},0);Q("round",1,!1,!1,function(a,b){return Math.round(N(b,a))},1);Q("starts-with",2,!1,!1,function(a,b,c){b=O(b,a);a=O(c,a);return 0==b.lastIndexOf(a,0)},2);Q("string",3,!1,!0,function(a,b){return b?O(b,a):B(a.a)},0,1);
-Q("string-length",1,!1,!0,function(a,b){return(b?O(b,a):B(a.a)).length},0,1);Q("substring",3,!1,!1,function(a,b,c,d){c=N(c,a);if(isNaN(c)||Infinity==c||-Infinity==c)return"";d=d?N(d,a):Infinity;if(isNaN(d)||-Infinity===d)return"";c=Math.round(c)-1;var e=Math.max(c,0);a=O(b,a);return Infinity==d?a.substring(e):a.substring(e,c+Math.round(d))},2,3);Q("substring-after",3,!1,!1,function(a,b,c){b=O(b,a);a=O(c,a);c=b.indexOf(a);return-1==c?"":b.substring(c+a.length)},2);
-Q("substring-before",3,!1,!1,function(a,b,c){b=O(b,a);a=O(c,a);a=b.indexOf(a);return-1==a?"":b.substring(0,a)},2);Q("sum",1,!1,!1,function(a,b){a=H(b.a(a));b=0;for(var c=I(a);c;c=I(a))b+=+B(c);return b},1,1,!0);Q("translate",3,!1,!1,function(a,b,c,d){b=O(b,a);c=O(c,a);var e=O(d,a);a={};for(d=0;d<c.length;d++){var f=c.charAt(d);f in a||(a[f]=e.charAt(d))}c="";for(d=0;d<b.length;d++)f=b.charAt(d),c+=f in a?a[f]:f;return c},3);Q("true",2,!1,!1,function(){return!0},0);function G(a,b){this.h=a;this.c=void 0!==b?b:null;this.b=null;switch(a){case "comment":this.b=8;break;case "text":this.b=3;break;case "processing-instruction":this.b=7;break;case "node":break;default:throw Error("Unexpected argument");}}function Cb(a){return"comment"==a||"text"==a||"processing-instruction"==a||"node"==a}G.prototype.a=function(a){return null===this.b||this.b==a.nodeType};G.prototype.f=function(){return this.h};
-G.prototype.toString=function(){var a="Kind Test: "+this.h;null===this.c||(a+=K(this.c));return a};function Db(a){J.call(this,3);this.c=a.substring(1,a.length-1)}l(Db,J);Db.prototype.a=function(){return this.c};Db.prototype.toString=function(){return"Literal: "+this.c};function F(a,b){this.j=a.toLowerCase();a="*"==this.j?"*":"http://www.w3.org/1999/xhtml";this.c=b?b.toLowerCase():a}F.prototype.a=function(a){var b=a.nodeType;if(1!=b&&2!=b)return!1;b=void 0!==a.localName?a.localName:a.nodeName;return"*"!=this.j&&this.j!=b.toLowerCase()?!1:"*"==this.c?!0:this.c==(a.namespaceURI?a.namespaceURI.toLowerCase():"http://www.w3.org/1999/xhtml")};F.prototype.f=function(){return this.j};
-F.prototype.toString=function(){return"Name Test: "+("http://www.w3.org/1999/xhtml"==this.c?"":this.c+":")+this.j};function Eb(a){J.call(this,1);this.c=a}l(Eb,J);Eb.prototype.a=function(){return this.c};Eb.prototype.toString=function(){return"Number: "+this.c};function Fb(a,b){J.call(this,a.i);this.h=a;this.c=b;this.g=a.g;this.b=a.b;1==this.c.length&&(a=this.c[0],a.A||a.c!=Gb||(a=a.o,"*"!=a.f()&&(this.f={name:a.f(),u:null})))}l(Fb,J);function Hb(){J.call(this,4)}l(Hb,J);Hb.prototype.a=function(a){var b=new E;a=a.a;9==a.nodeType?b.add(a):b.add(a.ownerDocument);return b};Hb.prototype.toString=function(){return"Root Helper Expression"};function Ib(){J.call(this,4)}l(Ib,J);Ib.prototype.a=function(a){var b=new E;b.add(a.a);return b};Ib.prototype.toString=function(){return"Context Helper Expression"};
-function Jb(a){return"/"==a||"//"==a}Fb.prototype.a=function(a){var b=this.h.a(a);if(!(b instanceof E))throw Error("Filter expression must evaluate to nodeset.");a=this.c;for(var c=0,d=a.length;c<d&&b.l;c++){var e=a[c],f=H(b,e.c.s);if(e.g||e.c!=Kb)if(e.g||e.c!=Lb){var g=I(f);for(b=e.a(new ia(g));null!=(g=I(f));)g=e.a(new ia(g)),b=kb(b,g)}else g=I(f),b=e.a(new ia(g));else{for(g=I(f);(b=I(f))&&(!g.contains||g.contains(b))&&b.compareDocumentPosition(g)&8;g=b);b=e.a(new ia(g))}}return b};
-Fb.prototype.toString=function(){var a="Path Expression:"+K(this.h);if(this.c.length){var b=la(this.c,function(c,d){return c+K(d)},"Steps:");a+=K(b)}return a};function Mb(a,b){this.a=a;this.s=!!b}
-function yb(a,b,c){for(c=c||0;c<a.a.length;c++)for(var d=a.a[c],e=H(b),f=b.l,g,h=0;g=I(e);h++){var m=a.s?f-h:h+1;g=d.a(new ia(g,m,f));if("number"==typeof g)m=m==g;else if("string"==typeof g||"boolean"==typeof g)m=!!g;else if(g instanceof E)m=0<g.l;else throw Error("Predicate.evaluate returned an unexpected type.");if(!m){m=e;g=m.f;var w=m.a;if(!w)throw Error("Next must be called at least once before remove.");var r=w.b;w=w.a;r?r.a=w:g.a=w;w?w.b=r:g.b=r;g.l--;m.a=null}}return b}
-Mb.prototype.toString=function(){return la(this.a,function(a,b){return a+K(b)},"Predicates:")};function R(a,b,c,d){J.call(this,4);this.c=a;this.o=b;this.h=c||new Mb([]);this.A=!!d;b=this.h;b=0<b.a.length?b.a[0].f:null;a.J&&b&&(a=b.name,a=x?a.toLowerCase():a,this.f={name:a,u:b.u});a:{a=this.h;for(b=0;b<a.a.length;b++)if(c=a.a[b],c.g||1==c.i||0==c.i){a=!0;break a}a=!1}this.g=a}l(R,J);
-R.prototype.a=function(a){var b=a.a,c=this.f,d=null,e=null,f=0;c&&(d=c.name,e=c.u?O(c.u,a):null,f=1);if(this.A)if(this.g||this.c!=Nb)if(b=H((new R(Ob,new G("node"))).a(a)),c=I(b))for(a=this.m(c,d,e,f);null!=(c=I(b));)a=kb(a,this.m(c,d,e,f));else a=new E;else a=bb(this.o,b,d,e),a=yb(this.h,a,f);else a=this.m(a.a,d,e,f);return a};R.prototype.m=function(a,b,c,d){a=this.c.v(this.o,a,b,c);return a=yb(this.h,a,d)};
-R.prototype.toString=function(){var a="Step:"+K("Operator: "+(this.A?"//":"/"));this.c.j&&(a+=K("Axis: "+this.c));a+=K(this.o);if(this.h.a.length){var b=la(this.h.a,function(c,d){return c+K(d)},"Predicates:");a+=K(b)}return a};function Pb(a,b,c,d){this.j=a;this.v=b;this.s=c;this.J=d}Pb.prototype.toString=function(){return this.j};var Qb={};function S(a,b,c,d){if(Qb.hasOwnProperty(a))throw Error("Axis already created: "+a);b=new Pb(a,b,c,!!d);return Qb[a]=b}
-S("ancestor",function(a,b){for(var c=new E;b=b.parentNode;)a.a(b)&&lb(c,b);return c},!0);S("ancestor-or-self",function(a,b){var c=new E;do a.a(b)&&lb(c,b);while(b=b.parentNode);return c},!0);
-var Gb=S("attribute",function(a,b){var c=new E,d=a.f();if("style"==d&&x&&b.style)return c.add(new Na(b.style,b,"style",b.style.cssText)),c;var e=b.attributes;if(e)if(a instanceof G&&null===a.b||"*"==d)for(a=0;d=e[a];a++)x?d.nodeValue&&c.add(Oa(b,d)):c.add(d);else(d=e.getNamedItem(d))&&(x?d.nodeValue&&c.add(Oa(b,d)):c.add(d));return c},!1),Nb=S("child",function(a,b,c,d,e){return(x?hb:ib).call(null,a,b,aa(c)?c:null,aa(d)?d:null,e||new E)},!1,!0);S("descendant",bb,!1,!0);
-var Ob=S("descendant-or-self",function(a,b,c,d){var e=new E;C(b,c,d)&&a.a(b)&&e.add(b);return bb(a,b,c,d,e)},!1,!0),Kb=S("following",function(a,b,c,d){var e=new E;do for(var f=b;f=f.nextSibling;)C(f,c,d)&&a.a(f)&&e.add(f),e=bb(a,f,c,d,e);while(b=b.parentNode);return e},!1,!0);S("following-sibling",function(a,b){for(var c=new E;b=b.nextSibling;)a.a(b)&&c.add(b);return c},!1);S("namespace",function(){return new E},!1);
-var Rb=S("parent",function(a,b){var c=new E;if(9==b.nodeType)return c;if(2==b.nodeType)return c.add(b.ownerElement),c;b=b.parentNode;a.a(b)&&c.add(b);return c},!1),Lb=S("preceding",function(a,b,c,d){var e=new E,f=[];do f.unshift(b);while(b=b.parentNode);for(var g=1,h=f.length;g<h;g++){var m=[];for(b=f[g];b=b.previousSibling;)m.unshift(b);for(var w=0,r=m.length;w<r;w++)b=m[w],C(b,c,d)&&a.a(b)&&e.add(b),e=bb(a,b,c,d,e)}return e},!0,!0);
-S("preceding-sibling",function(a,b){for(var c=new E;b=b.previousSibling;)a.a(b)&&lb(c,b);return c},!0);var Sb=S("self",function(a,b){var c=new E;a.a(b)&&c.add(b);return c},!1);function Tb(a){J.call(this,1);this.c=a;this.g=a.g;this.b=a.b}l(Tb,J);Tb.prototype.a=function(a){return-N(this.c,a)};Tb.prototype.toString=function(){return"Unary Expression: -"+K(this.c)};function Ub(a){J.call(this,4);this.c=a;pb(this,ma(this.c,function(b){return b.g}));qb(this,ma(this.c,function(b){return b.b}))}l(Ub,J);Ub.prototype.a=function(a){var b=new E;n(this.c,function(c){c=c.a(a);if(!(c instanceof E))throw Error("Path expression must evaluate to NodeSet.");b=kb(b,c)});return b};Ub.prototype.toString=function(){return la(this.c,function(a,b){return a+K(b)},"Union Expression:")};function Vb(a,b){this.a=a;this.b=b}function Yb(a){for(var b,c=[];;){T(a,"Missing right hand side of binary expression.");b=Zb(a);var d=z(a.a);if(!d)break;var e=(d=wb[d]||null)&&d.D;if(!e){a.a.a--;break}for(;c.length&&e<=c[c.length-1].D;)b=new sb(c.pop(),c.pop(),b);c.push(b,d)}for(;c.length;)b=new sb(c.pop(),c.pop(),b);return b}function T(a,b){if(Ta(a.a))throw Error(b);}function $b(a,b){a=z(a.a);if(a!=b)throw Error("Bad token, expected: "+b+" got: "+a);}
-function ac(a){a=z(a.a);if(")"!=a)throw Error("Bad token: "+a);}function bc(a){a=z(a.a);if(2>a.length)throw Error("Unclosed literal string");return new Db(a)}
-function cc(a){var b=[];if(Jb(y(a.a))){var c=z(a.a);var d=y(a.a);if("/"==c&&(Ta(a.a)||"."!=d&&".."!=d&&"@"!=d&&"*"!=d&&!/(?![0-9])[\w]/.test(d)))return new Hb;d=new Hb;T(a,"Missing next location step.");c=dc(a,c);b.push(c)}else{a:{c=y(a.a);d=c.charAt(0);switch(d){case "$":throw Error("Variable reference not allowed in HTML XPath");case "(":z(a.a);c=Yb(a);T(a,'unclosed "("');$b(a,")");break;case '"':case "'":c=bc(a);break;default:if(isNaN(+c))if(!Cb(c)&&/(?![0-9])[\w]/.test(d)&&"("==y(a.a,1)){c=z(a.a);
-c=Bb[c]||null;z(a.a);for(d=[];")"!=y(a.a);){T(a,"Missing function argument list.");d.push(Yb(a));if(","!=y(a.a))break;z(a.a)}T(a,"Unclosed function argument list.");ac(a);c=new zb(c,d)}else{c=null;break a}else c=new Eb(+z(a.a))}"["==y(a.a)&&(d=new Mb(ec(a)),c=new xb(c,d))}if(c)if(Jb(y(a.a)))d=c;else return c;else c=dc(a,"/"),d=new Ib,b.push(c)}for(;Jb(y(a.a));)c=z(a.a),T(a,"Missing next location step."),c=dc(a,c),b.push(c);return new Fb(d,b)}
-function dc(a,b){if("/"!=b&&"//"!=b)throw Error('Step op should be "/" or "//"');if("."==y(a.a)){var c=new R(Sb,new G("node"));z(a.a);return c}if(".."==y(a.a))return c=new R(Rb,new G("node")),z(a.a),c;if("@"==y(a.a)){var d=Gb;z(a.a);T(a,"Missing attribute name")}else if("::"==y(a.a,1)){if(!/(?![0-9])[\w]/.test(y(a.a).charAt(0)))throw Error("Bad token: "+z(a.a));var e=z(a.a);d=Qb[e]||null;if(!d)throw Error("No axis with name: "+e);z(a.a);T(a,"Missing node name")}else d=Nb;e=y(a.a);if(/(?![0-9])[\w\*]/.test(e.charAt(0)))if("("==
-y(a.a,1)){if(!Cb(e))throw Error("Invalid node type: "+e);e=z(a.a);if(!Cb(e))throw Error("Invalid type name: "+e);$b(a,"(");T(a,"Bad nodetype");var f=y(a.a).charAt(0),g=null;if('"'==f||"'"==f)g=bc(a);T(a,"Bad nodetype");ac(a);e=new G(e,g)}else if(e=z(a.a),f=e.indexOf(":"),-1==f)e=new F(e);else{g=e.substring(0,f);if("*"==g)var h="*";else if(h=a.b(g),!h)throw Error("Namespace prefix not declared: "+g);e=e.substr(f+1);e=new F(e,h)}else throw Error("Bad token: "+z(a.a));a=new Mb(ec(a),d.s);return c||new R(d,
-e,a,"//"==b)}function ec(a){for(var b=[];"["==y(a.a);){z(a.a);T(a,"Missing predicate expression.");var c=Yb(a);b.push(c);T(a,"Unclosed predicate expression.");$b(a,"]")}return b}function Zb(a){if("-"==y(a.a))return z(a.a),new Tb(Zb(a));var b=cc(a);if("|"!=y(a.a))a=b;else{for(b=[b];"|"==z(a.a);)T(a,"Missing next union location path."),b.push(cc(a));a.a.a--;a=new Ub(b)}return a};function fc(a){switch(a.nodeType){case 1:return ha(gc,a);case 9:return fc(a.documentElement);case 11:case 10:case 6:case 12:return hc;default:return a.parentNode?fc(a.parentNode):hc}}function hc(){return null}function gc(a,b){if(a.prefix==b)return a.namespaceURI||"http://www.w3.org/1999/xhtml";var c=a.getAttributeNode("xmlns:"+b);return c&&c.specified?c.value||null:a.parentNode&&9!=a.parentNode.nodeType?gc(a.parentNode,b):null};function ic(a,b){if(!a.length)throw Error("Empty XPath expression.");a=Qa(a);if(Ta(a))throw Error("Invalid XPath expression.");b?"function"==ca(b)||(b=fa(b.lookupNamespaceURI,b)):b=function(){return null};var c=Yb(new Vb(a,b));if(!Ta(a))throw Error("Bad token: "+z(a));this.evaluate=function(d,e){d=c.a(new ia(d));return new U(d,e)}}
-function U(a,b){if(0==b)if(a instanceof E)b=4;else if("string"==typeof a)b=2;else if("number"==typeof a)b=1;else if("boolean"==typeof a)b=3;else throw Error("Unexpected evaluation result.");if(2!=b&&1!=b&&3!=b&&!(a instanceof E))throw Error("value could not be converted to the specified type");this.resultType=b;switch(b){case 2:this.stringValue=a instanceof E?nb(a):""+a;break;case 1:this.numberValue=a instanceof E?+nb(a):+a;break;case 3:this.booleanValue=a instanceof E?0<a.l:!!a;break;case 4:case 5:case 6:case 7:var c=
-H(a);var d=[];for(var e=I(c);e;e=I(c))d.push(e instanceof Na?e.a:e);this.snapshotLength=a.l;this.invalidIteratorState=!1;break;case 8:case 9:a=mb(a);this.singleNodeValue=a instanceof Na?a.a:a;break;default:throw Error("Unknown XPathResult type.");}var f=0;this.iterateNext=function(){if(4!=b&&5!=b)throw Error("iterateNext called with wrong result type");return f>=d.length?null:d[f++]};this.snapshotItem=function(g){if(6!=b&&7!=b)throw Error("snapshotItem called with wrong result type");return g>=d.length||
-0>g?null:d[g]}}U.ANY_TYPE=0;U.NUMBER_TYPE=1;U.STRING_TYPE=2;U.BOOLEAN_TYPE=3;U.UNORDERED_NODE_ITERATOR_TYPE=4;U.ORDERED_NODE_ITERATOR_TYPE=5;U.UNORDERED_NODE_SNAPSHOT_TYPE=6;U.ORDERED_NODE_SNAPSHOT_TYPE=7;U.ANY_UNORDERED_NODE_TYPE=8;U.FIRST_ORDERED_NODE_TYPE=9;function jc(a){this.lookupNamespaceURI=fc(a)}
-function kc(a,b){a=a||k;var c=a.Document&&a.Document.prototype||a.document;if(!c.evaluate||b)a.XPathResult=U,c.evaluate=function(d,e,f,g){return(new ic(d,f)).evaluate(e,g)},c.createExpression=function(d,e){return new ic(d,e)},c.createNSResolver=function(d){return new jc(d)}}ba("wgxpath.install",kc);ba("wgxpath.install",kc);var lc={aliceblue:"#f0f8ff",antiquewhite:"#faebd7",aqua:"#00ffff",aquamarine:"#7fffd4",azure:"#f0ffff",beige:"#f5f5dc",bisque:"#ffe4c4",black:"#000000",blanchedalmond:"#ffebcd",blue:"#0000ff",blueviolet:"#8a2be2",brown:"#a52a2a",burlywood:"#deb887",cadetblue:"#5f9ea0",chartreuse:"#7fff00",chocolate:"#d2691e",coral:"#ff7f50",cornflowerblue:"#6495ed",cornsilk:"#fff8dc",crimson:"#dc143c",cyan:"#00ffff",darkblue:"#00008b",darkcyan:"#008b8b",darkgoldenrod:"#b8860b",darkgray:"#a9a9a9",darkgreen:"#006400",
+function(){return (function(){var g=this||self;
+function aa(a){var b=typeof a;if("object"==b)if(a){if(a instanceof Array)return"array";if(a instanceof Object)return b;var c=Object.prototype.toString.call(a);if("[object Window]"==c)return"object";if("[object Array]"==c||"number"==typeof a.length&&"undefined"!=typeof a.splice&&"undefined"!=typeof a.propertyIsEnumerable&&!a.propertyIsEnumerable("splice"))return"array";if("[object Function]"==c||"undefined"!=typeof a.call&&"undefined"!=typeof a.propertyIsEnumerable&&!a.propertyIsEnumerable("call"))return"function"}else return"null";else if("function"==
+b&&"undefined"==typeof a.call)return"object";return b}function ca(a,b){function c(){}c.prototype=b.prototype;a.prototype=new c;a.prototype.constructor=a};var da=Array.prototype.indexOf?function(a,b){return Array.prototype.indexOf.call(a,b,void 0)}:function(a,b){if("string"===typeof a)return"string"!==typeof b||1!=b.length?-1:a.indexOf(b,0);for(var c=0;c<a.length;c++)if(c in a&&a[c]===b)return c;return-1},ea=Array.prototype.some?function(a,b){return Array.prototype.some.call(a,b,void 0)}:function(a,b){for(var c=a.length,e="string"===typeof a?a.split(""):a,d=0;d<c;d++)if(d in e&&b.call(void 0,e[d],d,a))return!0;return!1},fa=Array.prototype.every?function(a,
+b){return Array.prototype.every.call(a,b,void 0)}:function(a,b){for(var c=a.length,e="string"===typeof a?a.split(""):a,d=0;d<c;d++)if(d in e&&!b.call(void 0,e[d],d,a))return!1;return!0};var ha={aliceblue:"#f0f8ff",antiquewhite:"#faebd7",aqua:"#00ffff",aquamarine:"#7fffd4",azure:"#f0ffff",beige:"#f5f5dc",bisque:"#ffe4c4",black:"#000000",blanchedalmond:"#ffebcd",blue:"#0000ff",blueviolet:"#8a2be2",brown:"#a52a2a",burlywood:"#deb887",cadetblue:"#5f9ea0",chartreuse:"#7fff00",chocolate:"#d2691e",coral:"#ff7f50",cornflowerblue:"#6495ed",cornsilk:"#fff8dc",crimson:"#dc143c",cyan:"#00ffff",darkblue:"#00008b",darkcyan:"#008b8b",darkgoldenrod:"#b8860b",darkgray:"#a9a9a9",darkgreen:"#006400",
 darkgrey:"#a9a9a9",darkkhaki:"#bdb76b",darkmagenta:"#8b008b",darkolivegreen:"#556b2f",darkorange:"#ff8c00",darkorchid:"#9932cc",darkred:"#8b0000",darksalmon:"#e9967a",darkseagreen:"#8fbc8f",darkslateblue:"#483d8b",darkslategray:"#2f4f4f",darkslategrey:"#2f4f4f",darkturquoise:"#00ced1",darkviolet:"#9400d3",deeppink:"#ff1493",deepskyblue:"#00bfff",dimgray:"#696969",dimgrey:"#696969",dodgerblue:"#1e90ff",firebrick:"#b22222",floralwhite:"#fffaf0",forestgreen:"#228b22",fuchsia:"#ff00ff",gainsboro:"#dcdcdc",
 ghostwhite:"#f8f8ff",gold:"#ffd700",goldenrod:"#daa520",gray:"#808080",green:"#008000",greenyellow:"#adff2f",grey:"#808080",honeydew:"#f0fff0",hotpink:"#ff69b4",indianred:"#cd5c5c",indigo:"#4b0082",ivory:"#fffff0",khaki:"#f0e68c",lavender:"#e6e6fa",lavenderblush:"#fff0f5",lawngreen:"#7cfc00",lemonchiffon:"#fffacd",lightblue:"#add8e6",lightcoral:"#f08080",lightcyan:"#e0ffff",lightgoldenrodyellow:"#fafad2",lightgray:"#d3d3d3",lightgreen:"#90ee90",lightgrey:"#d3d3d3",lightpink:"#ffb6c1",lightsalmon:"#ffa07a",
 lightseagreen:"#20b2aa",lightskyblue:"#87cefa",lightslategray:"#778899",lightslategrey:"#778899",lightsteelblue:"#b0c4de",lightyellow:"#ffffe0",lime:"#00ff00",limegreen:"#32cd32",linen:"#faf0e6",magenta:"#ff00ff",maroon:"#800000",mediumaquamarine:"#66cdaa",mediumblue:"#0000cd",mediumorchid:"#ba55d3",mediumpurple:"#9370db",mediumseagreen:"#3cb371",mediumslateblue:"#7b68ee",mediumspringgreen:"#00fa9a",mediumturquoise:"#48d1cc",mediumvioletred:"#c71585",midnightblue:"#191970",mintcream:"#f5fffa",mistyrose:"#ffe4e1",
 moccasin:"#ffe4b5",navajowhite:"#ffdead",navy:"#000080",oldlace:"#fdf5e6",olive:"#808000",olivedrab:"#6b8e23",orange:"#ffa500",orangered:"#ff4500",orchid:"#da70d6",palegoldenrod:"#eee8aa",palegreen:"#98fb98",paleturquoise:"#afeeee",palevioletred:"#db7093",papayawhip:"#ffefd5",peachpuff:"#ffdab9",peru:"#cd853f",pink:"#ffc0cb",plum:"#dda0dd",powderblue:"#b0e0e6",purple:"#800080",red:"#ff0000",rosybrown:"#bc8f8f",royalblue:"#4169e1",saddlebrown:"#8b4513",salmon:"#fa8072",sandybrown:"#f4a460",seagreen:"#2e8b57",
-seashell:"#fff5ee",sienna:"#a0522d",silver:"#c0c0c0",skyblue:"#87ceeb",slateblue:"#6a5acd",slategray:"#708090",slategrey:"#708090",snow:"#fffafa",springgreen:"#00ff7f",steelblue:"#4682b4",tan:"#d2b48c",teal:"#008080",thistle:"#d8bfd8",tomato:"#ff6347",turquoise:"#40e0d0",violet:"#ee82ee",wheat:"#f5deb3",white:"#ffffff",whitesmoke:"#f5f5f5",yellow:"#ffff00",yellowgreen:"#9acd32"};var mc="backgroundColor borderTopColor borderRightColor borderBottomColor borderLeftColor color outlineColor".split(" "),nc=/#([0-9a-fA-F])([0-9a-fA-F])([0-9a-fA-F])/,oc=/^#(?:[0-9a-f]{3}){1,2}$/i,pc=/^(?:rgba)?\((\d{1,3}),\s?(\d{1,3}),\s?(\d{1,3}),\s?(0|1|0\.\d*)\)$/i,qc=/^(?:rgb)?\((0|[1-9]\d{0,2}),\s?(0|[1-9]\d{0,2}),\s?(0|[1-9]\d{0,2})\)$/i;function rc(a,b){this.code=a;this.a=V[a]||sc;this.message=b||"";a=this.a.replace(/((?:^|\s+)[a-z])/g,function(c){return c.toUpperCase().replace(/^[\s\xa0]+/g,"")});b=a.length-5;if(0>b||a.indexOf("Error",b)!=b)a+="Error";this.name=a;a=Error(this.message);a.name=this.name;this.stack=a.stack||""}l(rc,Error);var sc="unknown error",V={15:"element not selectable",11:"element not visible"};V[31]=sc;V[30]=sc;V[24]="invalid cookie domain";V[29]="invalid element coordinates";V[12]="invalid element state";
-V[32]="invalid selector";V[51]="invalid selector";V[52]="invalid selector";V[17]="javascript error";V[405]="unsupported operation";V[34]="move target out of bounds";V[27]="no such alert";V[7]="no such element";V[8]="no such frame";V[23]="no such window";V[28]="script timeout";V[33]="session not created";V[10]="stale element reference";V[21]="timeout";V[25]="unable to set cookie";V[26]="unexpected alert open";V[13]=sc;V[9]="unknown command";var tc=va(),uc=ya()||u("iPod"),vc=u("iPad"),wc=u("Android")&&!(wa()||va()||u("Opera")||u("Silk")),xc=wa(),yc=u("Safari")&&!(wa()||u("Coast")||u("Opera")||u("Edge")||u("Edg/")||u("OPR")||va()||u("Silk")||u("Android"))&&!(ya()||u("iPad")||u("iPod"));function zc(a){return(a=a.exec(t))?a[1]:""}(function(){if(tc)return zc(/Firefox\/([0-9.]+)/);if(v||Ca||Ba)return Ga;if(xc)return ya()||u("iPad")||u("iPod")?zc(/CriOS\/([0-9.]+)/):zc(/Chrome\/([0-9.]+)/);if(yc&&!(ya()||u("iPad")||u("iPod")))return zc(/Version\/([0-9.]+)/);if(uc||vc){var a=/Version\/(\S+).*Mobile\/(\S+)/.exec(t);if(a)return a[1]+"."+a[2]}else if(wc)return(a=zc(/Android\s+([0-9.]+)/))?a:zc(/Version\/([0-9.]+)/);return""})();var Ac=v&&!(9<=Number(La));function W(a,b){b&&"string"!==typeof b&&(b=b.toString());return!!a&&1==a.nodeType&&(!b||a.tagName.toUpperCase()==b)};var Bc=function(){var a={K:"http://www.w3.org/2000/svg"};return function(b){return a[b]||null}}();
-function Cc(a,b){var c=A(a);if(!c.documentElement)return null;(v||wc)&&kc(c?c.parentWindow||c.defaultView:window);try{var d=c.createNSResolver?c.createNSResolver(c.documentElement):Bc;if(v&&!Ka(7))return c.evaluate.call(c,b,a,d,9,null);if(!v||9<=Number(La)){for(var e={},f=c.getElementsByTagName("*"),g=0;g<f.length;++g){var h=f[g],m=h.namespaceURI;if(m&&!e[m]){var w=h.lookupPrefix(m);if(!w){var r=m.match(".*/(\\w+)/?$");w=r?r[1]:"xhtml"}e[m]=w}}var D={},L;for(L in e)D[e[L]]=L;d=function(M){return D[M]||
-null}}try{return c.evaluate(b,a,d,9,null)}catch(M){if("TypeError"===M.name)return d=c.createNSResolver?c.createNSResolver(c.documentElement):Bc,c.evaluate(b,a,d,9,null);throw M;}}catch(M){if(!Da||"NS_ERROR_ILLEGAL_VALUE"!=M.name)throw new rc(32,"Unable to locate an element with the xpath expression "+b+" because of the following error:\n"+M);}}
-function Dc(a,b){var c=function(){var d=Cc(b,a);return d?d.singleNodeValue||null:b.selectSingleNode?(d=A(b),d.setProperty&&d.setProperty("SelectionLanguage","XPath"),b.selectSingleNode(a)):null}();if(null!==c&&(!c||1!=c.nodeType))throw new rc(32,'The result of the xpath expression "'+a+'" is: '+c+". It should be an element.");return c};function Ec(a,b,c,d){this.c=a;this.a=b;this.b=c;this.f=d}Ec.prototype.ceil=function(){this.c=Math.ceil(this.c);this.a=Math.ceil(this.a);this.b=Math.ceil(this.b);this.f=Math.ceil(this.f);return this};Ec.prototype.floor=function(){this.c=Math.floor(this.c);this.a=Math.floor(this.a);this.b=Math.floor(this.b);this.f=Math.floor(this.f);return this};Ec.prototype.round=function(){this.c=Math.round(this.c);this.a=Math.round(this.a);this.b=Math.round(this.b);this.f=Math.round(this.f);return this};function X(a,b,c,d){this.a=a;this.b=b;this.width=c;this.height=d}X.prototype.ceil=function(){this.a=Math.ceil(this.a);this.b=Math.ceil(this.b);this.width=Math.ceil(this.width);this.height=Math.ceil(this.height);return this};X.prototype.floor=function(){this.a=Math.floor(this.a);this.b=Math.floor(this.b);this.width=Math.floor(this.width);this.height=Math.floor(this.height);return this};
-X.prototype.round=function(){this.a=Math.round(this.a);this.b=Math.round(this.b);this.width=Math.round(this.width);this.height=Math.round(this.height);return this};var Fc="function"===typeof ShadowRoot;function Gc(a){for(a=a.parentNode;a&&1!=a.nodeType&&9!=a.nodeType&&11!=a.nodeType;)a=a.parentNode;return W(a)?a:null}
-function Y(a,b){b=xa(b);if("float"==b||"cssFloat"==b||"styleFloat"==b)b=Ac?"styleFloat":"cssFloat";a:{var c=b;var d=A(a);if(d.defaultView&&d.defaultView.getComputedStyle&&(d=d.defaultView.getComputedStyle(a,null))){c=d[c]||d.getPropertyValue(c)||"";break a}c=""}a=c||Hc(a,b);if(null===a)a=null;else if(0<=ja(mc,b)){b:{var e=a.match(pc);if(e&&(b=Number(e[1]),c=Number(e[2]),d=Number(e[3]),e=Number(e[4]),0<=b&&255>=b&&0<=c&&255>=c&&0<=d&&255>=d&&0<=e&&1>=e)){b=[b,c,d,e];break b}b=null}if(!b)b:{if(d=a.match(qc))if(b=
-Number(d[1]),c=Number(d[2]),d=Number(d[3]),0<=b&&255>=b&&0<=c&&255>=c&&0<=d&&255>=d){b=[b,c,d,1];break b}b=null}if(!b)b:{b=a.toLowerCase();c=lc[b.toLowerCase()];if(!c&&(c="#"==b.charAt(0)?b:"#"+b,4==c.length&&(c=c.replace(nc,"#$1$1$2$2$3$3")),!oc.test(c))){b=null;break b}b=[parseInt(c.substr(1,2),16),parseInt(c.substr(3,2),16),parseInt(c.substr(5,2),16),1]}a=b?"rgba("+b.join(", ")+")":a}return a}
-function Hc(a,b){var c=a.currentStyle||a.style,d=c[b];void 0===d&&"function"==ca(c.getPropertyValue)&&(d=c.getPropertyValue(b));return"inherit"!=d?void 0!==d?d:null:(a=Gc(a))?Hc(a,b):null}
-function Ic(a,b,c){function d(g){var h=Jc(g);return 0<h.height&&0<h.width?!0:W(g,"PATH")&&(0<h.height||0<h.width)?(g=Y(g,"stroke-width"),!!g&&0<parseInt(g,10)):"hidden"!=Y(g,"overflow")&&ma(g.childNodes,function(m){return 3==m.nodeType||W(m)&&d(m)})}function e(g){return Kc(g)==Z&&na(g.childNodes,function(h){return!W(h)||e(h)||!d(h)})}if(!W(a))throw Error("Argument to isShown must be of type Element");if(W(a,"BODY"))return!0;if(W(a,"OPTION")||W(a,"OPTGROUP"))return a=$a(a,function(g){return W(g,"SELECT")}),
-!!a&&Ic(a,!0,c);var f=Lc(a);if(f)return!!f.image&&0<f.rect.width&&0<f.rect.height&&Ic(f.image,b,c);if(W(a,"INPUT")&&"hidden"==a.type.toLowerCase()||W(a,"NOSCRIPT"))return!1;f=Y(a,"visibility");return"collapse"!=f&&"hidden"!=f&&c(a)&&(b||0!=Mc(a))&&d(a)?!e(a):!1}var Z="hidden";
-function Kc(a){function b(p){function q(fb){if(fb==g)return!0;var Wb=Y(fb,"display");return 0==Wb.lastIndexOf("inline",0)||"contents"==Wb||"absolute"==Xb&&"static"==Y(fb,"position")?!1:!0}var Xb=Y(p,"position");if("fixed"==Xb)return w=!0,p==g?null:g;for(p=Gc(p);p&&!q(p);)p=Gc(p);return p}function c(p){var q=p;if("visible"==m)if(p==g&&h)q=h;else if(p==h)return{x:"visible",y:"visible"};q={x:Y(q,"overflow-x"),y:Y(q,"overflow-y")};p==g&&(q.x="visible"==q.x?"auto":q.x,q.y="visible"==q.y?"auto":q.y);return q}
-function d(p){if(p==g){var q=(new ab(f)).a;p=q.scrollingElement?q.scrollingElement:Ea||"CSS1Compat"!=q.compatMode?q.body||q.documentElement:q.documentElement;q=q.parentWindow||q.defaultView;p=v&&Ka("10")&&q.pageYOffset!=p.scrollTop?new Ua(p.scrollLeft,p.scrollTop):new Ua(q.pageXOffset||p.scrollLeft,q.pageYOffset||p.scrollTop)}else p=new Ua(p.scrollLeft,p.scrollTop);return p}var e=Nc(a),f=A(a),g=f.documentElement,h=f.body,m=Y(g,"overflow"),w;for(a=b(a);a;a=b(a)){var r=c(a);if("visible"!=r.x||"visible"!=
-r.y){var D=Jc(a);if(0==D.width||0==D.height)return Z;var L=e.a<D.a,M=e.b<D.b;if(L&&"hidden"==r.x||M&&"hidden"==r.y)return Z;if(L&&"visible"!=r.x||M&&"visible"!=r.y){L=d(a);M=e.b<D.b-L.y;if(e.a<D.a-L.x&&"visible"!=r.x||M&&"visible"!=r.x)return Z;e=Kc(a);return e==Z?Z:"scroll"}L=e.f>=D.a+D.width;D=e.c>=D.b+D.height;if(L&&"hidden"==r.x||D&&"hidden"==r.y)return Z;if(L&&"visible"!=r.x||D&&"visible"!=r.y){if(w&&(r=d(a),e.f>=g.scrollWidth-r.x||e.a>=g.scrollHeight-r.y))return Z;e=Kc(a);return e==Z?Z:"scroll"}}}return"none"}
-function Jc(a){var b=Lc(a);if(b)return b.rect;if(W(a,"HTML"))return a=A(a),a=((a?a.parentWindow||a.defaultView:window)||window).document,a="CSS1Compat"==a.compatMode?a.documentElement:a.body,a=new Va(a.clientWidth,a.clientHeight),new X(0,0,a.width,a.height);try{var c=a.getBoundingClientRect()}catch(d){return new X(0,0,0,0)}b=new X(c.left,c.top,c.right-c.left,c.bottom-c.top);v&&a.ownerDocument.body&&(a=A(a),b.a-=a.documentElement.clientLeft+a.body.clientLeft,b.b-=a.documentElement.clientTop+a.body.clientTop);
-return b}function Lc(a){var b=W(a,"MAP");if(!b&&!W(a,"AREA"))return null;var c=b?a:W(a.parentNode,"MAP")?a.parentNode:null,d=null,e=null;c&&c.name&&(d=Dc('/descendant::*[@usemap = "#'+c.name+'"]',A(c)))&&(e=Jc(d),b||"default"==a.shape.toLowerCase()||(a=Oc(a),b=Math.min(Math.max(a.a,0),e.width),c=Math.min(Math.max(a.b,0),e.height),e=new X(b+e.a,c+e.b,Math.min(a.width,e.width-b),Math.min(a.height,e.height-c))));return{image:d,rect:e||new X(0,0,0,0)}}
-function Oc(a){var b=a.shape.toLowerCase();a=a.coords.split(",");if("rect"==b&&4==a.length){b=a[0];var c=a[1];return new X(b,c,a[2]-b,a[3]-c)}if("circle"==b&&3==a.length)return b=a[2],new X(a[0]-b,a[1]-b,2*b,2*b);if("poly"==b&&2<a.length){b=a[0];c=a[1];for(var d=b,e=c,f=2;f+1<a.length;f+=2)b=Math.min(b,a[f]),d=Math.max(d,a[f]),c=Math.min(c,a[f+1]),e=Math.max(e,a[f+1]);return new X(b,c,d-b,e-c)}return new X(0,0,0,0)}function Nc(a){a=Jc(a);return new Ec(a.b,a.a+a.width,a.b+a.height,a.a)}
-function Mc(a){if(Ac){if("relative"==Y(a,"position"))return 1;a=Y(a,"filter");return(a=a.match(/^alpha\(opacity=(\d*)\)/)||a.match(/^progid:DXImageTransform.Microsoft.Alpha\(Opacity=(\d*)\)/))?Number(a[1])/100:1}return Pc(a)}function Pc(a){var b=1,c=Y(a,"opacity");c&&(b=Number(c));(a=Gc(a))&&(b*=Pc(a));return b};ba("_",function(a,b){function c(d){if(W(d)&&"none"==Y(d,"display"))return!1;var e;if((e=d.parentNode)&&e.shadowRoot&&void 0!==d.assignedSlot)e=d.assignedSlot?d.assignedSlot.parentNode:null;else if(d.getDestinationInsertionPoints){var f=d.getDestinationInsertionPoints();0<f.length&&(e=f[f.length-1])}if(Fc&&e instanceof ShadowRoot){if(e.host.shadowRoot!==e)return!1;e=e.host}return!e||9!=e.nodeType&&11!=e.nodeType?e&&W(e,"DETAILS")&&!e.open&&!W(d,"SUMMARY")?!1:!!e&&c(e):!0}return Ic(a,!!b,c)});; return this._.apply(null,arguments);}).apply({navigator:typeof window!='undefined'?window.navigator:null,document:typeof window!='undefined'?window.document:null}, arguments);}
+seashell:"#fff5ee",sienna:"#a0522d",silver:"#c0c0c0",skyblue:"#87ceeb",slateblue:"#6a5acd",slategray:"#708090",slategrey:"#708090",snow:"#fffafa",springgreen:"#00ff7f",steelblue:"#4682b4",tan:"#d2b48c",teal:"#008080",thistle:"#d8bfd8",tomato:"#ff6347",turquoise:"#40e0d0",violet:"#ee82ee",wheat:"#f5deb3",white:"#ffffff",whitesmoke:"#f5f5f5",yellow:"#ffff00",yellowgreen:"#9acd32"};var ia="backgroundColor borderTopColor borderRightColor borderBottomColor borderLeftColor color outlineColor".split(" "),ja=/#([0-9a-fA-F])([0-9a-fA-F])([0-9a-fA-F])/,ka=/^#(?:[0-9a-f]{3}){1,2}$/i,la=/^(?:rgba)?\((\d{1,3}),\s?(\d{1,3}),\s?(\d{1,3}),\s?(0|1|0\.\d*)\)$/i,ma=/^(?:rgb)?\((0|[1-9]\d{0,2}),\s?(0|[1-9]\d{0,2}),\s?(0|[1-9]\d{0,2})\)$/i;function m(a,b){this.code=a;this.a=p[a]||r;this.message=b||"";a=this.a.replace(/((?:^|\s+)[a-z])/g,function(c){return c.toUpperCase().replace(/^[\s\xa0]+/g,"")});b=a.length-5;if(0>b||a.indexOf("Error",b)!=b)a+="Error";this.name=a;a=Error(this.message);a.name=this.name;this.stack=a.stack||""}ca(m,Error);var r="unknown error",p={15:"element not selectable",11:"element not visible"};p[31]=r;p[30]=r;p[24]="invalid cookie domain";p[29]="invalid element coordinates";p[12]="invalid element state";
+p[32]="invalid selector";p[51]="invalid selector";p[52]="invalid selector";p[17]="javascript error";p[405]="unsupported operation";p[34]="move target out of bounds";p[27]="no such alert";p[7]="no such element";p[8]="no such frame";p[23]="no such window";p[28]="script timeout";p[33]="session not created";p[10]="stale element reference";p[21]="timeout";p[25]="unable to set cookie";p[26]="unexpected alert open";p[13]=r;p[9]="unknown command";var u=String.prototype.trim?function(a){return a.trim()}:function(a){return/^[\s\xa0]*([\s\S]*?)[\s\xa0]*$/.exec(a)[1]};
+function na(a,b){var c=0;a=u(String(a)).split(".");b=u(String(b)).split(".");for(var e=Math.max(a.length,b.length),d=0;0==c&&d<e;d++){var f=a[d]||"",h=b[d]||"";do{f=/(\d*)(\D*)(.*)/.exec(f)||["","","",""];h=/(\d*)(\D*)(.*)/.exec(h)||["","","",""];if(0==f[0].length&&0==h[0].length)break;c=v(0==f[1].length?0:parseInt(f[1],10),0==h[1].length?0:parseInt(h[1],10))||v(0==f[2].length,0==h[2].length)||v(f[2],h[2]);f=f[3];h=h[3]}while(0==c)}return c}function v(a,b){return a<b?-1:a>b?1:0};var w;a:{var oa=g.navigator;if(oa){var sa=oa.userAgent;if(sa){w=sa;break a}}w=""}function x(a){return-1!=w.indexOf(a)};function y(){return x("Firefox")||x("FxiOS")}function A(){return(x("Chrome")||x("CriOS"))&&!x("Edge")};function ta(a){return String(a).replace(/\-([a-z])/g,function(b,c){return c.toUpperCase()})};function B(){return x("iPhone")&&!x("iPod")&&!x("iPad")};function ua(a,b){var c=va;return Object.prototype.hasOwnProperty.call(c,a)?c[a]:c[a]=b(a)};var wa=x("Opera"),C=x("Trident")||x("MSIE"),xa=x("Edge"),ya=x("Gecko")&&!(-1!=w.toLowerCase().indexOf("webkit")&&!x("Edge"))&&!(x("Trident")||x("MSIE"))&&!x("Edge"),za=-1!=w.toLowerCase().indexOf("webkit")&&!x("Edge");function Aa(){var a=g.document;return a?a.documentMode:void 0}var E;
+a:{var F="",G=function(){var a=w;if(ya)return/rv:([^\);]+)(\)|;)/.exec(a);if(xa)return/Edge\/([\d\.]+)/.exec(a);if(C)return/\b(?:MSIE|rv)[: ]([^\);]+)(\)|;)/.exec(a);if(za)return/WebKit\/(\S+)/.exec(a);if(wa)return/(?:Version)[ \/]?(\S+)/.exec(a)}();G&&(F=G?G[1]:"");if(C){var H=Aa();if(null!=H&&H>parseFloat(F)){E=String(H);break a}}E=F}var va={};function Ba(a){return ua(a,function(){return 0<=na(E,a)})}var I;I=g.document&&C?Aa():void 0;var Ca=y(),Da=B()||x("iPod"),Ea=x("iPad"),Fa=x("Android")&&!(A()||y()||x("Opera")||x("Silk")),Ga=A(),Ha=x("Safari")&&!(A()||x("Coast")||x("Opera")||x("Edge")||x("Edg/")||x("OPR")||y()||x("Silk")||x("Android"))&&!(B()||x("iPad")||x("iPod"));function J(a){return(a=a.exec(w))?a[1]:""}(function(){if(Ca)return J(/Firefox\/([0-9.]+)/);if(C||xa||wa)return E;if(Ga)return B()||x("iPad")||x("iPod")?J(/CriOS\/([0-9.]+)/):J(/Chrome\/([0-9.]+)/);if(Ha&&!(B()||x("iPad")||x("iPod")))return J(/Version\/([0-9.]+)/);if(Da||Ea){var a=/Version\/(\S+).*Mobile\/(\S+)/.exec(w);if(a)return a[1]+"."+a[2]}else if(Fa)return(a=J(/Android\s+([0-9.]+)/))?a:J(/Version\/([0-9.]+)/);return""})();var K;if(K=C)K=!(9<=Number(I));var Ia=K;function L(a,b){this.x=void 0!==a?a:0;this.y=void 0!==b?b:0}L.prototype.ceil=function(){this.x=Math.ceil(this.x);this.y=Math.ceil(this.y);return this};L.prototype.floor=function(){this.x=Math.floor(this.x);this.y=Math.floor(this.y);return this};L.prototype.round=function(){this.x=Math.round(this.x);this.y=Math.round(this.y);return this};function M(a,b){this.width=a;this.height=b}M.prototype.aspectRatio=function(){return this.width/this.height};M.prototype.ceil=function(){this.width=Math.ceil(this.width);this.height=Math.ceil(this.height);return this};M.prototype.floor=function(){this.width=Math.floor(this.width);this.height=Math.floor(this.height);return this};M.prototype.round=function(){this.width=Math.round(this.width);this.height=Math.round(this.height);return this};function N(a){return 9==a.nodeType?a:a.ownerDocument||a.document}function Ja(a,b){a&&(a=a.parentNode);for(var c=0;a;){if(b(a))return a;a=a.parentNode;c++}return null}function Ka(a){this.a=a||g.document||document};function P(a,b){b&&"string"!==typeof b&&(b=b.toString());return a instanceof HTMLFormElement?!!a&&1==a.nodeType&&(!b||"FORM"==b):!!a&&1==a.nodeType&&(!b||a.tagName.toUpperCase()==b)};function Q(a,b,c,e){this.f=a;this.a=b;this.b=c;this.c=e}Q.prototype.ceil=function(){this.f=Math.ceil(this.f);this.a=Math.ceil(this.a);this.b=Math.ceil(this.b);this.c=Math.ceil(this.c);return this};Q.prototype.floor=function(){this.f=Math.floor(this.f);this.a=Math.floor(this.a);this.b=Math.floor(this.b);this.c=Math.floor(this.c);return this};Q.prototype.round=function(){this.f=Math.round(this.f);this.a=Math.round(this.a);this.b=Math.round(this.b);this.c=Math.round(this.c);return this};function R(a,b,c,e){this.a=a;this.b=b;this.width=c;this.height=e}R.prototype.ceil=function(){this.a=Math.ceil(this.a);this.b=Math.ceil(this.b);this.width=Math.ceil(this.width);this.height=Math.ceil(this.height);return this};R.prototype.floor=function(){this.a=Math.floor(this.a);this.b=Math.floor(this.b);this.width=Math.floor(this.width);this.height=Math.floor(this.height);return this};
+R.prototype.round=function(){this.a=Math.round(this.a);this.b=Math.round(this.b);this.width=Math.round(this.width);this.height=Math.round(this.height);return this};var La="function"===typeof ShadowRoot;function S(a){for(a=a.parentNode;a&&1!=a.nodeType&&9!=a.nodeType&&11!=a.nodeType;)a=a.parentNode;return P(a)?a:null}
+function T(a,b){b=ta(b);if("float"==b||"cssFloat"==b||"styleFloat"==b)b=Ia?"styleFloat":"cssFloat";a:{var c=b;var e=N(a);if(e.defaultView&&e.defaultView.getComputedStyle&&(e=e.defaultView.getComputedStyle(a,null))){c=e[c]||e.getPropertyValue(c)||"";break a}c=""}a=c||Ma(a,b);if(null===a)a=null;else if(0<=da(ia,b)){b:{var d=a.match(la);if(d&&(b=Number(d[1]),c=Number(d[2]),e=Number(d[3]),d=Number(d[4]),0<=b&&255>=b&&0<=c&&255>=c&&0<=e&&255>=e&&0<=d&&1>=d)){b=[b,c,e,d];break b}b=null}if(!b)b:{if(e=a.match(ma))if(b=
+Number(e[1]),c=Number(e[2]),e=Number(e[3]),0<=b&&255>=b&&0<=c&&255>=c&&0<=e&&255>=e){b=[b,c,e,1];break b}b=null}if(!b)b:{b=a.toLowerCase();c=ha[b.toLowerCase()];if(!c&&(c="#"==b.charAt(0)?b:"#"+b,4==c.length&&(c=c.replace(ja,"#$1$1$2$2$3$3")),!ka.test(c))){b=null;break b}b=[parseInt(c.substr(1,2),16),parseInt(c.substr(3,2),16),parseInt(c.substr(5,2),16),1]}a=b?"rgba("+b.join(", ")+")":a}return a}
+function Ma(a,b){var c=a.currentStyle||a.style,e=c[b];void 0===e&&"function"==aa(c.getPropertyValue)&&(e=c.getPropertyValue(b));return"inherit"!=e?void 0!==e?e:null:(a=S(a))?Ma(a,b):null}
+function U(a,b,c){function e(h){var n=V(h);return 0<n.height&&0<n.width?!0:P(h,"PATH")&&(0<n.height||0<n.width)?(h=T(h,"stroke-width"),!!h&&0<parseInt(h,10)):"hidden"!=T(h,"overflow")&&ea(h.childNodes,function(D){return 3==D.nodeType||P(D)&&e(D)})}function d(h){return Na(h)==W&&fa(h.childNodes,function(n){return!P(n)||d(n)||!e(n)})}if(!P(a))throw Error("Argument to isShown must be of type Element");if(P(a,"BODY"))return!0;if(P(a,"OPTION")||P(a,"OPTGROUP"))return a=Ja(a,function(h){return P(h,"SELECT")}),
+!!a&&U(a,!0,c);var f=Oa(a);if(f)return!!f.image&&0<f.rect.width&&0<f.rect.height&&U(f.image,b,c);if(P(a,"INPUT")&&"hidden"==a.type.toLowerCase()||P(a,"NOSCRIPT"))return!1;f=T(a,"visibility");return"collapse"!=f&&"hidden"!=f&&c(a)&&(b||0!=Pa(a))&&e(a)?!d(a):!1}var W="hidden";
+function Na(a){function b(k){function l(ba){if(ba==h)return!0;var pa=T(ba,"display");return 0==pa.lastIndexOf("inline",0)||"contents"==pa||"absolute"==qa&&"static"==T(ba,"position")?!1:!0}var qa=T(k,"position");if("fixed"==qa)return ra=!0,k==h?null:h;for(k=S(k);k&&!l(k);)k=S(k);return k}function c(k){var l=k;if("visible"==D)if(k==h&&n)l=n;else if(k==n)return{x:"visible",y:"visible"};l={x:T(l,"overflow-x"),y:T(l,"overflow-y")};k==h&&(l.x="visible"==l.x?"auto":l.x,l.y="visible"==l.y?"auto":l.y);return l}
+function e(k){if(k==h){var l=(new Ka(f)).a;k=l.scrollingElement?l.scrollingElement:za||"CSS1Compat"!=l.compatMode?l.body||l.documentElement:l.documentElement;l=l.parentWindow||l.defaultView;k=C&&Ba("10")&&l.pageYOffset!=k.scrollTop?new L(k.scrollLeft,k.scrollTop):new L(l.pageXOffset||k.scrollLeft,l.pageYOffset||k.scrollTop)}else k=new L(k.scrollLeft,k.scrollTop);return k}var d=Qa(a),f=N(a),h=f.documentElement,n=f.body,D=T(h,"overflow"),ra;for(a=b(a);a;a=b(a)){var q=c(a);if("visible"!=q.x||"visible"!=
+q.y){var t=V(a);if(0==t.width||0==t.height)return W;var z=d.a<t.a,O=d.b<t.b;if(z&&"hidden"==q.x||O&&"hidden"==q.y)return W;if(z&&"visible"!=q.x||O&&"visible"!=q.y){z=e(a);O=d.b<t.b-z.y;if(d.a<t.a-z.x&&"visible"!=q.x||O&&"visible"!=q.x)return W;d=Na(a);return d==W?W:"scroll"}z=d.c>=t.a+t.width;t=d.f>=t.b+t.height;if(z&&"hidden"==q.x||t&&"hidden"==q.y)return W;if(z&&"visible"!=q.x||t&&"visible"!=q.y){if(ra&&(q=e(a),d.c>=h.scrollWidth-q.x||d.a>=h.scrollHeight-q.y))return W;d=Na(a);return d==W?W:"scroll"}}}return"none"}
+function V(a){var b=Oa(a);if(b)return b.rect;if(P(a,"HTML"))return a=N(a),a=((a?a.parentWindow||a.defaultView:window)||window).document,a="CSS1Compat"==a.compatMode?a.documentElement:a.body,a=new M(a.clientWidth,a.clientHeight),new R(0,0,a.width,a.height);try{var c=a.getBoundingClientRect()}catch(e){return new R(0,0,0,0)}b=new R(c.left,c.top,c.right-c.left,c.bottom-c.top);C&&a.ownerDocument.body&&(a=N(a),b.a-=a.documentElement.clientLeft+a.body.clientLeft,b.b-=a.documentElement.clientTop+a.body.clientTop);
+return b}
+function Oa(a){var b=P(a,"MAP");if(!b&&!P(a,"AREA"))return null;var c=b?a:P(a.parentNode,"MAP")?a.parentNode:null,e=null,d=null;if(c&&c.name){e='*[usemap="#'+c.name+'"]';c=N(c);var f;if(f="function"!=aa(c.querySelector)&&C&&(C?0<=na(I,8):Ba(8))){f=c.querySelector;var h=typeof f;f=!("object"==h&&null!=f||"function"==h)}if(f)throw Error("CSS selection is not supported");if(!e)throw new m(32,"No selector specified");e=u(e);try{var n=c.querySelector(e)}catch(D){throw new m(32,"An invalid or illegal selector was specified");}if(e=
+n&&1==n.nodeType?n:null)d=V(e),b||"default"==a.shape.toLowerCase()||(a=Ra(a),b=Math.min(Math.max(a.a,0),d.width),n=Math.min(Math.max(a.b,0),d.height),d=new R(b+d.a,n+d.b,Math.min(a.width,d.width-b),Math.min(a.height,d.height-n)))}return{image:e,rect:d||new R(0,0,0,0)}}
+function Ra(a){var b=a.shape.toLowerCase();a=a.coords.split(",");if("rect"==b&&4==a.length){b=a[0];var c=a[1];return new R(b,c,a[2]-b,a[3]-c)}if("circle"==b&&3==a.length)return b=a[2],new R(a[0]-b,a[1]-b,2*b,2*b);if("poly"==b&&2<a.length){b=a[0];c=a[1];for(var e=b,d=c,f=2;f+1<a.length;f+=2)b=Math.min(b,a[f]),e=Math.max(e,a[f]),c=Math.min(c,a[f+1]),d=Math.max(d,a[f+1]);return new R(b,c,e-b,d-c)}return new R(0,0,0,0)}function Qa(a){a=V(a);return new Q(a.b,a.a+a.width,a.b+a.height,a.a)}
+function Pa(a){if(Ia){if("relative"==T(a,"position"))return 1;a=T(a,"filter");return(a=a.match(/^alpha\(opacity=(\d*)\)/)||a.match(/^progid:DXImageTransform.Microsoft.Alpha\(Opacity=(\d*)\)/))?Number(a[1])/100:1}return Sa(a)}function Sa(a){var b=1,c=T(a,"opacity");c&&(b=Number(c));(a=S(a))&&(b*=Sa(a));return b};function Ta(a,b){function c(e){if(P(e)&&("none"==T(e,"display")||"hidden"==T(e,"content-visibility")))return!1;var d;if((d=e.parentNode)&&d.shadowRoot&&void 0!==e.assignedSlot)d=e.assignedSlot?e.assignedSlot.parentNode:null;else if(e.getDestinationInsertionPoints){var f=e.getDestinationInsertionPoints();0<f.length&&(d=f[f.length-1])}if(La&&d instanceof ShadowRoot){if(d.host.shadowRoot&&d.host.shadowRoot!==d)return!1;d=d.host}return!d||9!=d.nodeType&&11!=d.nodeType?d&&P(d,"DETAILS")&&!d.open&&!P(e,
+"SUMMARY")?!1:!!d&&c(d):!0}return U(a,!!b,c)}var X=["se_exportedFunctionSymbol"],Y=g;X[0]in Y||"undefined"==typeof Y.execScript||Y.execScript("var "+X[0]);for(var Z;X.length&&(Z=X.shift());)X.length||void 0===Ta?Y[Z]&&Y[Z]!==Object.prototype[Z]?Y=Y[Z]:Y=Y[Z]={}:Y[Z]=Ta;; return this.se_exportedFunctionSymbol.apply(null,arguments);}).apply(window, arguments);}
diff -pruN 4.4.0-1/lib/selenium/webdriver/atoms.rb 4.38.0-1/lib/selenium/webdriver/atoms.rb
--- 4.4.0-1/lib/selenium/webdriver/atoms.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/atoms.rb	2025-11-02 08:23:03.000000000 +0000
@@ -20,6 +20,10 @@
 module Selenium
   module WebDriver
     module Atoms
+      def atom_script(function_name)
+        format("/* #{function_name} */return (%<atom>s).apply(null, arguments)",
+               atom: read_atom(function_name))
+      end
 
       private
 
@@ -27,11 +31,9 @@ module Selenium
         File.read(File.expand_path("../atoms/#{function}.js", __FILE__))
       end
 
-      def execute_atom(function_name, *arguments)
-        script = format("return (%<atom>s).apply(null, arguments)", atom: read_atom(function_name))
-        execute_script(script, *arguments)
+      def execute_atom(function_name, *)
+        execute_script(atom_script(function_name), *)
       end
-
     end # Atoms
   end # WebDriver
 end # Selenium
diff -pruN 4.4.0-1/lib/selenium/webdriver/bidi/browser.rb 4.38.0-1/lib/selenium/webdriver/bidi/browser.rb
--- 4.4.0-1/lib/selenium/webdriver/bidi/browser.rb	1970-01-01 00:00:00.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/bidi/browser.rb	2025-11-02 08:23:03.000000000 +0000
@@ -0,0 +1,64 @@
+# frozen_string_literal: true
+
+# Licensed to the Software Freedom Conservancy (SFC) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The SFC licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+module Selenium
+  module WebDriver
+    class BiDi
+      class Browser
+        Window = Struct.new(:handle, :active, :height, :width, :x, :y, :state) do
+          def active?
+            active
+          end
+        end
+        def initialize(bidi)
+          @bidi = bidi
+        end
+
+        def create_user_context
+          @bidi.send_cmd('browser.createUserContext')
+        end
+
+        def user_contexts
+          @bidi.send_cmd('browser.getUserContexts')
+        end
+
+        def remove_user_context(user_context)
+          @bidi.send_cmd('browser.removeUserContext', userContext: user_context)
+        end
+
+        def windows
+          response = @bidi.send_cmd('browser.getClientWindows')
+
+          response['clientWindows'].map do |win_data|
+            attributes = {
+              handle: win_data['clientWindow'],
+              active: win_data['active'],
+              height: win_data['height'],
+              width: win_data['width'],
+              x: win_data['x'],
+              y: win_data['y'],
+              state: win_data['state']
+            }
+            Window.new(**attributes)
+          end
+        end
+      end # Browser
+    end # BiDi
+  end # WebDriver
+end # Selenium
diff -pruN 4.4.0-1/lib/selenium/webdriver/bidi/browsing_context.rb 4.38.0-1/lib/selenium/webdriver/bidi/browsing_context.rb
--- 4.4.0-1/lib/selenium/webdriver/bidi/browsing_context.rb	1970-01-01 00:00:00.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/bidi/browsing_context.rb	2025-11-02 08:23:03.000000000 +0000
@@ -0,0 +1,115 @@
+# frozen_string_literal: true
+
+# Licensed to the Software Freedom Conservancy (SFC) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The SFC licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+module Selenium
+  module WebDriver
+    class BiDi
+      # Implements the browsingContext Module of the WebDriver-BiDi specification
+      #
+      # @api private
+      #
+      class BrowsingContext
+        READINESS_STATE = {
+          'none' => 'none',
+          'eager' => 'interactive',
+          'normal' => 'complete'
+        }.freeze
+
+        # TODO: store current window handle in bridge object instead of always calling it
+        def initialize(bridge)
+          @bridge = bridge
+          @bidi = @bridge.bidi
+          page_load_strategy = bridge.capabilities[:page_load_strategy]
+          @readiness = READINESS_STATE[page_load_strategy]
+        end
+
+        # Navigates to the specified URL in the given browsing context.
+        #
+        # @param url [String] The URL to navigate to.
+        # @param context_id [String, NilClass] The ID of the browsing context to navigate in.
+        #   Defaults to the window handle of the current context.
+        def navigate(url, context_id: nil)
+          context_id ||= @bridge.window_handle
+          @bidi.send_cmd('browsingContext.navigate', context: context_id, url: url, wait: @readiness)
+        end
+
+        # Traverses the browsing context history by a given delta.
+        #
+        # @param delta [Integer] The number of steps to traverse.
+        #   Positive values go forwards, negative values go backwards.
+        # @param context_id [String, NilClass] The ID of the context to traverse.
+        #   Defaults to the window handle of the current context.
+        def traverse_history(delta, context_id: nil)
+          context_id ||= @bridge.window_handle
+          @bidi.send_cmd('browsingContext.traverseHistory', context: context_id, delta: delta)
+        end
+
+        # Reloads the browsing context.
+        # @param [String, NilClass] context_id The ID of the context to reload.
+        #   Defaults to the window handle of the current context.
+        # @param [Boolean] ignore_cache Whether to bypass the cache when reloading.
+        #   Defaults to false.
+        def reload(context_id: nil, ignore_cache: false)
+          context_id ||= @bridge.window_handle
+          params = {context: context_id, ignore_cache: ignore_cache, wait: @readiness}
+          @bidi.send_cmd('browsingContext.reload', **params)
+        end
+
+        # Closes the browsing context.
+        #
+        # @param [String] context_id The ID of the context to close.
+        #   Defaults to the window handle of the current context.
+        def close(context_id: nil)
+          context_id ||= @bridge.window_handle
+          @bidi.send_cmd('browsingContext.close', context: context_id)
+        end
+
+        # Create a new browsing context.
+        #
+        # @param [Symbol] type The type of browsing context to create.
+        #   Valid options are :tab and :window with :window being the default
+        # @param [String] context_id The reference context for the new browsing context.
+        #   Defaults to the current window handle.
+        #
+        # @return [String] The context ID of the created browsing context.
+        def create(type: nil, context_id: nil)
+          type ||= :window
+          context_id ||= @bridge.window_handle
+          result = @bidi.send_cmd('browsingContext.create', type: type.to_s, referenceContext: context_id)
+          result['context']
+        end
+
+        def set_viewport(context_id: nil, width: nil, height: nil, device_pixel_ratio: nil)
+          context_id ||= @bridge.window_handle
+          params = {context: context_id, viewport: {width:, height:}, device_pixel_ratio:}
+          @bidi.send_cmd('browsingContext.setViewport', **params)
+        end
+
+        def handle_user_prompt(context_id, accept: true, text: nil)
+          @bidi.send_cmd('browsingContext.handleUserPrompt', context: context_id, accept: accept, text: text)
+        end
+
+        def activate(context_id: nil)
+          context_id ||= @bridge.window_handle
+          @bidi.send_cmd('browsingContext.activate', context: context_id)
+        end
+      end # BrowsingContext
+    end # BiDi
+  end # WebDriver
+end # Selenium
diff -pruN 4.4.0-1/lib/selenium/webdriver/bidi/log_handler.rb 4.38.0-1/lib/selenium/webdriver/bidi/log_handler.rb
--- 4.4.0-1/lib/selenium/webdriver/bidi/log_handler.rb	1970-01-01 00:00:00.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/bidi/log_handler.rb	2025-11-02 08:23:03.000000000 +0000
@@ -0,0 +1,65 @@
+# frozen_string_literal: true
+
+# Licensed to the Software Freedom Conservancy (SFC) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The SFC licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+module Selenium
+  module WebDriver
+    class BiDi
+      class LogHandler
+        ConsoleLogEntry = BiDi::Struct.new(:level, :text, :timestamp, :stack_trace, :type, :source, :method, :args)
+        JavaScriptLogEntry = BiDi::Struct.new(:level, :text, :timestamp, :stack_trace, :type, :source)
+
+        def initialize(bidi)
+          @bidi = bidi
+          @log_entry_subscribed = false
+        end
+
+        # @return [int] id of the handler
+        # steep:ignore:start
+        def add_message_handler(type)
+          subscribe_log_entry unless @log_entry_subscribed
+          @bidi.add_callback('log.entryAdded') do |params|
+            if params['type'] == type
+              log_entry_klass = type == 'console' ? ConsoleLogEntry : JavaScriptLogEntry
+              yield(log_entry_klass.new(**params))
+            end
+          end
+        end
+        # steep:ignore:end
+
+        # @param [int] id of the handler previously added
+        def remove_message_handler(id)
+          @bidi.remove_callback('log.entryAdded', id)
+          unsubscribe_log_entry if @log_entry_subscribed && @bidi.callbacks['log.entryAdded'].empty?
+        end
+
+        private
+
+        def subscribe_log_entry
+          @bidi.session.subscribe('log.entryAdded')
+          @log_entry_subscribed = true
+        end
+
+        def unsubscribe_log_entry
+          @bidi.session.unsubscribe('log.entryAdded')
+          @log_entry_subscribed = false
+        end
+      end # LogHandler
+    end # Bidi
+  end # WebDriver
+end # Selenium
diff -pruN 4.4.0-1/lib/selenium/webdriver/bidi/network/cookies.rb 4.38.0-1/lib/selenium/webdriver/bidi/network/cookies.rb
--- 4.4.0-1/lib/selenium/webdriver/bidi/network/cookies.rb	1970-01-01 00:00:00.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/bidi/network/cookies.rb	2025-11-02 08:23:03.000000000 +0000
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+
+# Licensed to the Software Freedom Conservancy (SFC) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The SFC licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+module Selenium
+  module WebDriver
+    class BiDi
+      class Cookies < Hash
+        def as_json
+          map do |name, val|
+            self[:name] = name.to_s
+            self[:value] = {type: 'string', value: val.to_s}
+
+            [compact]
+          end
+        end
+      end
+    end # BiDi
+  end # WebDriver
+end # Selenium
diff -pruN 4.4.0-1/lib/selenium/webdriver/bidi/network/credentials.rb 4.38.0-1/lib/selenium/webdriver/bidi/network/credentials.rb
--- 4.4.0-1/lib/selenium/webdriver/bidi/network/credentials.rb	1970-01-01 00:00:00.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/bidi/network/credentials.rb	2025-11-02 08:23:03.000000000 +0000
@@ -0,0 +1,43 @@
+# frozen_string_literal: true
+
+# Licensed to the Software Freedom Conservancy (SFC) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The SFC licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+module Selenium
+  module WebDriver
+    class BiDi
+      class Credentials
+        attr_accessor :username, :password
+
+        def initialize(username: nil, password: nil)
+          @username = username
+          @password = password
+        end
+
+        def as_json
+          return nil unless username && password
+
+          {
+            type: 'password',
+            username: username,
+            password: password
+          }
+        end
+      end
+    end # BiDi
+  end # WebDriver
+end # Selenium
diff -pruN 4.4.0-1/lib/selenium/webdriver/bidi/network/headers.rb 4.38.0-1/lib/selenium/webdriver/bidi/network/headers.rb
--- 4.4.0-1/lib/selenium/webdriver/bidi/network/headers.rb	1970-01-01 00:00:00.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/bidi/network/headers.rb	2025-11-02 08:23:03.000000000 +0000
@@ -0,0 +1,38 @@
+# frozen_string_literal: true
+
+# Licensed to the Software Freedom Conservancy (SFC) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The SFC licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+module Selenium
+  module WebDriver
+    class BiDi
+      class Headers < Hash
+        def as_json
+          map do |name, val|
+            {
+              name: name.to_s,
+              value: {
+                type: 'string',
+                value: val.to_s
+              }
+            }
+          end
+        end
+      end
+    end # BiDi
+  end # WebDriver
+end # Selenium
diff -pruN 4.4.0-1/lib/selenium/webdriver/bidi/network/intercepted_auth.rb 4.38.0-1/lib/selenium/webdriver/bidi/network/intercepted_auth.rb
--- 4.4.0-1/lib/selenium/webdriver/bidi/network/intercepted_auth.rb	1970-01-01 00:00:00.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/bidi/network/intercepted_auth.rb	2025-11-02 08:23:03.000000000 +0000
@@ -0,0 +1,38 @@
+# frozen_string_literal: true
+
+# Licensed to the Software Freedom Conservancy (SFC) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The SFC licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+module Selenium
+  module WebDriver
+    class BiDi
+      class InterceptedAuth < InterceptedItem
+        def authenticate(username, password)
+          network.continue_with_auth(id, username, password)
+        end
+
+        def skip
+          network.continue_without_auth(id)
+        end
+
+        def cancel
+          network.cancel_auth(id)
+        end
+      end
+    end # BiDi
+  end # WebDriver
+end # Selenium
diff -pruN 4.4.0-1/lib/selenium/webdriver/bidi/network/intercepted_item.rb 4.38.0-1/lib/selenium/webdriver/bidi/network/intercepted_item.rb
--- 4.4.0-1/lib/selenium/webdriver/bidi/network/intercepted_item.rb	1970-01-01 00:00:00.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/bidi/network/intercepted_item.rb	2025-11-02 08:23:03.000000000 +0000
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+# Licensed to the Software Freedom Conservancy (SFC) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The SFC licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+module Selenium
+  module WebDriver
+    class BiDi
+      class InterceptedItem
+        attr_reader :network, :request
+
+        def initialize(network, request)
+          @network = network
+          @request = request
+        end
+
+        def id
+          @id ||= @request['request']
+        end
+      end
+    end # BiDi
+  end # WebDriver
+end # Selenium
diff -pruN 4.4.0-1/lib/selenium/webdriver/bidi/network/intercepted_request.rb 4.38.0-1/lib/selenium/webdriver/bidi/network/intercepted_request.rb
--- 4.4.0-1/lib/selenium/webdriver/bidi/network/intercepted_request.rb	1970-01-01 00:00:00.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/bidi/network/intercepted_request.rb	2025-11-02 08:23:03.000000000 +0000
@@ -0,0 +1,81 @@
+# frozen_string_literal: true
+
+# Licensed to the Software Freedom Conservancy (SFC) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The SFC licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+require_relative 'cookies'
+require_relative 'headers'
+
+module Selenium
+  module WebDriver
+    class BiDi
+      class InterceptedRequest < InterceptedItem
+        attr_accessor :method, :url
+        attr_reader :body
+
+        def initialize(network, request)
+          super
+          @method = nil
+          @url = nil
+          @body = nil
+          @headers = nil
+          @cookies = nil
+        end
+
+        def continue
+          cookies = @cookies&.as_json
+          headers = @headers&.as_json
+          network.continue_request(
+            id: id,
+            body: body,
+            cookies: cookies,
+            headers: headers,
+            method: method,
+            url: url
+          )
+        end
+
+        def fail
+          network.fail_request(id)
+        end
+
+        def body=(value)
+          @body = {
+            type: 'string',
+            value: value.to_json
+          }
+        end
+
+        def headers=(headers = {})
+          @headers = Headers.new(headers)
+        end
+
+        def headers(headers = {})
+          @headers ||= Headers.new(headers)
+        end
+
+        def cookies(cookies = {})
+          @cookies ||= Cookies.new(cookies)
+        end
+
+        def cookies=(cookies = {})
+          @cookies = Cookies.new(cookies)
+        end
+      end
+    end # BiDi
+  end # WebDriver
+end # Selenium
diff -pruN 4.4.0-1/lib/selenium/webdriver/bidi/network/intercepted_response.rb 4.38.0-1/lib/selenium/webdriver/bidi/network/intercepted_response.rb
--- 4.4.0-1/lib/selenium/webdriver/bidi/network/intercepted_response.rb	1970-01-01 00:00:00.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/bidi/network/intercepted_response.rb	2025-11-02 08:23:03.000000000 +0000
@@ -0,0 +1,95 @@
+# frozen_string_literal: true
+
+# Licensed to the Software Freedom Conservancy (SFC) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The SFC licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+require_relative 'credentials'
+require_relative 'headers'
+require_relative 'cookies'
+
+module Selenium
+  module WebDriver
+    class BiDi
+      class InterceptedResponse < InterceptedItem
+        attr_accessor :reason, :status
+        attr_reader :body
+
+        def initialize(network, request)
+          super
+          @reason = nil
+          @status = nil
+          @body = nil
+          @headers = nil
+          @cookies = nil
+        end
+
+        def continue
+          cookies = @cookies&.as_json
+          headers = @headers&.as_json
+          network.continue_response(
+            id: id,
+            cookies: cookies,
+            headers: headers,
+            credentials: credentials.as_json,
+            reason: reason,
+            status: status
+          )
+        end
+
+        def provide_response
+          cookies = @cookies&.as_json
+          headers = @headers&.as_json
+          network.provide_response(
+            id: id,
+            cookies: cookies,
+            headers: headers,
+            body: body,
+            reason: reason,
+            status: status
+          )
+        end
+
+        def credentials(username: nil, password: nil)
+          @credentials ||= Credentials.new(username: username, password: password)
+        end
+
+        def headers(headers = {})
+          @headers ||= Headers.new(headers)
+        end
+
+        def headers=(*headers)
+          @headers = Headers.new(headers)
+        end
+
+        def cookies(cookies = {})
+          @cookies ||= Cookies.new(cookies)
+        end
+
+        def cookies=(cookies = {})
+          @cookies ||= Cookies.new(cookies)
+        end
+
+        def body=(value)
+          @body = {
+            type: 'string',
+            value: value.to_json
+          }
+        end
+      end
+    end # BiDi
+  end # WebDriver
+end # Selenium
diff -pruN 4.4.0-1/lib/selenium/webdriver/bidi/network/url_pattern.rb 4.38.0-1/lib/selenium/webdriver/bidi/network/url_pattern.rb
--- 4.4.0-1/lib/selenium/webdriver/bidi/network/url_pattern.rb	1970-01-01 00:00:00.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/bidi/network/url_pattern.rb	2025-11-02 08:23:03.000000000 +0000
@@ -0,0 +1,65 @@
+# frozen_string_literal: true
+
+# Licensed to the Software Freedom Conservancy (SFC) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The SFC licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+require 'uri'
+
+module Selenium
+  module WebDriver
+    class BiDi
+      module UrlPattern
+        module_function
+
+        def format_pattern(url_patterns, pattern_type)
+          case pattern_type
+          when :string
+            to_url_string_pattern(url_patterns)
+          when :url
+            to_url_pattern(url_patterns)
+          else
+            raise ArgumentError, "Unknown pattern type: #{pattern_type}"
+          end
+        end
+
+        def to_url_pattern(*url_patterns)
+          url_patterns.flatten.map do |url_pattern|
+            uri = URI.parse(url_pattern)
+
+            {
+              type: 'pattern',
+              protocol: uri.scheme || '',
+              hostname: uri.host || '',
+              port: uri.port.to_s,
+              pathname: uri.path || '',
+              search: uri.query || ''
+            }
+          end
+        end
+
+        def to_url_string_pattern(*url_patterns)
+          url_patterns.flatten.map do |url_pattern|
+            {
+              type: 'string',
+              pattern: url_pattern
+            }
+          end
+        end
+      end
+    end # BiDi
+  end # WebDriver
+end # Selenium
diff -pruN 4.4.0-1/lib/selenium/webdriver/bidi/network.rb 4.38.0-1/lib/selenium/webdriver/bidi/network.rb
--- 4.4.0-1/lib/selenium/webdriver/bidi/network.rb	1970-01-01 00:00:00.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/bidi/network.rb	2025-11-02 08:23:03.000000000 +0000
@@ -0,0 +1,142 @@
+# frozen_string_literal: true
+
+# Licensed to the Software Freedom Conservancy (SFC) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The SFC licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+require_relative 'network/url_pattern'
+
+module Selenium
+  module WebDriver
+    class BiDi
+      class Network
+        EVENTS = {
+          before_request: 'network.beforeRequestSent',
+          response_started: 'network.responseStarted',
+          response_completed: 'network.responseCompleted',
+          auth_required: 'network.authRequired',
+          fetch_error: 'network.fetchError'
+        }.freeze
+
+        PHASES = {
+          before_request: 'beforeRequestSent',
+          response_started: 'responseStarted',
+          auth_required: 'authRequired'
+        }.freeze
+
+        def initialize(bidi)
+          @bidi = bidi
+        end
+
+        def add_intercept(phases: [], contexts: nil, url_patterns: nil, pattern_type: :string)
+          url_patterns = url_patterns && pattern_type ? UrlPattern.format_pattern(url_patterns, pattern_type) : nil
+          @bidi.send_cmd('network.addIntercept',
+                         phases: phases,
+                         contexts: contexts,
+                         urlPatterns: url_patterns)
+        end
+
+        def remove_intercept(intercept)
+          @bidi.send_cmd('network.removeIntercept', intercept: intercept)
+        end
+
+        def continue_with_auth(request_id, username, password)
+          @bidi.send_cmd(
+            'network.continueWithAuth',
+            request: request_id,
+            action: 'provideCredentials',
+            credentials: {
+              type: 'password',
+              username: username,
+              password: password
+            }
+          )
+        end
+
+        def continue_without_auth(request_id)
+          @bidi.send_cmd(
+            'network.continueWithAuth',
+            request: request_id,
+            action: 'default'
+          )
+        end
+
+        def cancel_auth(request_id)
+          @bidi.send_cmd(
+            'network.continueWithAuth',
+            request: request_id,
+            action: 'cancel'
+          )
+        end
+
+        def continue_request(**args)
+          args = {
+            request: args[:id],
+            body: args[:body],
+            cookies: args[:cookies],
+            headers: args[:headers],
+            method: args[:method],
+            url: args[:url]
+          }.compact
+
+          @bidi.send_cmd('network.continueRequest', **args)
+        end
+
+        def fail_request(request_id)
+          @bidi.send_cmd(
+            'network.failRequest',
+            request: request_id
+          )
+        end
+
+        def continue_response(**args)
+          args = {
+            request: args[:id],
+            cookies: args[:cookies],
+            credentials: args[:credentials],
+            headers: args[:headers],
+            reasonPhrase: args[:reason],
+            statusCode: args[:status]
+          }.compact
+
+          @bidi.send_cmd('network.continueResponse', **args)
+        end
+
+        def provide_response(**args)
+          args = {
+            request: args[:id],
+            body: args[:body],
+            cookies: args[:cookies],
+            headers: args[:headers],
+            reasonPhrase: args[:reason],
+            statusCode: args[:status]
+          }.compact
+
+          @bidi.send_cmd('network.provideResponse', **args)
+        end
+
+        def set_cache_behavior(behavior, *contexts)
+          @bidi.send_cmd('network.setCacheBehavior', cacheBehavior: behavior, contexts: contexts)
+        end
+
+        def on(event, &block)
+          event = EVENTS[event] if event.is_a?(Symbol)
+          @bidi.add_callback(event, &block)
+          @bidi.session.subscribe(event)
+        end
+      end # Network
+    end # BiDi
+  end # WebDriver
+end # Selenium
diff -pruN 4.4.0-1/lib/selenium/webdriver/bidi/session.rb 4.38.0-1/lib/selenium/webdriver/bidi/session.rb
--- 4.4.0-1/lib/selenium/webdriver/bidi/session.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/bidi/session.rb	2025-11-02 08:23:03.000000000 +0000
@@ -29,9 +29,22 @@ module Selenium
 
         def status
           status = @bidi.send_cmd('session.status')
-          Status.new(status['ready'], status['message'])
+          Status.new(**status)
         end
 
+        def subscribe(events, browsing_contexts = nil)
+          opts = {events: Array(events)}
+          opts[:browsing_contexts] = Array(browsing_contexts) if browsing_contexts
+
+          @bidi.send_cmd('session.subscribe', **opts)
+        end
+
+        def unsubscribe(events, browsing_contexts = nil)
+          opts = {events: Array(events)}
+          opts[:browsing_contexts] = Array(browsing_contexts) if browsing_contexts
+
+          @bidi.send_cmd('session.unsubscribe', **opts)
+        end
       end # Session
     end # BiDi
   end # WebDriver
diff -pruN 4.4.0-1/lib/selenium/webdriver/bidi/struct.rb 4.38.0-1/lib/selenium/webdriver/bidi/struct.rb
--- 4.4.0-1/lib/selenium/webdriver/bidi/struct.rb	1970-01-01 00:00:00.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/bidi/struct.rb	2025-11-02 08:23:03.000000000 +0000
@@ -0,0 +1,42 @@
+# frozen_string_literal: true
+
+# Licensed to the Software Freedom Conservancy (SFC) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The SFC licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+module Selenium
+  module WebDriver
+    class BiDi
+      class Struct < ::Struct
+        class << self
+          def new(*args, &block)
+            super do
+              define_method(:initialize) do |**kwargs|
+                converted_kwargs = kwargs.transform_keys { |key| self.class.camel_to_snake(key.to_s).to_sym }
+                super(*converted_kwargs.values_at(*self.class.members))
+              end
+              class_eval(&block) if block
+            end
+          end
+
+          def camel_to_snake(camel_str)
+            camel_str.gsub(/([A-Z])/, '_\1').downcase
+          end
+        end
+      end
+    end # BiDi
+  end # WebDriver
+end # Selenium
diff -pruN 4.4.0-1/lib/selenium/webdriver/bidi.rb 4.38.0-1/lib/selenium/webdriver/bidi.rb
--- 4.4.0-1/lib/selenium/webdriver/bidi.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/bidi.rb	2025-11-02 08:23:03.000000000 +0000
@@ -21,6 +21,15 @@ module Selenium
   module WebDriver
     class BiDi
       autoload :Session, 'selenium/webdriver/bidi/session'
+      autoload :LogHandler, 'selenium/webdriver/bidi/log_handler'
+      autoload :Browser, 'selenium/webdriver/bidi/browser'
+      autoload :BrowsingContext, 'selenium/webdriver/bidi/browsing_context'
+      autoload :Struct, 'selenium/webdriver/bidi/struct'
+      autoload :Network, 'selenium/webdriver/bidi/network'
+      autoload :InterceptedRequest, 'selenium/webdriver/bidi/network/intercepted_request'
+      autoload :InterceptedResponse, 'selenium/webdriver/bidi/network/intercepted_response'
+      autoload :InterceptedAuth, 'selenium/webdriver/bidi/network/intercepted_auth'
+      autoload :InterceptedItem, 'selenium/webdriver/bidi/network/intercepted_item'
 
       def initialize(url:)
         @ws = WebSocketConnection.new(url: url)
@@ -34,8 +43,16 @@ module Selenium
         @ws.callbacks
       end
 
+      def add_callback(event, &block)
+        @ws.add_callback(event, &block)
+      end
+
+      def remove_callback(event, id)
+        @ws.remove_callback(event, id)
+      end
+
       def session
-        Session.new(self)
+        @session ||= Session.new(self)
       end
 
       def send_cmd(method, **params)
@@ -49,7 +66,6 @@ module Selenium
       def error_message(message)
         "#{message['error']}: #{message['message']}\n#{message['stacktrace']}"
       end
-
     end # BiDi
   end # WebDriver
 end # Selenium
diff -pruN 4.4.0-1/lib/selenium/webdriver/chrome/driver.rb 4.38.0-1/lib/selenium/webdriver/chrome/driver.rb
--- 4.4.0-1/lib/selenium/webdriver/chrome/driver.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/chrome/driver.rb	2025-11-02 08:23:03.000000000 +0000
@@ -17,31 +17,23 @@
 # specific language governing permissions and limitations
 # under the License.
 
+require 'selenium/webdriver/chromium/driver'
+
 module Selenium
   module WebDriver
     module Chrome
-
       #
       # Driver implementation for Chrome.
       # @api private
       #
 
-      class Driver < WebDriver::Driver
-        EXTENSIONS = [DriverExtensions::HasCDP,
-                      DriverExtensions::HasCasting,
-                      DriverExtensions::HasNetworkConditions,
-                      DriverExtensions::HasNetworkInterception,
-                      DriverExtensions::HasWebStorage,
-                      DriverExtensions::HasLaunching,
-                      DriverExtensions::HasLocation,
-                      DriverExtensions::HasPermissions,
-                      DriverExtensions::DownloadsFiles,
-                      DriverExtensions::HasDevTools,
-                      DriverExtensions::HasAuthentication,
-                      DriverExtensions::HasLogs,
-                      DriverExtensions::HasLogEvents,
-                      DriverExtensions::HasPinnedScripts,
-                      DriverExtensions::PrintsPage].freeze
+      class Driver < Chromium::Driver
+        include LocalDriver
+
+        def initialize(options: nil, service: nil, url: nil, **)
+          caps, url = initialize_local_driver(options, service, url)
+          super(caps: caps, url: url, **)
+        end
 
         def browser
           :chrome
@@ -49,21 +41,9 @@ module Selenium
 
         private
 
-        def devtools_url
-          uri = URI(devtools_address)
-          response = Net::HTTP.get(uri.hostname, '/json/version', uri.port)
-
-          JSON.parse(response)['webSocketDebuggerUrl']
-        end
-
-        def devtools_version
-          Integer(capabilities.browser_version.split('.').first)
-        end
-
         def devtools_address
           "http://#{capabilities['goog:chromeOptions']['debuggerAddress']}"
         end
-
       end # Driver
     end # Chrome
   end # WebDriver
diff -pruN 4.4.0-1/lib/selenium/webdriver/chrome/features.rb 4.38.0-1/lib/selenium/webdriver/chrome/features.rb
--- 4.4.0-1/lib/selenium/webdriver/chrome/features.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/chrome/features.rb	2025-11-02 08:23:03.000000000 +0000
@@ -17,93 +17,30 @@
 # specific language governing permissions and limitations
 # under the License.
 
+require 'selenium/webdriver/chromium/features'
+
 module Selenium
   module WebDriver
     module Chrome
       module Features
+        include WebDriver::Chromium::Features
 
         CHROME_COMMANDS = {
-          launch_app: [:post, 'session/:session_id/chromium/launch_app'],
           get_cast_sinks: [:get, 'session/:session_id/goog/cast/get_sinks'],
           set_cast_sink_to_use: [:post, 'session/:session_id/goog/cast/set_sink_to_use'],
           start_cast_tab_mirroring: [:post, 'session/:session_id/goog/cast/start_tab_mirroring'],
           start_cast_desktop_mirroring: [:post, 'session/:session_id/goog/cast/start_desktop_mirroring'],
           get_cast_issue_message: [:get, 'session/:session_id/goog/cast/get_issue_message'],
           stop_casting: [:post, 'session/:session_id/goog/cast/stop_casting'],
-          get_network_conditions: [:get, 'session/:session_id/chromium/network_conditions'],
-          set_network_conditions: [:post, 'session/:session_id/chromium/network_conditions'],
-          delete_network_conditions: [:delete, 'session/:session_id/chromium/network_conditions'],
-          set_permission: [:post, 'session/:session_id/permissions'],
-          send_command: [:post, 'session/:session_id/goog/cdp/execute'],
-          get_available_log_types: [:get, 'session/:session_id/se/log/types'],
-          get_log: [:post, 'session/:session_id/se/log']
+          send_command: [:post, 'session/:session_id/goog/cdp/execute']
         }.freeze
 
-        def commands(command)
-          CHROME_COMMANDS[command] || self.class::COMMANDS[command]
-        end
-
-        def launch_app(id)
-          execute :launch_app, {}, {id: id}
-        end
-
-        def cast_sinks
-          execute :get_cast_sinks
-        end
-
-        def cast_sink_to_use=(name)
-          execute :set_cast_sink_to_use, {}, {sinkName: name}
-        end
-
-        def cast_issue_message
-          execute :cast_issue_message
-        end
-
-        def start_cast_tab_mirroring(name)
-          execute :start_cast_tab_mirroring, {}, {sinkName: name}
-        end
-
-        def start_cast_desktop_mirroring(name)
-          execute :start_cast_desktop_mirroring, {}, {sinkName: name}
-        end
-
-        def stop_casting(name)
-          execute :stop_casting, {}, {sinkName: name}
-        end
-
-        def set_permission(name, value)
-          execute :set_permission, {}, {descriptor: {name: name}, state: value}
-        end
-
-        def network_conditions
-          execute :get_network_conditions
-        end
-
-        def network_conditions=(conditions)
-          execute :set_network_conditions, {}, {network_conditions: conditions}
+        def command_list
+          CHROME_COMMANDS.merge(CHROMIUM_COMMANDS).merge(self.class::COMMANDS)
         end
 
-        def delete_network_conditions
-          execute :delete_network_conditions
-        end
-
-        def send_command(command_params)
-          execute :send_command, {}, command_params
-        end
-
-        def available_log_types
-          types = execute :get_available_log_types
-          Array(types).map(&:to_sym)
-        end
-
-        def log(type)
-          data = execute :get_log, {}, {type: type.to_s}
-
-          Array(data).map do |l|
-            LogEntry.new l.fetch('level', 'UNKNOWN'), l.fetch('timestamp'), l.fetch('message')
-          rescue KeyError
-            next
-          end
+        def commands(command)
+          command_list[command]
         end
       end # Bridge
     end # Chrome
diff -pruN 4.4.0-1/lib/selenium/webdriver/chrome/options.rb 4.38.0-1/lib/selenium/webdriver/chrome/options.rb
--- 4.4.0-1/lib/selenium/webdriver/chrome/options.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/chrome/options.rb	2025-11-02 08:23:03.000000000 +0000
@@ -17,258 +17,24 @@
 # specific language governing permissions and limitations
 # under the License.
 
+require 'selenium/webdriver/chromium/options'
+
 module Selenium
   module WebDriver
     module Chrome
-      class Options < WebDriver::Options
-        attr_accessor :profile, :logging_prefs
-
+      class Options < Chromium::Options
         KEY = 'goog:chromeOptions'
         BROWSER = 'chrome'
 
-        # see: http://chromedriver.chromium.org/capabilities
-        CAPABILITIES = {args: 'args',
-                        binary: 'binary',
-                        local_state: 'localState',
-                        prefs: 'prefs',
-                        detach: 'detach',
-                        debugger_address: 'debuggerAddress',
-                        exclude_switches: 'excludeSwitches',
-                        minidump_path: 'minidumpPath',
-                        emulation: 'mobileEmulation',
-                        perf_logging_prefs: 'perfLoggingPrefs',
-                        window_types: 'windowTypes',
-                        android_package: 'androidPackage',
-                        android_activity: 'androidActivity',
-                        android_device_serial: 'androidDeviceSerial',
-                        android_use_running_app: 'androidUseRunningApp'}.freeze
-
-        # NOTE: special handling of 'extensions' to validate when set instead of when used
-        attr_reader :extensions
-
-        # Create a new Options instance.
-        #
-        # @example
-        #   options = Selenium::WebDriver::Chrome::Options.new(args: ['start-maximized', 'user-data-dir=/tmp/temp_profile'])
-        #   driver = Selenium::WebDriver.for(:chrome, capabilities: options)
-        #
-        # @param [Profile] profile An instance of a Chrome::Profile Class
-        # @param [Hash] opts the pre-defined options to create the Chrome::Options with
-        # @option opts [Array] encoded_extensions List of extensions that do not need to be Base64 encoded
-        # @option opts [Array<String>] args List of command-line arguments to use when starting Chrome
-        # @option opts [String] binary Path to the Chrome executable to use
-        # @option opts [Hash] prefs A hash with each entry consisting of the name of the preference and its value
-        # @option opts [Array<String>] extensions A list of paths to (.crx) Chrome extensions to install on startup
-        # @option opts [Hash] options A hash for raw options
-        # @option opts [Hash] emulation A hash for raw emulation options
-        # @option opts [Hash] local_state A hash for the Local State file in the user data folder
-        # @option opts [Boolean] detach whether browser is closed when the driver is sent the quit command
-        # @option opts [String] debugger_address address of a Chrome debugger server to connect to
-        # @option opts [Array<String>] exclude_switches command line switches to exclude
-        # @option opts [String] minidump_path Directory to store Chrome minidumps (linux only)
-        # @option opts [Hash] perf_logging_prefs A hash for performance logging preferences
-        # @option opts [Array<String>] window_types A list of window types to appear in the list of window handles
-        #
-
-        def initialize(profile: nil, **opts)
-          super(**opts)
-
-          @profile = profile
-
-          @options = {args: [],
-                      prefs: {},
-                      emulation: {},
-                      extensions: [],
-                      local_state: {},
-                      exclude_switches: [],
-                      perf_logging_prefs: {},
-                      window_types: []}.merge(@options)
-
-          @logging_prefs = options.delete(:logging_prefs) || {}
-          @encoded_extensions = @options.delete(:encoded_extensions) || []
-          @extensions = []
-          @options.delete(:extensions).each { |ext| validate_extension(ext) }
-        end
-
-        #
-        # Add an extension by local path.
-        #
-        # @example
-        #   options = Selenium::WebDriver::Chrome::Options.new
-        #   options.add_extension('/path/to/extension.crx')
-        #
-        # @param [String] path The local path to the .crx file
-        #
-
-        def add_extension(path)
-          validate_extension(path)
-        end
-
-        #
-        # Add an extension by local path.
-        #
-        # @example
-        #   extensions = ['/path/to/extension.crx', '/path/to/other.crx']
-        #   options = Selenium::WebDriver::Chrome::Options.new
-        #   options.extensions = extensions
-        #
-        # @param [Array<String>] extensions A list of paths to (.crx) Chrome extensions to install on startup
-        #
-
-        def extensions=(extensions)
-          extensions.each { |ext| validate_extension(ext) }
-        end
-
-        #
-        # Add an extension by Base64-encoded string.
-        #
-        # @example
-        #   options = Selenium::WebDriver::Chrome::Options.new
-        #   options.add_encoded_extension(encoded_string)
-        #
-        # @param [String] encoded The Base64-encoded string of the .crx file
-        #
-
-        def add_encoded_extension(encoded)
-          @encoded_extensions << encoded
-        end
-
-        #
-        # Add a command-line argument to use when starting Chrome.
-        #
-        # @example Start Chrome maximized
-        #   options = Selenium::WebDriver::Chrome::Options.new
-        #   options.add_argument('start-maximized')
-        #
-        # @param [String] arg The command-line argument to add
-        #
-
-        def add_argument(arg)
-          @options[:args] << arg
-        end
-
-        #
-        # Add a preference that is only applied to the user profile in use.
-        #
-        # @example Set the default homepage
-        #   options = Selenium::WebDriver::Chrome::Options.new
-        #   options.add_preference('homepage', 'http://www.seleniumhq.com/')
-        #
-        # @param [String] name Key of the preference
-        # @param [Boolean, String, Integer] value Value of the preference
-        #
-
-        def add_preference(name, value)
-          @options[:prefs][name] = value
-        end
-
-        #
-        # Run Chrome in headless mode.
-        #
-        # @example Enable headless mode
-        #   options = Selenium::WebDriver::Chrome::Options.new
-        #   options.headless!
-        #
-
-        def headless!
-          add_argument '--headless'
-        end
-
-        #
-        # Add emulation device information
-        #
-        # see: http://chromedriver.chromium.org/mobile-emulation
-        #
-        # @example Start Chrome in mobile emulation mode by device name
-        #   options = Selenium::WebDriver::Chrome::Options.new
-        #   options.add_emulation(device_name: 'iPhone 6')
-        #
-        # @example Start Chrome in mobile emulation mode by device metrics
-        #   options = Selenium::WebDriver::Chrome::Options.new
-        #   options.add_emulation(device_metrics: {width: 400, height: 800, pixelRatio: 1, touch: true})
-        #
-        # @param [Hash] opts the pre-defined options for adding mobile emulation values
-        # @option opts [String] :device_name A valid device name from the Chrome DevTools Emulation panel
-        # @option opts [Hash] :device_metrics Hash containing width, height, pixelRatio, touch
-        # @option opts [String] :user_agent Full user agent
-        #
-
-        def add_emulation(**opts)
-          @options[:emulation] = opts
-        end
-
-        #
-        # Enables mobile browser use on Android.
-        #
-        # @see https://chromedriver.chromium.org/getting-started/getting-started---android
-        #
-        # @param [String] package The package name of the Chrome or WebView app.
-        # @param [String] serial_number The device serial number on which to launch the Chrome or WebView app.
-        # @param [String] use_running_app When true uses an already-running Chrome or WebView app,
-        #   instead of launching the app with a clear data directory.
-        # @param [String] activity Name of the Activity hosting the WebView (Not available on Chrome Apps).
-        #
-
-        def enable_android(package: 'com.android.chrome', serial_number: nil, use_running_app: nil, activity: nil)
-          @options[:android_package] = package
-          @options[:android_activity] = activity unless activity.nil?
-          @options[:android_device_serial] = serial_number unless serial_number.nil?
-          @options[:android_use_running_app] = use_running_app unless use_running_app.nil?
-        end
-
         private
 
         def enable_logging(browser_options)
           browser_options['goog:loggingPrefs'] = @logging_prefs
         end
 
-        def process_browser_options(browser_options)
-          enable_logging(browser_options) unless @logging_prefs.empty?
-
-          options = browser_options[self.class::KEY]
-          options['binary'] ||= binary_path if binary_path
-
-          check_w3c(options[:w3c]) if options.key?(:w3c)
-
-          if @profile
-            options['args'] ||= []
-            options['args'] << "--user-data-dir=#{@profile.directory}"
-          end
-
-          return if (@encoded_extensions + @extensions).empty?
-
-          options['extensions'] = @encoded_extensions + @extensions.map { |ext| encode_extension(ext) }
-        end
-
-        def check_w3c(w3c)
-          if w3c
-            WebDriver.logger.warn("Setting 'w3c: true' is redundant and will no longer be allowed", id: :w3c)
-            return
-          end
-
-          raise Error::InvalidArgumentError,
-                "Setting 'w3c: false' is not allowed.\n" \
-                "Please update to W3C Syntax: https://www.selenium.dev/blog/2022/legacy-protocol-support/"
-        end
-
         def binary_path
           Chrome.path
         end
-
-        def encode_extension(path)
-          File.open(path, 'rb') { |crx_file| Base64.strict_encode64 crx_file.read }
-        end
-
-        def validate_extension(path)
-          raise Error::WebDriverError, "could not find extension at #{path.inspect}" unless File.file?(path)
-          raise Error::WebDriverError, "file was not an extension #{path.inspect}" unless File.extname(path) == '.crx'
-
-          @extensions << path
-        end
-
-        def camelize?(key)
-          !%w[localState prefs].include?(key)
-        end
       end # Options
     end # Chrome
   end # WebDriver
diff -pruN 4.4.0-1/lib/selenium/webdriver/chrome/profile.rb 4.38.0-1/lib/selenium/webdriver/chrome/profile.rb
--- 4.4.0-1/lib/selenium/webdriver/chrome/profile.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/chrome/profile.rb	2025-11-02 08:23:03.000000000 +0000
@@ -17,6 +17,8 @@
 # specific language governing permissions and limitations
 # under the License.
 
+require 'selenium/webdriver/chromium/profile'
+
 module Selenium
   module WebDriver
     module Chrome
@@ -24,89 +26,7 @@ module Selenium
       # @private
       #
 
-      class Profile
-        include ProfileHelper
-
-        def initialize(model = nil)
-          @model = verify_model(model)
-          @extensions = []
-          @encoded_extensions = []
-          @directory = nil
-        end
-
-        def add_extension(path)
-          raise Error::WebDriverError, "could not find extension at #{path.inspect}" unless File.file?(path)
-
-          @extensions << path
-        end
-
-        def add_encoded_extension(encoded)
-          @encoded_extensions << encoded
-        end
-
-        def directory
-          @directory || layout_on_disk
-        end
-
-        #
-        # Set a preference in the profile.
-        #
-        # See https://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/pref_names.cc
-        #
-
-        def []=(key, value)
-          parts = key.split('.')
-          parts[0..-2].inject(prefs) { |a, e| a[e] ||= {} }[parts.last] = value
-        end
-
-        def [](key)
-          parts = key.split('.')
-          parts.inject(prefs) { |a, e| a.fetch(e) }
-        end
-
-        def layout_on_disk
-          @directory = @model ? create_tmp_copy(@model) : Dir.mktmpdir('webdriver-chrome-profile')
-          FileReaper << @directory
-
-          write_prefs_to @directory
-
-          @directory
-        end
-
-        def as_json(*)
-          extensions = @extensions.map do |crx_path|
-            File.open(crx_path, 'rb') { |crx_file| Base64.strict_encode64 crx_file.read }
-          end
-
-          extensions.concat(@encoded_extensions)
-
-          opts = {'directory' => directory || layout_on_disk}
-          opts['extensions'] = extensions if extensions.any?
-          opts
-        end
-
-        private
-
-        def write_prefs_to(dir)
-          prefs_file = prefs_file_for(dir)
-
-          FileUtils.mkdir_p File.dirname(prefs_file)
-          File.open(prefs_file, 'w') { |file| file << JSON.generate(prefs) }
-        end
-
-        def prefs
-          @prefs ||= read_model_prefs
-        end
-
-        def read_model_prefs
-          return {} unless @model
-
-          JSON.parse File.read(prefs_file_for(@model))
-        end
-
-        def prefs_file_for(dir)
-          File.join dir, 'Default', 'Preferences'
-        end
+      class Profile < Chromium::Profile
       end # Profile
     end # Chrome
   end # WebDriver
diff -pruN 4.4.0-1/lib/selenium/webdriver/chrome/service.rb 4.38.0-1/lib/selenium/webdriver/chrome/service.rb
--- 4.4.0-1/lib/selenium/webdriver/chrome/service.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/chrome/service.rb	2025-11-02 08:23:03.000000000 +0000
@@ -23,28 +23,14 @@ module Selenium
       class Service < WebDriver::Service
         DEFAULT_PORT = 9515
         EXECUTABLE = 'chromedriver'
-        MISSING_TEXT = <<~ERROR
-          Unable to find chromedriver. Please download the server from
-          https://chromedriver.storage.googleapis.com/index.html and place it somewhere on your PATH.
-          More info at https://github.com/SeleniumHQ/selenium/wiki/ChromeDriver.
-        ERROR
         SHUTDOWN_SUPPORTED = true
+        DRIVER_PATH_ENV_KEY = 'SE_CHROMEDRIVER'
 
-        private
+        def log
+          return @log unless @log.is_a? String
 
-        # NOTE: This processing is deprecated
-        def extract_service_args(driver_opts)
-          driver_args = super
-          driver_opts = driver_opts.dup
-          driver_args << "--log-path=#{driver_opts.delete(:log_path)}" if driver_opts.key?(:log_path)
-          driver_args << "--url-base=#{driver_opts.delete(:url_base)}" if driver_opts.key?(:url_base)
-          driver_args << "--port-server=#{driver_opts.delete(:port_server)}" if driver_opts.key?(:port_server)
-          if driver_opts.key?(:whitelisted_ips)
-            driver_args << "--whitelisted-ips=#{driver_opts.delete(:whitelisted_ips)}"
-          end
-          driver_args << "--verbose" if driver_opts.key?(:verbose)
-          driver_args << "--silent" if driver_opts.key?(:silent)
-          driver_args
+          @args << "--log-path=#{@log}"
+          @log = nil
         end
       end # Service
     end # Chrome
diff -pruN 4.4.0-1/lib/selenium/webdriver/chrome.rb 4.38.0-1/lib/selenium/webdriver/chrome.rb
--- 4.4.0-1/lib/selenium/webdriver/chrome.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/chrome.rb	2025-11-02 08:23:03.000000000 +0000
@@ -17,8 +17,6 @@
 # specific language governing permissions and limitations
 # under the License.
 
-require 'net/http'
-
 module Selenium
   module WebDriver
     module Chrome
diff -pruN 4.4.0-1/lib/selenium/webdriver/chromium/driver.rb 4.38.0-1/lib/selenium/webdriver/chromium/driver.rb
--- 4.4.0-1/lib/selenium/webdriver/chromium/driver.rb	1970-01-01 00:00:00.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/chromium/driver.rb	2025-11-02 08:23:03.000000000 +0000
@@ -0,0 +1,60 @@
+# frozen_string_literal: true
+
+# Licensed to the Software Freedom Conservancy (SFC) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The SFC licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+module Selenium
+  module WebDriver
+    module Chromium
+      #
+      # Driver implementation for Chrome.
+      # @api private
+      #
+
+      class Driver < WebDriver::Driver
+        EXTENSIONS = [DriverExtensions::HasCDP,
+                      DriverExtensions::HasBiDi,
+                      DriverExtensions::HasCasting,
+                      DriverExtensions::HasFedCmDialog,
+                      DriverExtensions::HasNetworkConditions,
+                      DriverExtensions::HasNetworkInterception,
+                      DriverExtensions::HasLaunching,
+                      DriverExtensions::HasPermissions,
+                      DriverExtensions::DownloadsFiles,
+                      DriverExtensions::HasDevTools,
+                      DriverExtensions::HasAuthentication,
+                      DriverExtensions::HasLogs,
+                      DriverExtensions::HasLogEvents,
+                      DriverExtensions::HasPinnedScripts,
+                      DriverExtensions::PrintsPage].freeze
+
+        protected
+
+        def devtools_url
+          uri = URI(devtools_address)
+          response = Net::HTTP.get(uri.hostname, '/json/version', uri.port)
+
+          JSON.parse(response)['webSocketDebuggerUrl']
+        end
+
+        def devtools_version
+          Integer(capabilities.browser_version.split('.').first)
+        end
+      end # Driver
+    end # Chromium
+  end # WebDriver
+end # Selenium
diff -pruN 4.4.0-1/lib/selenium/webdriver/chromium/features.rb 4.38.0-1/lib/selenium/webdriver/chromium/features.rb
--- 4.4.0-1/lib/selenium/webdriver/chromium/features.rb	1970-01-01 00:00:00.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/chromium/features.rb	2025-11-02 08:23:03.000000000 +0000
@@ -0,0 +1,99 @@
+# frozen_string_literal: true
+
+# Licensed to the Software Freedom Conservancy (SFC) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The SFC licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+module Selenium
+  module WebDriver
+    module Chromium
+      module Features
+        CHROMIUM_COMMANDS = {
+          launch_app: [:post, 'session/:session_id/chromium/launch_app'],
+          get_network_conditions: [:get, 'session/:session_id/chromium/network_conditions'],
+          set_network_conditions: [:post, 'session/:session_id/chromium/network_conditions'],
+          delete_network_conditions: [:delete, 'session/:session_id/chromium/network_conditions'],
+          set_permission: [:post, 'session/:session_id/permissions'],
+          get_available_log_types: [:get, 'session/:session_id/se/log/types'],
+          get_log: [:post, 'session/:session_id/se/log']
+        }.freeze
+
+        def launch_app(id)
+          execute :launch_app, {}, {id: id}
+        end
+
+        def cast_sinks
+          execute :get_cast_sinks
+        end
+
+        def cast_sink_to_use=(name)
+          execute :set_cast_sink_to_use, {}, {sinkName: name}
+        end
+
+        def cast_issue_message
+          execute :cast_issue_message
+        end
+
+        def start_cast_tab_mirroring(name)
+          execute :start_cast_tab_mirroring, {}, {sinkName: name}
+        end
+
+        def start_cast_desktop_mirroring(name)
+          execute :start_cast_desktop_mirroring, {}, {sinkName: name}
+        end
+
+        def stop_casting(name)
+          execute :stop_casting, {}, {sinkName: name}
+        end
+
+        def set_permission(name, value)
+          execute :set_permission, {}, {descriptor: {name: name}, state: value}
+        end
+
+        def network_conditions
+          execute :get_network_conditions
+        end
+
+        def network_conditions=(conditions)
+          execute :set_network_conditions, {}, {network_conditions: conditions}
+        end
+
+        def delete_network_conditions
+          execute :delete_network_conditions
+        end
+
+        def send_command(command_params)
+          execute :send_command, {}, command_params
+        end
+
+        def available_log_types
+          types = execute :get_available_log_types
+          Array(types).map(&:to_sym)
+        end
+
+        def log(type)
+          data = execute :get_log, {}, {type: type.to_s}
+
+          Array(data).map do |l|
+            LogEntry.new l.fetch('level', 'UNKNOWN'), l.fetch('timestamp'), l.fetch('message')
+          rescue KeyError
+            next
+          end
+        end
+      end # Bridge
+    end # Chromium
+  end # WebDriver
+end # Selenium
diff -pruN 4.4.0-1/lib/selenium/webdriver/chromium/options.rb 4.38.0-1/lib/selenium/webdriver/chromium/options.rb
--- 4.4.0-1/lib/selenium/webdriver/chromium/options.rb	1970-01-01 00:00:00.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/chromium/options.rb	2025-11-02 08:23:03.000000000 +0000
@@ -0,0 +1,243 @@
+# frozen_string_literal: true
+
+# Licensed to the Software Freedom Conservancy (SFC) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The SFC licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+module Selenium
+  module WebDriver
+    module Chromium
+      class Options < WebDriver::Options
+        attr_accessor :profile, :logging_prefs
+
+        # see: http://chromedriver.chromium.org/capabilities
+        CAPABILITIES = {args: 'args',
+                        binary: 'binary',
+                        local_state: 'localState',
+                        prefs: 'prefs',
+                        detach: 'detach',
+                        debugger_address: 'debuggerAddress',
+                        exclude_switches: 'excludeSwitches',
+                        minidump_path: 'minidumpPath',
+                        emulation: 'mobileEmulation',
+                        perf_logging_prefs: 'perfLoggingPrefs',
+                        window_types: 'windowTypes',
+                        android_package: 'androidPackage',
+                        android_activity: 'androidActivity',
+                        android_device_serial: 'androidDeviceSerial',
+                        android_use_running_app: 'androidUseRunningApp'}.freeze
+
+        # NOTE: special handling of 'extensions' to validate when set instead of when used
+        attr_reader :extensions
+
+        # Create a new Options instance.
+        #
+        # @example
+        #   options = Selenium::WebDriver::Chrome::Options.new(args: ['start-maximized', 'user-data-dir=/tmp/temp_profile'])
+        #   driver = Selenium::WebDriver.for(:chrome, options: options)
+        #
+        # @param [Profile] profile An instance of a Chrome::Profile Class
+        # @param [Hash] opts the pre-defined options to create the Chrome::Options with
+        # @option opts [Array] encoded_extensions List of extensions that do not need to be Base64 encoded
+        # @option opts [Array<String>] args List of command-line arguments to use when starting Chrome
+        # @option opts [String] binary Path to the Chrome executable to use
+        # @option opts [Hash] prefs A hash with each entry consisting of the name of the preference and its value
+        # @option opts [Array<String>] extensions A list of paths to (.crx) Chrome extensions to install on startup
+        # @option opts [Hash] options A hash for raw options
+        # @option opts [Hash] emulation A hash for raw emulation options
+        # @option opts [Hash] local_state A hash for the Local State file in the user data folder
+        # @option opts [Boolean] detach whether browser is closed when the driver is sent the quit command
+        # @option opts [String] debugger_address address of a Chrome debugger server to connect to
+        # @option opts [Array<String>] exclude_switches command line switches to exclude
+        # @option opts [String] minidump_path Directory to store Chrome minidumps (linux only)
+        # @option opts [Hash] perf_logging_prefs A hash for performance logging preferences
+        # @option opts [Array<String>] window_types A list of window types to appear in the list of window handles
+        #
+
+        def initialize(profile: nil, **)
+          super(**)
+
+          @profile = profile
+
+          @options = {args: [],
+                      prefs: {},
+                      emulation: {},
+                      extensions: [],
+                      local_state: {},
+                      exclude_switches: [],
+                      perf_logging_prefs: {},
+                      window_types: []}.merge(@options)
+
+          @logging_prefs = options.delete(:logging_prefs) || {}
+          @encoded_extensions = @options.delete(:encoded_extensions) || []
+          @extensions = []
+          @options.delete(:extensions).each { |ext| validate_extension(ext) }
+        end
+
+        #
+        # Add an extension by local path.
+        #
+        # @example
+        #   options = Selenium::WebDriver::Chrome::Options.new
+        #   options.add_extension('/path/to/extension.crx')
+        #
+        # @param [String] path The local path to the .crx file
+        #
+
+        def add_extension(path)
+          validate_extension(path)
+        end
+
+        #
+        # Add an extension by local path.
+        #
+        # @example
+        #   extensions = ['/path/to/extension.crx', '/path/to/other.crx']
+        #   options = Selenium::WebDriver::Chrome::Options.new
+        #   options.extensions = extensions
+        #
+        # @param [Array<String>] extensions A list of paths to (.crx) Chrome extensions to install on startup
+        #
+
+        def extensions=(extensions)
+          extensions.each { |ext| validate_extension(ext) }
+        end
+
+        #
+        # Add an extension by Base64-encoded string.
+        #
+        # @example
+        #   options = Selenium::WebDriver::Chrome::Options.new
+        #   options.add_encoded_extension(encoded_string)
+        #
+        # @param [String] encoded The Base64-encoded string of the .crx file
+        #
+
+        def add_encoded_extension(encoded)
+          @encoded_extensions << encoded
+        end
+
+        #
+        # Add a command-line argument to use when starting Chrome.
+        #
+        # @example Start Chrome maximized
+        #   options = Selenium::WebDriver::Chrome::Options.new
+        #   options.add_argument('start-maximized')
+        #
+        # @param [String] arg The command-line argument to add
+        #
+
+        def add_argument(arg)
+          @options[:args] << arg
+        end
+
+        #
+        # Add a preference that is only applied to the user profile in use.
+        #
+        # @example Set the default homepage
+        #   options = Selenium::WebDriver::Chrome::Options.new
+        #   options.add_preference('homepage', 'http://www.seleniumhq.com/')
+        #
+        # @param [String] name Key of the preference
+        # @param [Boolean, String, Integer] value Value of the preference
+        #
+
+        def add_preference(name, value)
+          @options[:prefs][name] = value
+        end
+
+        #
+        # Add emulation device information
+        #
+        # see: http://chromedriver.chromium.org/mobile-emulation
+        #
+        # @example Start Chrome in mobile emulation mode by device name
+        #   options = Selenium::WebDriver::Chrome::Options.new
+        #   options.add_emulation(device_name: 'iPhone 6')
+        #
+        # @example Start Chrome in mobile emulation mode by device metrics
+        #   options = Selenium::WebDriver::Chrome::Options.new
+        #   options.add_emulation(device_metrics: {width: 400, height: 800, pixelRatio: 1, touch: true})
+        #
+        # @param [Hash] opts the pre-defined options for adding mobile emulation values
+        # @option opts [String] :device_name A valid device name from the Chrome DevTools Emulation panel
+        # @option opts [Hash] :device_metrics Hash containing width, height, pixelRatio, touch
+        # @option opts [String] :user_agent Full user agent
+        #
+
+        def add_emulation(**opts)
+          @options[:emulation] = opts
+        end
+
+        #
+        # Enables mobile browser use on Android.
+        #
+        # @see https://chromedriver.chromium.org/getting-started/getting-started---android
+        #
+        # @param [String] package The package name of the Chrome or WebView app.
+        # @param [String] serial_number The device serial number on which to launch the Chrome or WebView app.
+        # @param [String] use_running_app When true uses an already-running Chrome or WebView app,
+        #   instead of launching the app with a clear data directory.
+        # @param [String] activity Name of the Activity hosting the WebView (Not available on Chrome Apps).
+        #
+
+        def enable_android(package: 'com.android.chrome', serial_number: nil, use_running_app: nil, activity: nil)
+          @options[:android_package] = package
+          @options[:android_activity] = activity unless activity.nil?
+          @options[:android_device_serial] = serial_number unless serial_number.nil?
+          @options[:android_use_running_app] = use_running_app unless use_running_app.nil?
+        end
+
+        protected
+
+        def process_browser_options(browser_options)
+          enable_logging(browser_options) unless @logging_prefs.empty?
+
+          options = browser_options[self.class::KEY]
+          options['binary'] ||= binary_path if binary_path
+
+          if @profile
+            options['args'] ||= []
+            options['args'] << "--user-data-dir=#{@profile.directory}"
+          end
+
+          return if (@encoded_extensions + @extensions).empty?
+
+          options['extensions'] = @encoded_extensions + @extensions.map { |ext| encode_extension(ext) }
+        end
+
+        def binary_path
+          Chrome.path
+        end
+
+        def encode_extension(path)
+          File.open(path, 'rb') { |crx_file| Base64.strict_encode64 crx_file.read }
+        end
+
+        def validate_extension(path)
+          raise Error::WebDriverError, "could not find extension at #{path.inspect}" unless File.file?(path)
+          raise Error::WebDriverError, "file was not an extension #{path.inspect}" unless File.extname(path) == '.crx'
+
+          @extensions << path
+        end
+
+        def camelize?(key)
+          !%w[localState prefs].include?(key)
+        end
+      end # Options
+    end # Chromium
+  end # WebDriver
+end # Selenium
diff -pruN 4.4.0-1/lib/selenium/webdriver/chromium/profile.rb 4.38.0-1/lib/selenium/webdriver/chromium/profile.rb
--- 4.4.0-1/lib/selenium/webdriver/chromium/profile.rb	1970-01-01 00:00:00.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/chromium/profile.rb	2025-11-02 08:23:03.000000000 +0000
@@ -0,0 +1,113 @@
+# frozen_string_literal: true
+
+# Licensed to the Software Freedom Conservancy (SFC) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The SFC licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+module Selenium
+  module WebDriver
+    module Chromium
+      #
+      # @private
+      #
+
+      class Profile
+        include ProfileHelper
+
+        def initialize(model = nil)
+          @model = verify_model(model)
+          @extensions = []
+          @encoded_extensions = []
+          @directory = nil
+        end
+
+        def add_extension(path)
+          raise Error::WebDriverError, "could not find extension at #{path.inspect}" unless File.file?(path)
+
+          @extensions << path
+        end
+
+        def add_encoded_extension(encoded)
+          @encoded_extensions << encoded
+        end
+
+        def directory
+          @directory || layout_on_disk
+        end
+
+        #
+        # Set a preference in the profile.
+        #
+        # See https://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/pref_names.cc
+        #
+
+        def []=(key, value)
+          parts = key.split('.')
+          parts[0..-2].inject(prefs) { |a, e| a[e] ||= {} }[parts.last] = value
+        end
+
+        def [](key)
+          parts = key.split('.')
+          parts.inject(prefs) { |a, e| a.fetch(e) }
+        end
+
+        def layout_on_disk
+          @directory = @model ? create_tmp_copy(@model) : Dir.mktmpdir('webdriver-chrome-profile')
+          FileReaper << @directory
+
+          write_prefs_to @directory
+
+          @directory
+        end
+
+        def as_json(*)
+          extensions = @extensions.map do |crx_path|
+            File.open(crx_path, 'rb') { |crx_file| Base64.strict_encode64 crx_file.read }
+          end
+
+          extensions.concat(@encoded_extensions)
+
+          opts = {'directory' => directory || layout_on_disk}
+          opts['extensions'] = extensions if extensions.any?
+          opts
+        end
+
+        private
+
+        def write_prefs_to(dir)
+          prefs_file = prefs_file_for(dir)
+
+          FileUtils.mkdir_p File.dirname(prefs_file)
+          File.open(prefs_file, 'w') { |file| file << JSON.generate(prefs) }
+        end
+
+        def prefs
+          @prefs ||= read_model_prefs
+        end
+
+        def read_model_prefs
+          return {} unless @model
+
+          JSON.parse File.read(prefs_file_for(@model))
+        end
+
+        def prefs_file_for(dir)
+          File.join dir, 'Default', 'Preferences'
+        end
+      end # Profile
+    end # Chromium
+  end # WebDriver
+end # Selenium
diff -pruN 4.4.0-1/lib/selenium/webdriver/chromium.rb 4.38.0-1/lib/selenium/webdriver/chromium.rb
--- 4.4.0-1/lib/selenium/webdriver/chromium.rb	1970-01-01 00:00:00.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/chromium.rb	2025-11-02 08:23:03.000000000 +0000
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+# Licensed to the Software Freedom Conservancy (SFC) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The SFC licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+module Selenium
+  module WebDriver
+    module Chromium
+      autoload :Features, 'selenium/webdriver/chromium/features'
+      autoload :Driver, 'selenium/webdriver/chromium/driver'
+      autoload :Profile, 'selenium/webdriver/chromium/profile'
+      autoload :Options, 'selenium/webdriver/chromium/options'
+    end # Chromium
+  end # WebDriver
+end # Selenium
diff -pruN 4.4.0-1/lib/selenium/webdriver/common/action_builder.rb 4.38.0-1/lib/selenium/webdriver/common/action_builder.rb
--- 4.4.0-1/lib/selenium/webdriver/common/action_builder.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/common/action_builder.rb	2025-11-02 08:23:03.000000000 +0000
@@ -33,39 +33,18 @@ module Selenium
       # correctly when using asynchronous.
       #
       # @param [Selenium::WebDriver::Remote::Bridge] bridge the bridge for the current driver instance.
-      # @param [Selenium::WebDriver::Interactions::PointerInput] deprecated_mouse PointerInput for the mouse.
-      # @param [Selenium::WebDriver::Interactions::KeyInput] deprecated_keyboard KeyInput for the keyboard.
-      # @param [Boolean] deprecated_async Whether to perform the actions asynchronously per device.
-      #   Defaults to false for backwards compatibility.
       # @param [Array<Selenium::WebDriver::Interactions::InputDevices>] devices list of valid sources of input.
       # @param [Boolean] async Whether to perform the actions asynchronously per device.
       # @return [ActionBuilder] A self reference.
       #
 
-      def initialize(bridge, deprecated_mouse = nil, deprecated_keyboard = nil, deprecated_async = nil,
-                     devices: [], async: false, duration: 250)
+      def initialize(bridge, devices: [], async: false, duration: 250)
         @bridge = bridge
         @duration = duration
-
-        @async = if deprecated_async.nil?
-                   async
-                 else
-                   WebDriver.logger.deprecate('initializing ActionBuilder with async parameter',
-                                              ':async keyword',
-                                              id: :action_async)
-                   deprecated_async
-                 end
-
+        @async = async
         @devices = []
-        if deprecated_keyboard || deprecated_mouse
-          WebDriver.logger.deprecate "initializing ActionBuilder with keyboard and mouse parameters",
-                                     "devices keyword or, even better, Driver#action",
-                                     id: :action_devices
-          add_input(deprecated_mouse)
-          add_input(deprecated_keyboard)
-        else
-          Array(devices).each { |device| add_input(device) }
-        end
+
+        Array(devices).each { |device| add_input(device) }
       end
 
       #
@@ -119,20 +98,6 @@ module Selenium
       end
 
       #
-      # Retrieves the input device for the given name
-      #
-      # @param [String] name name of the input device
-      # @return [Selenium::WebDriver::Interactions::InputDevice] input device with given name
-      #
-
-      def get_device(name)
-        WebDriver.logger.deprecate('#get_device with name parameter',
-                                   '#device with :name or :type keyword',
-                                   id: :get_device)
-        device(name: name)
-      end
-
-      #
       # Retrieves the input device for the given name or type
       #
       # @param [String] name name of the input device
@@ -194,11 +159,9 @@ module Selenium
       # @return [ActionBuilder] A self reference.
       #
 
-      def pause(deprecated_device = nil, deprecated_duration = nil, device: nil, duration: 0)
-        deprecate_method(deprecated_device, deprecated_duration)
-
-        device ||= deprecated_device || pointer_input
-        device.create_pause(deprecated_duration || duration)
+      def pause(device: nil, duration: 0)
+        device ||= pointer_input
+        device.create_pause(duration)
         self
       end
 
@@ -218,13 +181,10 @@ module Selenium
       # @return [ActionBuilder] A self reference.
       #
 
-      def pauses(deprecated_device = nil, deprecated_number = nil, deprecated_duration = nil,
-                 device: nil, number: nil, duration: 0)
-        deprecate_method(deprecated_device, deprecated_duration, deprecated_number, method: :pauses)
-
-        number ||= deprecated_number || 2
-        device ||= deprecated_device || pointer_input
-        duration ||= deprecated_duration || 0
+      def pauses(device: nil, number: nil, duration: 0)
+        number ||= 2
+        device ||= pointer_input
+        duration ||= 0
 
         number.times { device.create_pause(duration) }
         self
@@ -286,15 +246,6 @@ module Selenium
         @devices << device
         device
       end
-
-      def deprecate_method(device = nil, duration = nil, number = nil, method: :pause)
-        return unless device || number || duration
-
-        WebDriver.logger.deprecate "ActionBuilder##{method} with ordered parameters",
-                                   ':device, :duration, :number keywords',
-                                   id: method
-      end
-
     end # ActionBuilder
   end # WebDriver
 end # Selenium
diff -pruN 4.4.0-1/lib/selenium/webdriver/common/child_process.rb 4.38.0-1/lib/selenium/webdriver/common/child_process.rb
--- 4.4.0-1/lib/selenium/webdriver/common/child_process.rb	1970-01-01 00:00:00.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/common/child_process.rb	2025-11-02 08:23:03.000000000 +0000
@@ -0,0 +1,140 @@
+# frozen_string_literal: true
+
+# Licensed to the Software Freedom Conservancy (SFC) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The SFC licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+module Selenium
+  module WebDriver
+    #
+    # @api private
+    #
+
+    class ChildProcess
+      TimeoutError = Class.new(StandardError)
+
+      SIGTERM = 'TERM'
+      SIGKILL = 'KILL'
+
+      POLL_INTERVAL = 0.1
+
+      attr_accessor :detach
+      attr_writer :io
+
+      def self.build(*command)
+        new(*command)
+      end
+
+      def initialize(*command)
+        @command = command
+        @detach = false
+        @pid = nil
+        @status = nil
+      end
+
+      def io
+        @io ||= Platform.null_device
+      end
+
+      def start
+        options = {%i[out err] => io}
+        options[:pgroup] = true unless Platform.windows? # NOTE: this is a bug only in Windows 7
+
+        WebDriver.logger.debug("Starting process: #{@command} with #{options}", id: :process)
+        @pid = Process.spawn(*@command, options)
+        WebDriver.logger.debug("  -> pid: #{@pid}", id: :process)
+
+        Process.detach(@pid) if detach
+      end
+
+      def stop(timeout = 3)
+        return unless @pid
+        return if exited?
+
+        terminate_and_wait_else_kill(timeout)
+      rescue Errno::ECHILD, Errno::ESRCH => e
+        # Process exited earlier than terminate/kill could catch
+        WebDriver.logger.debug("    -> process: #{@pid} does not exist (#{e.class.name})", id: :process)
+      end
+
+      def alive?
+        @pid && !exited?
+      end
+
+      def exited?
+        return false unless @pid
+
+        WebDriver.logger.debug("Checking if #{@pid} is exited:", id: :process)
+        _, @status = waitpid2(@pid, Process::WNOHANG | Process::WUNTRACED) if @status.nil?
+        return false if @status.nil?
+
+        exit_code = @status.exitstatus || @status.termsig
+        WebDriver.logger.debug("  -> exit code is #{exit_code.inspect}", id: :process)
+
+        !!exit_code
+      rescue Errno::ECHILD, Errno::ESRCH
+        WebDriver.logger.debug("  -> process: #{@pid} already finished", id: :process)
+        true
+      end
+
+      def poll_for_exit(timeout)
+        WebDriver.logger.debug("Polling #{timeout} seconds for exit of #{@pid}", id: :process)
+
+        end_time = Time.now + timeout
+        sleep POLL_INTERVAL until exited? || Time.now > end_time
+
+        raise TimeoutError, "  ->  #{@pid} still alive after #{timeout} seconds" unless exited?
+      end
+
+      def wait
+        return if exited?
+
+        _, @status = waitpid2(@pid)
+      end
+
+      private
+
+      def terminate_and_wait_else_kill(timeout)
+        WebDriver.logger.debug("Sending TERM to process: #{@pid}", id: :process)
+        terminate(@pid)
+        poll_for_exit(timeout)
+
+        WebDriver.logger.debug("  -> stopped #{@pid}", id: :process)
+      rescue TimeoutError, Errno::EINVAL
+        WebDriver.logger.debug("    -> sending KILL to process: #{@pid}", id: :process)
+        kill(@pid)
+        wait
+        WebDriver.logger.debug("      -> killed #{@pid}", id: :process)
+      end
+
+      def terminate(pid)
+        Process.kill(SIGTERM, pid)
+      rescue Errno::ECHILD, Errno::ESRCH
+        # Process does not exist, nothing to terminate
+      end
+
+      def kill(pid)
+        Process.kill(SIGKILL, pid)
+      rescue Errno::ECHILD, Errno::ESRCH
+        # Process does not exist, nothing to kill
+      end
+
+      def waitpid2(pid, flags = 0)
+        Process.waitpid2(pid, flags)
+      end
+    end # ChildProcess
+  end # WebDriver
+end # Selenium
diff -pruN 4.4.0-1/lib/selenium/webdriver/common/driver.rb 4.38.0-1/lib/selenium/webdriver/common/driver.rb
--- 4.4.0-1/lib/selenium/webdriver/common/driver.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/common/driver.rb	2025-11-02 08:23:03.000000000 +0000
@@ -43,7 +43,7 @@ module Selenium
 
         def for(browser, opts = {})
           case browser
-          when :chrome
+          when :chrome, :chrome_headless_shell
             Chrome::Driver.new(**opts)
           when :internet_explorer, :ie
             IE::Driver.new(**opts)
@@ -51,7 +51,7 @@ module Selenium
             Safari::Driver.new(**opts)
           when :firefox, :ff
             Firefox::Driver.new(**opts)
-          when :edge
+          when :edge, :microsoftedge, :msedge
             Edge::Driver.new(**opts)
           when :remote
             Remote::Driver.new(**opts)
@@ -68,12 +68,11 @@ module Selenium
       # @api private
       #
 
-      def initialize(bridge: nil, listener: nil, **opts)
-        @service = nil
+      def initialize(bridge: nil, listener: nil, **)
         @devtools = nil
-        bridge ||= create_bridge(**opts)
-        add_extensions(bridge.browser)
+        bridge ||= create_bridge(**)
         @bridge = listener ? Support::EventFiringBridge.new(bridge, listener) : bridge
+        add_extensions(@bridge.browser)
       end
 
       def inspect
@@ -101,6 +100,15 @@ module Selenium
       end
 
       #
+      # @return [Script]
+      # @see Script
+      #
+
+      def script
+        @script ||= WebDriver::Script.new(bridge)
+      end
+
+      #
       # @return [TargetLocator]
       # @see TargetLocator
       #
@@ -123,16 +131,8 @@ module Selenium
       # @see ActionBuilder
       #
 
-      def action(**opts)
-        bridge.action(**opts)
-      end
-
-      def mouse
-        bridge.mouse
-      end
-
-      def keyboard
-        bridge.keyboard
+      def action(**)
+        bridge.action(**)
       end
 
       #
@@ -180,8 +180,8 @@ module Selenium
       def quit
         bridge.quit
       ensure
-        @service&.stop
-        @devtools&.close
+        @service_manager&.stop
+        @devtools&.each_value(&:close)
       end
 
       #
@@ -189,7 +189,7 @@ module Selenium
       #
 
       def close
-        bridge.close
+        bridge&.close
       end
 
       #
@@ -225,8 +225,8 @@ module Selenium
       #   The value returned from the script.
       #
 
-      def execute_script(script, *args)
-        bridge.execute_script(script, *args)
+      def execute_script(script, *)
+        bridge.execute_script(script, *)
       end
 
       # Execute an asynchronous piece of JavaScript in the context of the
@@ -244,8 +244,8 @@ module Selenium
       # @return [WebDriver::Element,Integer,Float,Boolean,NilClass,String,Array]
       #
 
-      def execute_async_script(script, *args)
-        bridge.execute_async_script(script, *args)
+      def execute_async_script(script, *)
+        bridge.execute_async_script(script, *)
       end
 
       #
@@ -257,25 +257,28 @@ module Selenium
         bridge.add_virtual_authenticator(options)
       end
 
-      #-------------------------------- sugar  --------------------------------
-
       #
-      #   driver.first(id: 'foo')
+      # @return [Network]
+      # @see Network
       #
 
-      alias_method :first, :find_element
+      def network
+        @network ||= WebDriver::Network.new(bridge)
+      end
+
+      #-------------------------------- sugar  --------------------------------
 
       #
-      #   driver.all(class: 'bar') #=> [#<WebDriver::Element:0x1011c3b88, ...]
+      #   driver.first(id: 'foo')
       #
 
-      alias_method :all, :find_elements
+      alias first find_element
 
       #
-      #   driver.script('function() { ... };')
+      #   driver.all(class: 'bar') #=> [#<WebDriver::Element:0x1011c3b88, ...]
       #
 
-      alias_method :script, :execute_script
+      alias all find_elements
 
       # Get the first element matching the given selector. If given a
       # String or Symbol, it will be used as the id of the element.
@@ -296,7 +299,7 @@ module Selenium
       end
 
       def browser
-        bridge&.browser
+        bridge.browser
       end
 
       def capabilities
@@ -316,30 +319,16 @@ module Selenium
 
       attr_reader :bridge
 
-      def create_bridge(capabilities: nil, options: nil, url: nil, service: nil, http_client: nil)
-        Remote::Bridge.new(http_client: http_client,
-                           url: url || service_url(service)).tap do |bridge|
-          generated_caps = options ? options.as_json : generate_capabilities(capabilities)
-          bridge.create_session(generated_caps)
+      def create_bridge(caps:, url:, http_client: nil)
+        klass = caps['webSocketUrl'] ? Remote::BiDiBridge : Remote::Bridge
+        klass.new(http_client: http_client, url: url).tap do |bridge|
+          bridge.create_session(caps)
         end
       end
 
-      def generate_capabilities(capabilities)
-        Array(capabilities).map { |cap|
-          if cap.is_a? Symbol
-            cap = Remote::Capabilities.send(cap)
-          elsif !cap.respond_to? :as_json
-            msg = ":capabilities parameter only accepts objects responding to #as_json which #{cap.class} does not"
-            raise ArgumentError, msg
-          end
-          cap.as_json
-        }.inject(:merge) || Remote::Capabilities.send(browser || :new)
-      end
-
       def service_url(service)
-        service ||= Service.send(browser)
-        @service = service.launch
-        @service.uri
+        @service_manager = service.launch
+        @service_manager.uri
       end
 
       def screenshot
@@ -348,12 +337,14 @@ module Selenium
 
       def add_extensions(browser)
         extensions = case browser
-                     when :chrome, :msedge
-                       Chrome::Driver::EXTENSIONS
+                     when :chrome, :chrome_headless_shell, :msedge, :microsoftedge
+                       Chromium::Driver::EXTENSIONS
                      when :firefox
                        Firefox::Driver::EXTENSIONS
                      when :safari, :safari_technology_preview
                        Safari::Driver::EXTENSIONS
+                     when :ie, :internet_explorer
+                       IE::Driver::EXTENSIONS
                      else
                        []
                      end
diff -pruN 4.4.0-1/lib/selenium/webdriver/common/driver_extensions/downloads_files.rb 4.38.0-1/lib/selenium/webdriver/common/driver_extensions/downloads_files.rb
--- 4.4.0-1/lib/selenium/webdriver/common/driver_extensions/downloads_files.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/common/driver_extensions/downloads_files.rb	2025-11-02 08:23:03.000000000 +0000
@@ -21,7 +21,6 @@ module Selenium
   module WebDriver
     module DriverExtensions
       module DownloadsFiles
-
         #
         # Sets download path for Chromium.
         #
@@ -38,7 +37,6 @@ module Selenium
           }
           @bridge.send_command(params)
         end
-
       end # DownloadsFiles
     end # DriverExtensions
   end # WebDriver
diff -pruN 4.4.0-1/lib/selenium/webdriver/common/driver_extensions/full_page_screenshot.rb 4.38.0-1/lib/selenium/webdriver/common/driver_extensions/full_page_screenshot.rb
--- 4.4.0-1/lib/selenium/webdriver/common/driver_extensions/full_page_screenshot.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/common/driver_extensions/full_page_screenshot.rb	2025-11-02 08:23:03.000000000 +0000
@@ -36,7 +36,6 @@ module Selenium
         def full_screenshot
           @bridge.full_screenshot
         end
-
       end # FullPageScreenshot
     end # DriverExtensions
   end # WebDriver
diff -pruN 4.4.0-1/lib/selenium/webdriver/common/driver_extensions/has_addons.rb 4.38.0-1/lib/selenium/webdriver/common/driver_extensions/has_addons.rb
--- 4.4.0-1/lib/selenium/webdriver/common/driver_extensions/has_addons.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/common/driver_extensions/has_addons.rb	2025-11-02 08:23:03.000000000 +0000
@@ -21,7 +21,6 @@ module Selenium
   module WebDriver
     module DriverExtensions
       module HasAddons
-
         #
         # Installs addon.
         #
@@ -43,7 +42,6 @@ module Selenium
         def uninstall_addon(id)
           @bridge.uninstall_addon(id)
         end
-
       end # HasAddons
     end # DriverExtensions
   end # WebDriver
diff -pruN 4.4.0-1/lib/selenium/webdriver/common/driver_extensions/has_apple_permissions.rb 4.38.0-1/lib/selenium/webdriver/common/driver_extensions/has_apple_permissions.rb
--- 4.4.0-1/lib/selenium/webdriver/common/driver_extensions/has_apple_permissions.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/common/driver_extensions/has_apple_permissions.rb	2025-11-02 08:23:03.000000000 +0000
@@ -21,7 +21,6 @@ module Selenium
   module WebDriver
     module DriverExtensions
       module HasApplePermissions
-
         #
         # Returns permissions.
         #
@@ -44,7 +43,6 @@ module Selenium
         def permissions=(permissions)
           @bridge.permissions = permissions
         end
-
       end # HasPermissions
     end # DriverExtensions
   end # WebDriver
diff -pruN 4.4.0-1/lib/selenium/webdriver/common/driver_extensions/has_authentication.rb 4.38.0-1/lib/selenium/webdriver/common/driver_extensions/has_authentication.rb
--- 4.4.0-1/lib/selenium/webdriver/common/driver_extensions/has_authentication.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/common/driver_extensions/has_authentication.rb	2025-11-02 08:23:03.000000000 +0000
@@ -21,7 +21,6 @@ module Selenium
   module WebDriver
     module DriverExtensions
       module HasAuthentication
-
         #
         # Registers basic authentication handler which is automatically
         # used whenever browser gets an authentication required response.
@@ -82,7 +81,6 @@ module Selenium
             )
           end
         end
-
       end # HasAuthentication
     end # DriverExtensions
   end # WebDriver
diff -pruN 4.4.0-1/lib/selenium/webdriver/common/driver_extensions/has_bidi.rb 4.38.0-1/lib/selenium/webdriver/common/driver_extensions/has_bidi.rb
--- 4.4.0-1/lib/selenium/webdriver/common/driver_extensions/has_bidi.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/common/driver_extensions/has_bidi.rb	2025-11-02 08:23:03.000000000 +0000
@@ -21,7 +21,6 @@ module Selenium
   module WebDriver
     module DriverExtensions
       module HasBiDi
-
         #
         # Retrieves WebDriver BiDi connection.
         #
@@ -29,9 +28,8 @@ module Selenium
         #
 
         def bidi
-          @bidi ||= Selenium::WebDriver::BiDi.new(url: capabilities[:web_socket_url])
+          @bridge.bidi
         end
-
       end # HasBiDi
     end # DriverExtensions
   end # WebDriver
diff -pruN 4.4.0-1/lib/selenium/webdriver/common/driver_extensions/has_casting.rb 4.38.0-1/lib/selenium/webdriver/common/driver_extensions/has_casting.rb
--- 4.4.0-1/lib/selenium/webdriver/common/driver_extensions/has_casting.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/common/driver_extensions/has_casting.rb	2025-11-02 08:23:03.000000000 +0000
@@ -21,7 +21,6 @@ module Selenium
   module WebDriver
     module DriverExtensions
       module HasCasting
-
         #
         # What devices ("sinks") are available to be cast to.
         #
diff -pruN 4.4.0-1/lib/selenium/webdriver/common/driver_extensions/has_cdp.rb 4.38.0-1/lib/selenium/webdriver/common/driver_extensions/has_cdp.rb
--- 4.4.0-1/lib/selenium/webdriver/common/driver_extensions/has_cdp.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/common/driver_extensions/has_cdp.rb	2025-11-02 08:23:03.000000000 +0000
@@ -21,7 +21,6 @@ module Selenium
   module WebDriver
     module DriverExtensions
       module HasCDP
-
         #
         # Returns network conditions.
         #
@@ -31,7 +30,6 @@ module Selenium
         def execute_cdp(cmd, **params)
           @bridge.send_command(cmd: cmd, params: params)
         end
-
       end # HasCDP
     end # DriverExtensions
   end # WebDriver
diff -pruN 4.4.0-1/lib/selenium/webdriver/common/driver_extensions/has_context.rb 4.38.0-1/lib/selenium/webdriver/common/driver_extensions/has_context.rb
--- 4.4.0-1/lib/selenium/webdriver/common/driver_extensions/has_context.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/common/driver_extensions/has_context.rb	2025-11-02 08:23:03.000000000 +0000
@@ -21,7 +21,6 @@ module Selenium
   module WebDriver
     module DriverExtensions
       module HasContext
-
         #
         # Sets the context that Selenium commands are running in using
         #         a `with` statement. The state of the context on the server is
@@ -37,7 +36,6 @@ module Selenium
         def context
           @bridge.context
         end
-
       end # HasContext
     end # DriverExtensions
   end # WebDriver
diff -pruN 4.4.0-1/lib/selenium/webdriver/common/driver_extensions/has_debugger.rb 4.38.0-1/lib/selenium/webdriver/common/driver_extensions/has_debugger.rb
--- 4.4.0-1/lib/selenium/webdriver/common/driver_extensions/has_debugger.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/common/driver_extensions/has_debugger.rb	2025-11-02 08:23:03.000000000 +0000
@@ -21,7 +21,6 @@ module Selenium
   module WebDriver
     module DriverExtensions
       module HasDebugger
-
         #
         # Attaches debugger to session.
         #
@@ -35,7 +34,6 @@ module Selenium
         def attach_debugger
           @bridge.attach_debugger
         end
-
       end # HasDebugger
     end # DriverExtensions
   end # WebDriver
diff -pruN 4.4.0-1/lib/selenium/webdriver/common/driver_extensions/has_devtools.rb 4.38.0-1/lib/selenium/webdriver/common/driver_extensions/has_devtools.rb
--- 4.4.0-1/lib/selenium/webdriver/common/driver_extensions/has_devtools.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/common/driver_extensions/has_devtools.rb	2025-11-02 08:23:03.000000000 +0000
@@ -21,22 +21,21 @@ module Selenium
   module WebDriver
     module DriverExtensions
       module HasDevTools
-
         #
         # Retrieves connection to DevTools.
         #
         # @return [DevTools]
         #
 
-        def devtools
-          @devtools ||= begin
+        def devtools(target_type: 'page')
+          @devtools ||= {}
+          @devtools[target_type] ||= begin
             require 'selenium/devtools'
             Selenium::DevTools.version ||= devtools_version
             Selenium::DevTools.load_version
-            Selenium::WebDriver::DevTools.new(url: devtools_url)
+            Selenium::WebDriver::DevTools.new(url: devtools_url, target_type: target_type)
           end
         end
-
       end # HasDevTools
     end # DriverExtensions
   end # WebDriver
diff -pruN 4.4.0-1/lib/selenium/webdriver/common/driver_extensions/has_fedcm_dialog.rb 4.38.0-1/lib/selenium/webdriver/common/driver_extensions/has_fedcm_dialog.rb
--- 4.4.0-1/lib/selenium/webdriver/common/driver_extensions/has_fedcm_dialog.rb	1970-01-01 00:00:00.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/common/driver_extensions/has_fedcm_dialog.rb	2025-11-02 08:23:03.000000000 +0000
@@ -0,0 +1,55 @@
+# frozen_string_literal: true
+
+# Licensed to the Software Freedom Conservancy (SFC) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The SFC licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+module Selenium
+  module WebDriver
+    module DriverExtensions
+      module HasFedCmDialog
+        # Disables the promise rejection delay for FedCm.
+        #
+        # FedCm by default delays promise resolution in failure cases for privacy reasons.
+        # This method allows turning it off to let tests run faster where this is not relevant.
+        def enable_fedcm_delay=(enable)
+          @bridge.fedcm_delay(enable)
+        end
+
+        # Resets the FedCm dialog cooldown.
+        #
+        # If a user agent triggers a cooldown when the account chooser is dismissed,
+        # this method resets that cooldown so that the dialog can be triggered again immediately.
+        def reset_fedcm_cooldown
+          @bridge.reset_fedcm_cooldown
+        end
+
+        def fedcm_dialog
+          @fedcm_dialog ||= FedCM::Dialog.new(@bridge)
+        end
+
+        def wait_for_fedcm_dialog(timeout: 5, interval: 0.2, message: nil, ignore: nil)
+          wait = Wait.new(timeout: timeout, interval: interval, message: message, ignore: ignore)
+          wait.until do
+            fedcm_dialog if fedcm_dialog.type
+          rescue Error::NoSuchAlertError
+            nil
+          end
+        end
+      end # HasFedCmDialog
+    end # DriverExtensions
+  end # WebDriver
+end # Selenium
diff -pruN 4.4.0-1/lib/selenium/webdriver/common/driver_extensions/has_file_downloads.rb 4.38.0-1/lib/selenium/webdriver/common/driver_extensions/has_file_downloads.rb
--- 4.4.0-1/lib/selenium/webdriver/common/driver_extensions/has_file_downloads.rb	1970-01-01 00:00:00.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/common/driver_extensions/has_file_downloads.rb	2025-11-02 08:23:03.000000000 +0000
@@ -0,0 +1,71 @@
+# frozen_string_literal: true
+
+# Licensed to the Software Freedom Conservancy (SFC) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The SFC licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+module Selenium
+  module WebDriver
+    module DriverExtensions
+      module HasFileDownloads
+        def downloadable_files
+          verify_enabled
+
+          @bridge.downloadable_files['names']
+        end
+
+        def download_file(file_name, target_directory)
+          verify_enabled
+
+          response = @bridge.download_file(file_name)
+          contents = response['contents']
+
+          File.open("#{file_name}.zip", 'wb') { |f| f << Base64.decode64(contents) }
+          target_directory += '/' unless target_directory.end_with?('/')
+          FileUtils.mkdir_p(target_directory)
+
+          begin
+            Zip::File.open("#{file_name}.zip") do |zip|
+              zip.each do |entry|
+                if Zipper::RUBYZIP_V3
+                  zip.extract(entry, file_name, destination_directory: target_directory)
+                else
+                  zip.extract(entry, "#{target_directory}#{file_name}")
+                end
+              end
+            end
+          ensure
+            FileUtils.rm_f("#{file_name}.zip")
+          end
+        end
+
+        def delete_downloadable_files
+          verify_enabled
+
+          @bridge.delete_downloadable_files
+        end
+
+        private
+
+        def verify_enabled
+          return if capabilities['se:downloadsEnabled']
+
+          raise Error::WebDriverError, 'You must enable downloads in order to work with downloadable files.'
+        end
+      end # HasFileDownloads
+    end # DriverExtensions
+  end # WebDriver
+end # Selenium
diff -pruN 4.4.0-1/lib/selenium/webdriver/common/driver_extensions/has_launching.rb 4.38.0-1/lib/selenium/webdriver/common/driver_extensions/has_launching.rb
--- 4.4.0-1/lib/selenium/webdriver/common/driver_extensions/has_launching.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/common/driver_extensions/has_launching.rb	2025-11-02 08:23:03.000000000 +0000
@@ -21,7 +21,6 @@ module Selenium
   module WebDriver
     module DriverExtensions
       module HasLaunching
-
         #
         # Launches Chromium app specified by id.
         #
@@ -31,7 +30,6 @@ module Selenium
         def launch_app(id)
           @bridge.launch_app(id)
         end
-
       end # HasLaunching
     end # DriverExtensions
   end # WebDriver
diff -pruN 4.4.0-1/lib/selenium/webdriver/common/driver_extensions/has_location.rb 4.38.0-1/lib/selenium/webdriver/common/driver_extensions/has_location.rb
--- 4.4.0-1/lib/selenium/webdriver/common/driver_extensions/has_location.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/common/driver_extensions/has_location.rb	1970-01-01 00:00:00.000000000 +0000
@@ -1,37 +0,0 @@
-# frozen_string_literal: true
-
-# Licensed to the Software Freedom Conservancy (SFC) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The SFC licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#   http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License.
-
-# TODO: Deprecated; Delete after 4.0 release
-module Selenium
-  module WebDriver
-    module DriverExtensions
-      module HasLocation
-        def location
-          raise Error::UnsupportedOperationError, 'The W3C standard does not currently support getting location'
-        end
-
-        def location=(*)
-          raise Error::UnsupportedOperationError, 'The W3C standard does not currently support setting location'
-        end
-        alias_method :set_location, :location
-
-      end # HasLocation
-    end # DriverExtensions
-  end # WebDriver
-end # Selenium
diff -pruN 4.4.0-1/lib/selenium/webdriver/common/driver_extensions/has_log_events.rb 4.38.0-1/lib/selenium/webdriver/common/driver_extensions/has_log_events.rb
--- 4.4.0-1/lib/selenium/webdriver/common/driver_extensions/has_log_events.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/common/driver_extensions/has_log_events.rb	2025-11-02 08:23:03.000000000 +0000
@@ -57,6 +57,13 @@ module Selenium
         #
 
         def on_log_event(kind, &block)
+          if browser == :firefox
+            WebDriver.logger.deprecate(
+              'Driver#on_log_event on Firefox',
+              'the script.add_console_message_handler or the script.add_javascript_error_handler methods',
+              id: :on_log_event
+            )
+          end
           raise Error::WebDriverError, "Don't know how to handle #{kind} events" unless KINDS.include?(kind)
 
           enabled = log_listeners[kind].any?
@@ -64,7 +71,7 @@ module Selenium
           return if enabled
 
           devtools.runtime.enable
-          __send__("log_#{kind}_events")
+          __send__(:"log_#{kind}_events")
         end
 
         private
@@ -137,7 +144,6 @@ module Selenium
         def mutation_listener
           @mutation_listener ||= read_atom(:mutationListener)
         end
-
       end # HasLogEvents
     end # DriverExtensions
   end # WebDriver
diff -pruN 4.4.0-1/lib/selenium/webdriver/common/driver_extensions/has_network_conditions.rb 4.38.0-1/lib/selenium/webdriver/common/driver_extensions/has_network_conditions.rb
--- 4.4.0-1/lib/selenium/webdriver/common/driver_extensions/has_network_conditions.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/common/driver_extensions/has_network_conditions.rb	2025-11-02 08:23:03.000000000 +0000
@@ -21,7 +21,6 @@ module Selenium
   module WebDriver
     module DriverExtensions
       module HasNetworkConditions
-
         #
         # Returns network conditions.
         #
@@ -61,7 +60,6 @@ module Selenium
         def delete_network_conditions
           @bridge.delete_network_conditions
         end
-
       end # HasNetworkConditions
     end # DriverExtensions
   end # WebDriver
diff -pruN 4.4.0-1/lib/selenium/webdriver/common/driver_extensions/has_network_connection.rb 4.38.0-1/lib/selenium/webdriver/common/driver_extensions/has_network_connection.rb
--- 4.4.0-1/lib/selenium/webdriver/common/driver_extensions/has_network_connection.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/common/driver_extensions/has_network_connection.rb	1970-01-01 00:00:00.000000000 +0000
@@ -1,37 +0,0 @@
-# frozen_string_literal: true
-
-# Licensed to the Software Freedom Conservancy (SFC) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The SFC licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#   http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License.
-
-# TODO: Deprecated; Delete after 4.0 release
-module Selenium
-  module WebDriver
-    module DriverExtensions
-      module HasNetworkConnection
-        def network_connection_type
-          raise Error::UnsupportedOperationError,
-                'The W3C standard does not currently support getting network connection'
-        end
-
-        def network_connection_type=(*)
-          raise Error::UnsupportedOperationError,
-                'The W3C standard does not currently support setting network connection'
-        end
-      end # HasNetworkConnection
-    end # DriverExtensions
-  end # WebDriver
-end # Selenium
diff -pruN 4.4.0-1/lib/selenium/webdriver/common/driver_extensions/has_network_interception.rb 4.38.0-1/lib/selenium/webdriver/common/driver_extensions/has_network_interception.rb
--- 4.4.0-1/lib/selenium/webdriver/common/driver_extensions/has_network_interception.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/common/driver_extensions/has_network_interception.rb	2025-11-02 08:23:03.000000000 +0000
@@ -21,7 +21,6 @@ module Selenium
   module WebDriver
     module DriverExtensions
       module HasNetworkInterception
-
         #
         # Intercepts requests coming from browser allowing
         # to either pass them through like proxy or provide
@@ -61,10 +60,16 @@ module Selenium
         #
 
         def intercept(&block)
+          if browser == :firefox
+            WebDriver.logger.deprecate(
+              'Driver#intercept on Firefox',
+              'the new bidi.network.add_intercept method',
+              id: :intercept
+            )
+          end
           @interceptor ||= DevTools::NetworkInterceptor.new(devtools)
           @interceptor.intercept(&block)
         end
-
       end # HasNetworkInterception
     end # DriverExtensions
   end # WebDriver
diff -pruN 4.4.0-1/lib/selenium/webdriver/common/driver_extensions/has_permissions.rb 4.38.0-1/lib/selenium/webdriver/common/driver_extensions/has_permissions.rb
--- 4.4.0-1/lib/selenium/webdriver/common/driver_extensions/has_permissions.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/common/driver_extensions/has_permissions.rb	2025-11-02 08:23:03.000000000 +0000
@@ -21,7 +21,6 @@ module Selenium
   module WebDriver
     module DriverExtensions
       module HasPermissions
-
         #
         # Set one permission.
         #
@@ -44,7 +43,6 @@ module Selenium
             @bridge.set_permission(key, value)
           end
         end
-
       end # HasPermissions
     end # DriverExtensions
   end # WebDriver
diff -pruN 4.4.0-1/lib/selenium/webdriver/common/driver_extensions/has_pinned_scripts.rb 4.38.0-1/lib/selenium/webdriver/common/driver_extensions/has_pinned_scripts.rb
--- 4.4.0-1/lib/selenium/webdriver/common/driver_extensions/has_pinned_scripts.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/common/driver_extensions/has_pinned_scripts.rb	2025-11-02 08:23:03.000000000 +0000
@@ -21,7 +21,6 @@ module Selenium
   module WebDriver
     module DriverExtensions
       module HasPinnedScripts
-
         #
         # Returns the list of all pinned scripts.
         #
@@ -70,7 +69,6 @@ module Selenium
           devtools.page.remove_script_to_evaluate_on_new_document(identifier: script.devtools_identifier)
           pinned_scripts.delete(script)
         end
-
       end # HasPinnedScripts
     end # DriverExtensions
   end # WebDriver
diff -pruN 4.4.0-1/lib/selenium/webdriver/common/driver_extensions/has_web_storage.rb 4.38.0-1/lib/selenium/webdriver/common/driver_extensions/has_web_storage.rb
--- 4.4.0-1/lib/selenium/webdriver/common/driver_extensions/has_web_storage.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/common/driver_extensions/has_web_storage.rb	1970-01-01 00:00:00.000000000 +0000
@@ -1,38 +0,0 @@
-# frozen_string_literal: true
-
-# Licensed to the Software Freedom Conservancy (SFC) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The SFC licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#   http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License.
-
-module Selenium
-  module WebDriver
-    #
-    # @api private
-    #
-
-    module DriverExtensions
-      module HasWebStorage
-        def local_storage
-          HTML5::LocalStorage.new @bridge
-        end
-
-        def session_storage
-          HTML5::SessionStorage.new @bridge
-        end
-      end # HasWebStorage
-    end # DriverExtensions
-  end # WebDriver
-end # Selenium
diff -pruN 4.4.0-1/lib/selenium/webdriver/common/driver_finder.rb 4.38.0-1/lib/selenium/webdriver/common/driver_finder.rb
--- 4.4.0-1/lib/selenium/webdriver/common/driver_finder.rb	1970-01-01 00:00:00.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/common/driver_finder.rb	2025-11-02 08:23:03.000000000 +0000
@@ -0,0 +1,97 @@
+# frozen_string_literal: true
+
+# Licensed to the Software Freedom Conservancy (SFC) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The SFC licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+module Selenium
+  module WebDriver
+    class DriverFinder
+      def self.path(options, service_class)
+        WebDriver.logger.deprecate('DriverFinder.path(options, service_class)',
+                                   'DriverFinder.new(options, service).driver_path')
+        new(options, service_class.new).driver_path
+      end
+
+      def initialize(options, service)
+        @options = options
+        @service = service
+      end
+
+      def browser_path
+        paths[:browser_path]
+      end
+
+      def driver_path
+        paths[:driver_path]
+      end
+
+      def browser_path?
+        !browser_path.nil? && !browser_path.empty?
+      end
+
+      private
+
+      def paths
+        @paths ||= begin
+          path = @service.class.driver_path
+          path = path.call if path.is_a?(Proc)
+          exe = @service.class::EXECUTABLE
+          if path
+            WebDriver.logger.debug("Skipping Selenium Manager; path to #{exe} specified in service class: #{path}")
+            Platform.assert_executable(path)
+            {driver_path: path}
+          else
+            output = SeleniumManager.binary_paths(*to_args)
+            formatted = {driver_path: Platform.cygwin_path(output['driver_path'], only_cygwin: true),
+                         browser_path: Platform.cygwin_path(output['browser_path'], only_cygwin: true)}
+            Platform.assert_executable(formatted[:driver_path])
+
+            browser_path = formatted[:browser_path]
+            Platform.assert_executable(browser_path)
+            if @options.respond_to?(:binary) && @options.binary.nil?
+              @options.binary = browser_path
+              @options.browser_version = nil
+            end
+
+            formatted
+          end
+        rescue StandardError => e
+          WebDriver.logger.error("Exception occurred: #{e.message}")
+          WebDriver.logger.error("Backtrace:\n\t#{e.backtrace&.join("\n\t")}")
+          raise Error::NoSuchDriverError, "Unable to obtain #{exe}"
+        end
+      end
+
+      def to_args
+        args = ['--browser', @options.browser_name]
+        if @options.browser_version
+          args << '--browser-version'
+          args << @options.browser_version
+        end
+        if @options.respond_to?(:binary) && !@options.binary.nil?
+          args << '--browser-path'
+          args << @options.binary.gsub('\\', '\\\\\\')
+        end
+        if @options.proxy
+          args << '--proxy'
+          args << (@options.proxy.ssl || @options.proxy.http)
+        end
+        args
+      end
+    end
+  end
+end
diff -pruN 4.4.0-1/lib/selenium/webdriver/common/element.rb 4.38.0-1/lib/selenium/webdriver/common/element.rb
--- 4.4.0-1/lib/selenium/webdriver/common/element.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/common/element.rb	2025-11-02 08:23:03.000000000 +0000
@@ -43,7 +43,7 @@ module Selenium
       def ==(other)
         other.is_a?(self.class) && ref == other.ref
       end
-      alias_method :eql?, :==
+      alias eql? ==
 
       def hash
         [@id, @bridge].hash
@@ -101,7 +101,7 @@ module Selenium
       # if it exists. If it does not, then the value of the attribute with the given name is returned.
       # If neither exists, null is returned.
       #
-      # The "style" attribute is converted as best can be to a text representation with a trailing semi-colon.
+      # The "style" attribute is converted as best can be to a text representation with a trailing semicolon.
       #
       # The following are deemed to be "boolean" attributes, and will return either "true" or "false":
       #
@@ -207,7 +207,7 @@ module Selenium
       def send_keys(*args)
         bridge.send_keys_to_element @id, Keys.encode(args)
       end
-      alias_method :send_key, :send_keys
+      alias send_key send_keys
 
       #
       # If this element is a text entry element, this will clear the value. Has no effect on other
@@ -275,7 +275,7 @@ module Selenium
       def css_value(prop)
         bridge.element_value_of_css_property @id, prop
       end
-      alias_method :style, :css_value
+      alias style css_value
 
       #
       # Get the location of this element.
@@ -333,18 +333,18 @@ module Selenium
       #   element.first(id: 'foo')
       #
 
-      alias_method :first, :find_element
+      alias first find_element
 
       #
       #   element.all(class: 'bar')
       #
 
-      alias_method :all, :find_elements
+      alias all find_elements
 
       #
       #   element['class'] or element[:class] #=> "someclass"
       #
-      alias_method :[], :attribute
+      alias [] attribute
 
       #
       # @api private
diff -pruN 4.4.0-1/lib/selenium/webdriver/common/error.rb 4.38.0-1/lib/selenium/webdriver/common/error.rb
--- 4.4.0-1/lib/selenium/webdriver/common/error.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/common/error.rb	2025-11-02 08:23:03.000000000 +0000
@@ -20,7 +20,6 @@
 module Selenium
   module WebDriver
     module Error
-
       #
       # Returns exception from its string representation.
       # @param [String, nil] error
@@ -30,12 +29,33 @@ module Selenium
         return if error.nil?
 
         klass_name = error.split.map(&:capitalize).join.sub(/Error$/, '')
-        const_get("#{klass_name}Error", false)
+        const_get(:"#{klass_name}Error", false)
       rescue NameError
         WebDriverError
       end
 
-      class WebDriverError < StandardError; end
+      SUPPORT_MSG = 'For documentation on this error, please visit:'
+      ERROR_URL = 'https://www.selenium.dev/documentation/webdriver/troubleshooting/errors'
+
+      URLS = {
+        NoSuchElementError: "#{ERROR_URL}#nosuchelementexception",
+        StaleElementReferenceError: "#{ERROR_URL}#staleelementreferenceexception",
+        InvalidSelectorError: "#{ERROR_URL}#invalidselectorexception",
+        NoSuchDriverError: "#{ERROR_URL}/driver_location"
+      }.freeze
+
+      class WebDriverError < StandardError
+        def initialize(msg = '')
+          # Remove this conditional when all the error pages have been documented
+          super(URLS[class_name] ? "#{msg}; #{SUPPORT_MSG} #{URLS[class_name]}" : msg)
+        end
+
+        # steep:ignore:start
+        def class_name
+          self.class.name.split('::')&.last&.to_sym
+        end
+        # steep:ignore:end
+      end
 
       #
       # An element could not be located on the page using the given search parameters.
@@ -214,6 +234,11 @@ module Selenium
 
       class UnsupportedOperationError < WebDriverError; end
 
+      #
+      # Indicates that driver was not specified and could not be located.
+      #
+
+      class NoSuchDriverError < WebDriverError; end
     end # Error
   end # WebDriver
 end # Selenium
diff -pruN 4.4.0-1/lib/selenium/webdriver/common/fedcm/account.rb 4.38.0-1/lib/selenium/webdriver/common/fedcm/account.rb
--- 4.4.0-1/lib/selenium/webdriver/common/fedcm/account.rb	1970-01-01 00:00:00.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/common/fedcm/account.rb	2025-11-02 08:23:03.000000000 +0000
@@ -0,0 +1,49 @@
+# frozen_string_literal: true
+
+# Licensed to the Software Freedom Conservancy (SFC) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The SFC licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+module Selenium
+  module WebDriver
+    module FedCM
+      # Represents an account displayed in a FedCm account list.
+      # See: https://w3c-fedid.github.io/FedCM/#dictdef-identityprovideraccount
+      #      https://w3c-fedid.github.io/FedCM/#webdriver-accountlist
+      class Account
+        LOGIN_STATE_SIGNIN = 'SignIn'
+        LOGIN_STATE_SIGNUP = 'SignUp'
+
+        attr_reader :account_id, :email, :name, :given_name, :picture_url,
+                    :idp_config_url, :login_state, :terms_of_service_url, :privacy_policy_url
+
+        # steep:ignore:start
+        def initialize(**args)
+          @account_id = args['accountId']
+          @email = args['email']
+          @name = args['name']
+          @given_name = args['givenName']
+          @picture_url = args['pictureUrl']
+          @idp_config_url = args['idpConfigUrl']
+          @login_state = args['loginState']
+          @terms_of_service_url = args['termsOfServiceUrl']
+          @privacy_policy_url = args['privacyPolicyUrl']
+        end
+        # steep:ignore:end
+      end # Account
+    end # FedCM
+  end # WebDriver
+end # Selenium
diff -pruN 4.4.0-1/lib/selenium/webdriver/common/fedcm/dialog.rb 4.38.0-1/lib/selenium/webdriver/common/fedcm/dialog.rb
--- 4.4.0-1/lib/selenium/webdriver/common/fedcm/dialog.rb	1970-01-01 00:00:00.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/common/fedcm/dialog.rb	2025-11-02 08:23:03.000000000 +0000
@@ -0,0 +1,74 @@
+# frozen_string_literal: true
+
+# Licensed to the Software Freedom Conservancy (SFC) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The SFC licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+module Selenium
+  module WebDriver
+    module FedCM
+      class Dialog
+        def initialize(bridge)
+          @bridge = bridge
+        end
+
+        DIALOG_TYPE_ACCOUNT_LIST = 'AccountChooser'
+        DIALOG_TYPE_AUTO_REAUTH = 'AutoReauthn'
+
+        # Closes the dialog as if the user had clicked X.
+        def click
+          @bridge.click_fedcm_dialog_button
+        end
+
+        # Closes the dialog as if the user had clicked X.
+        def cancel
+          @bridge.cancel_fedcm_dialog
+        end
+
+        # Selects an account as if the user had clicked on it.
+        #
+        # @param [Integer] index The index of the account to select from the list returned by get_accounts.
+        def select_account(index)
+          @bridge.select_fedcm_account index
+        end
+
+        # Returns the type of the open dialog.
+        #
+        # One of DIALOG_TYPE_ACCOUNT_LIST and DIALOG_TYPE_AUTO_REAUTH.
+        def type
+          @bridge.fedcm_dialog_type
+        end
+
+        # Returns the title of the dialog.
+        def title
+          @bridge.fedcm_title
+        end
+
+        # Returns the subtitle of the dialog or nil if none.
+        def subtitle
+          @bridge.fedcm_subtitle
+        end
+
+        # Returns the accounts shown in the account chooser.
+        #
+        # If this is an auto reauth dialog, returns the single account that is being signed in.
+        def accounts
+          @bridge.fedcm_account_list.map { |account| Account.new(**account) }
+        end
+      end # Dialog
+    end # FedCM
+  end # WebDriver
+end # Selenium
diff -pruN 4.4.0-1/lib/selenium/webdriver/common/fedcm.rb 4.38.0-1/lib/selenium/webdriver/common/fedcm.rb
--- 4.4.0-1/lib/selenium/webdriver/common/fedcm.rb	1970-01-01 00:00:00.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/common/fedcm.rb	2025-11-02 08:23:03.000000000 +0000
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+# Licensed to the Software Freedom Conservancy (SFC) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The SFC licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+module Selenium
+  module WebDriver
+    module FedCM
+      autoload :Account, 'fedcm/account'
+      autoload :Dialog, 'fedcm/dialog'
+    end # FedCM
+  end # WebDriver
+end # Selenium
diff -pruN 4.4.0-1/lib/selenium/webdriver/common/html5/local_storage.rb 4.38.0-1/lib/selenium/webdriver/common/html5/local_storage.rb
--- 4.4.0-1/lib/selenium/webdriver/common/html5/local_storage.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/common/html5/local_storage.rb	1970-01-01 00:00:00.000000000 +0000
@@ -1,59 +0,0 @@
-# frozen_string_literal: true
-
-# Licensed to the Software Freedom Conservancy (SFC) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The SFC licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#   http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License.
-
-module Selenium
-  module WebDriver
-    module HTML5
-      class LocalStorage
-        include SharedWebStorage
-
-        #
-        # @api private
-        #
-        def initialize(bridge)
-          @bridge = bridge
-        end
-
-        def [](key)
-          @bridge.local_storage_item key
-        end
-
-        def []=(key, value)
-          @bridge.local_storage_item key, value
-        end
-
-        def delete(key)
-          @bridge.remove_local_storage_item key
-        end
-
-        def clear
-          @bridge.clear_local_storage
-        end
-
-        def size
-          @bridge.local_storage_size
-        end
-
-        def keys
-          @bridge.local_storage_keys.reverse
-        end
-      end # LocalStorage
-    end # HTML5
-  end # WebDriver
-end # Selenium
diff -pruN 4.4.0-1/lib/selenium/webdriver/common/html5/session_storage.rb 4.38.0-1/lib/selenium/webdriver/common/html5/session_storage.rb
--- 4.4.0-1/lib/selenium/webdriver/common/html5/session_storage.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/common/html5/session_storage.rb	1970-01-01 00:00:00.000000000 +0000
@@ -1,61 +0,0 @@
-# frozen_string_literal: true
-
-# Licensed to the Software Freedom Conservancy (SFC) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The SFC licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#   http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License.
-
-module Selenium
-  module WebDriver
-    module HTML5
-      class SessionStorage
-        include Enumerable
-        include SharedWebStorage
-
-        def [](key)
-          @bridge.session_storage_item key
-        end
-
-        def []=(key, value)
-          @bridge.session_storage_item key, value
-        end
-
-        def delete(key)
-          @bridge.remove_session_storage_item key
-        end
-
-        def clear
-          @bridge.clear_session_storage
-        end
-
-        def size
-          @bridge.session_storage_size
-        end
-
-        def keys
-          @bridge.session_storage_keys.reverse
-        end
-
-        #
-        # @api private
-        #
-
-        def initialize(bridge)
-          @bridge = bridge
-        end
-      end # SessionStorage
-    end # HTML5
-  end # WebDriver
-end # Selenium
diff -pruN 4.4.0-1/lib/selenium/webdriver/common/html5/shared_web_storage.rb 4.38.0-1/lib/selenium/webdriver/common/html5/shared_web_storage.rb
--- 4.4.0-1/lib/selenium/webdriver/common/html5/shared_web_storage.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/common/html5/shared_web_storage.rb	1970-01-01 00:00:00.000000000 +0000
@@ -1,53 +0,0 @@
-# frozen_string_literal: true
-
-# Licensed to the Software Freedom Conservancy (SFC) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The SFC licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#   http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License.
-
-module Selenium
-  module WebDriver
-    module HTML5
-      module SharedWebStorage
-        include Enumerable
-
-        def key?(key)
-          keys.include? key
-        end
-        alias_method :member?, :key?
-        alias_method :has_key?, :key?
-
-        def fetch(key)
-          return self[key] if key? key
-          return yield(key) if block_given?
-
-          raise KeyError, "missing key #{key.inspect}"
-        end
-
-        def empty?
-          to_a.empty?
-        end
-
-        def each
-          return enum_for(:each) unless block_given?
-
-          keys.each do |k|
-            yield k, self[k]
-          end
-        end
-      end # SharedWebStorage
-    end # HTML5
-  end # WebDriver
-end # Selenium
diff -pruN 4.4.0-1/lib/selenium/webdriver/common/interactions/key_actions.rb 4.38.0-1/lib/selenium/webdriver/common/interactions/key_actions.rb
--- 4.4.0-1/lib/selenium/webdriver/common/interactions/key_actions.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/common/interactions/key_actions.rb	2025-11-02 08:23:03.000000000 +0000
@@ -44,8 +44,8 @@ module Selenium
       # @return [ActionBuilder] A self reference
       #
 
-      def key_down(*args, device: nil)
-        key_action(*args, action: :create_key_down, device: device)
+      def key_down(*, device: nil)
+        key_action(*, action: :create_key_down, device: device)
       end
 
       #
@@ -71,8 +71,8 @@ module Selenium
       # @return [ActionBuilder] A self reference
       #
 
-      def key_up(*args, device: nil)
-        key_action(*args, action: :create_key_up, device: device)
+      def key_up(*, device: nil)
+        key_action(*, action: :create_key_up, device: device)
       end
 
       #
diff -pruN 4.4.0-1/lib/selenium/webdriver/common/interactions/pointer_actions.rb 4.38.0-1/lib/selenium/webdriver/common/interactions/pointer_actions.rb
--- 4.4.0-1/lib/selenium/webdriver/common/interactions/pointer_actions.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/common/interactions/pointer_actions.rb	2025-11-02 08:23:03.000000000 +0000
@@ -46,8 +46,8 @@ module Selenium
       # @return [ActionBuilder] A self reference.
       #
 
-      def pointer_down(button = :left, device: nil, **opts)
-        button_action(button, :create_pointer_down, device: device, **opts)
+      def pointer_down(button = :left, device: nil, **)
+        button_action(button, :create_pointer_down, device: device, **)
       end
 
       #
@@ -63,8 +63,8 @@ module Selenium
       # @return [ActionBuilder] A self reference.
       #
 
-      def pointer_up(button = :left, device: nil, **opts)
-        button_action(button, :create_pointer_up, device: device, **opts)
+      def pointer_up(button = :left, device: nil, **)
+        button_action(button, :create_pointer_up, device: device, **)
       end
 
       #
@@ -91,13 +91,12 @@ module Selenium
       #   element. A negative value means coordinates to the left of the center.
       # @param [Integer] down_by Optional offset from the in-view center of the
       #   element. A negative value means coordinates to the top of the center.
-      # @param [Symbol || String] device optional name of the PointerInput device to move.
       # @return [ActionBuilder] A self reference.
       #
 
-      def move_to(element, right_by = nil, down_by = nil, device: nil, duration: default_move_duration, **opts)
-        pointer = pointer_input(device)
-        pointer.create_pointer_move(duration: duration,
+      def move_to(element, right_by = nil, down_by = nil, **opts)
+        pointer = pointer_input(opts.delete(:device))
+        pointer.create_pointer_move(duration: opts.delete(:duration) || default_move_duration,
                                     x: right_by || 0,
                                     y: down_by || 0,
                                     origin: element,
@@ -123,13 +122,13 @@ module Selenium
       # @raise [MoveTargetOutOfBoundsError] if the provided offset is outside the document's boundaries.
       #
 
-      def move_by(right_by, down_by, device: nil, duration: default_move_duration, **opts)
+      def move_by(right_by, down_by, device: nil, duration: default_move_duration, **)
         pointer = pointer_input(device)
         pointer.create_pointer_move(duration: duration,
                                     x: Integer(right_by),
                                     y: Integer(down_by),
                                     origin: Interactions::PointerMove::POINTER,
-                                    **opts)
+                                    **)
         tick(pointer)
         self
       end
@@ -151,13 +150,13 @@ module Selenium
       # @raise [MoveTargetOutOfBoundsError] if the provided x or y value is outside the document's boundaries.
       #
 
-      def move_to_location(x, y, device: nil, duration: default_move_duration, **opts)
+      def move_to_location(x, y, device: nil, duration: default_move_duration, **)
         pointer = pointer_input(device)
         pointer.create_pointer_move(duration: duration,
                                     x: Integer(x),
                                     y: Integer(y),
                                     origin: Interactions::PointerMove::VIEWPORT,
-                                    **opts)
+                                    **)
         tick(pointer)
         self
       end
@@ -337,9 +336,9 @@ module Selenium
 
       private
 
-      def button_action(button, action, device: nil, **opts)
+      def button_action(button, action, device: nil, **)
         pointer = pointer_input(device)
-        pointer.send(action, button, **opts)
+        pointer.send(action, button, **)
         tick(pointer)
         self
       end
diff -pruN 4.4.0-1/lib/selenium/webdriver/common/interactions/pointer_cancel.rb 4.38.0-1/lib/selenium/webdriver/common/interactions/pointer_cancel.rb
--- 4.4.0-1/lib/selenium/webdriver/common/interactions/pointer_cancel.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/common/interactions/pointer_cancel.rb	2025-11-02 08:23:03.000000000 +0000
@@ -28,7 +28,7 @@ module Selenium
 
       class PointerCancel < Interaction
         def initialize(source)
-          super(source)
+          super
           @type = :pointerCancel
         end
 
diff -pruN 4.4.0-1/lib/selenium/webdriver/common/interactions/pointer_input.rb 4.38.0-1/lib/selenium/webdriver/common/interactions/pointer_input.rb
--- 4.4.0-1/lib/selenium/webdriver/common/interactions/pointer_input.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/common/interactions/pointer_input.rb	2025-11-02 08:23:03.000000000 +0000
@@ -49,16 +49,16 @@ module Selenium
           KIND[pointer]
         end
 
-        def create_pointer_move(duration: 0, x: 0, y: 0, origin: nil, **opts)
-          add_action(PointerMove.new(self, duration, x, y, origin: origin, **opts))
+        def create_pointer_move(duration: 0, x: 0, y: 0, origin: nil, **)
+          add_action(PointerMove.new(self, duration, x, y, origin: origin, **))
         end
 
-        def create_pointer_down(button, **opts)
-          add_action(PointerPress.new(self, :down, button, **opts))
+        def create_pointer_down(button, **)
+          add_action(PointerPress.new(self, :down, button, **))
         end
 
-        def create_pointer_up(button, **opts)
-          add_action(PointerPress.new(self, :up, button, **opts))
+        def create_pointer_up(button, **)
+          add_action(PointerPress.new(self, :up, button, **))
         end
 
         def create_pointer_cancel
diff -pruN 4.4.0-1/lib/selenium/webdriver/common/interactions/pointer_move.rb 4.38.0-1/lib/selenium/webdriver/common/interactions/pointer_move.rb
--- 4.4.0-1/lib/selenium/webdriver/common/interactions/pointer_move.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/common/interactions/pointer_move.rb	2025-11-02 08:23:03.000000000 +0000
@@ -33,12 +33,12 @@ module Selenium
         POINTER = :pointer
         ORIGINS = [VIEWPORT, POINTER].freeze
 
-        def initialize(source, duration, x, y, element: nil, origin: nil, **opts)
+        def initialize(source, duration, x, y, **opts)
           super(source)
           @duration = duration * 1000
           @x_offset = x
           @y_offset = y
-          @origin = element || origin || :viewport
+          @origin = opts.delete(:element) || opts.delete(:origin) || :viewport
           @type = :pointerMove
           @opts = opts
         end
diff -pruN 4.4.0-1/lib/selenium/webdriver/common/interactions/scroll.rb 4.38.0-1/lib/selenium/webdriver/common/interactions/scroll.rb
--- 4.4.0-1/lib/selenium/webdriver/common/interactions/scroll.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/common/interactions/scroll.rb	2025-11-02 08:23:03.000000000 +0000
@@ -27,15 +27,17 @@ module Selenium
       #
 
       class Scroll < Interaction
-        def initialize(source:, x: 0, y: 0, delta_x: 0, delta_y: 0, origin: :viewport, duration: 0.25)
+        def initialize(source:, origin: :viewport, duration: 0.25, **opts)
           super(source)
           @type = :scroll
           @duration = duration * 1000
           @origin = origin
-          @x_offset = x
-          @y_offset = y
-          @delta_x = delta_x
-          @delta_y = delta_y
+          @x_offset = opts.delete(:x) || 0
+          @y_offset = opts.delete(:y) || 0
+          @delta_x = opts.delete(:delta_x) || 0
+          @delta_y = opts.delete(:delta_y) || 0
+
+          raise ArgumentError, "Invalid arguments: #{opts.keys}" unless opts.empty?
         end
 
         def assert_source(source)
diff -pruN 4.4.0-1/lib/selenium/webdriver/common/interactions/wheel_actions.rb 4.38.0-1/lib/selenium/webdriver/common/interactions/wheel_actions.rb
--- 4.4.0-1/lib/selenium/webdriver/common/interactions/wheel_actions.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/common/interactions/wheel_actions.rb	2025-11-02 08:23:03.000000000 +0000
@@ -38,7 +38,8 @@ module Selenium
       #    el = driver.find_element(id: "some_id")
       #    driver.action.scroll_to(element).perform
       #
-      # @param [Object] Which element to scroll into the viewport.
+      # @param [Object] element Which element to scroll into the viewport.
+      # @param [Object] device Which device to use to scroll
       # @return [Selenium::WebDriver::WheelActions] A self reference.
       def scroll_to(element, device: nil)
         scroll(origin: element, device: device)
diff -pruN 4.4.0-1/lib/selenium/webdriver/common/interactions/wheel_input.rb 4.38.0-1/lib/selenium/webdriver/common/interactions/wheel_input.rb
--- 4.4.0-1/lib/selenium/webdriver/common/interactions/wheel_input.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/common/interactions/wheel_input.rb	2025-11-02 08:23:03.000000000 +0000
@@ -28,7 +28,7 @@ module Selenium
 
       class WheelInput < InputDevice
         def initialize(name = nil)
-          super(name)
+          super
           @type = Interactions::WHEEL
         end
 
diff -pruN 4.4.0-1/lib/selenium/webdriver/common/keys.rb 4.38.0-1/lib/selenium/webdriver/common/keys.rb
--- 4.4.0-1/lib/selenium/webdriver/common/keys.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/common/keys.rb	2025-11-02 08:23:03.000000000 +0000
@@ -75,6 +75,13 @@ module Selenium
         subtract: "\ue027",
         decimal: "\ue028",
         divide: "\ue029",
+        numpad_multiply: "\ue024",
+        numpad_add: "\ue025",
+        numpad_comma: "\ue026",
+        numpad_subtract: "\ue027",
+        numpad_decimal: "\ue028",
+        numpad_divide: "\ue029",
+        numpad_enter: "\ue007",
         f1: "\ue031",
         f2: "\ue032",
         f3: "\ue033",
@@ -95,6 +102,8 @@ module Selenium
         right_control: "\ue051",
         right_alt: "\ue052",
         right_meta: "\ue053",
+        options: "\ue052",
+        function: "\ue051", # macOS Function key, same as right_control
         numpad_page_up: "\ue054",
         numpad_page_down: "\ue055",
         numpad_end: "\ue056",
diff -pruN 4.4.0-1/lib/selenium/webdriver/common/local_driver.rb 4.38.0-1/lib/selenium/webdriver/common/local_driver.rb
--- 4.4.0-1/lib/selenium/webdriver/common/local_driver.rb	1970-01-01 00:00:00.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/common/local_driver.rb	2025-11-02 08:23:03.000000000 +0000
@@ -0,0 +1,53 @@
+# frozen_string_literal: true
+
+# Licensed to the Software Freedom Conservancy (SFC) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The SFC licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+module Selenium
+  module WebDriver
+    module LocalDriver
+      def initialize_local_driver(options, service, url)
+        raise ArgumentError, "Can't initialize #{self.class} with :url" if url
+
+        service ||= Service.send(browser)
+        caps = process_options(options, service)
+        url = service_url(service)
+
+        [caps, url]
+      end
+
+      def process_options(options, service)
+        default_options = Options.send(browser)
+        options ||= default_options
+
+        unless options.is_a?(default_options.class)
+          raise ArgumentError, ":options must be an instance of #{default_options.class}"
+        end
+
+        service.executable_path ||= begin
+          finder = WebDriver::DriverFinder.new(options, service)
+          if options.respond_to?(:binary) && finder.browser_path?
+            options.binary = finder.browser_path
+            options.browser_version = nil
+          end
+          finder.driver_path
+        end
+        options.as_json
+      end
+    end
+  end
+end
diff -pruN 4.4.0-1/lib/selenium/webdriver/common/logger.rb 4.38.0-1/lib/selenium/webdriver/common/logger.rb
--- 4.4.0-1/lib/selenium/webdriver/common/logger.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/common/logger.rb	2025-11-02 08:23:03.000000000 +0000
@@ -38,19 +38,31 @@ module Selenium
 
       def_delegators :@logger,
                      :close,
-                     :debug, :debug?,
-                     :info, :info?,
+                     :debug?,
+                     :info?,
                      :warn?,
-                     :error, :error?,
+                     :error?,
                      :fatal, :fatal?,
-                     :level, :level=
+                     :level
 
       #
       # @param [String] progname Allow child projects to use Selenium's Logger pattern
       #
-      def initialize(progname = 'Selenium')
-        @logger = create_logger(progname)
-        @ignored = []
+      def initialize(progname = 'Selenium', default_level: nil, ignored: nil, allowed: nil)
+        default_level ||= $DEBUG || ENV.key?('DEBUG') ? :debug : :warn
+
+        @logger = create_logger(progname, level: default_level)
+        @ignored = Array(ignored)
+        @allowed = Array(allowed)
+        @first_warning = false
+      end
+
+      def level=(level)
+        if level == :info && @logger.level == :info
+          info(':info is now the default log level, to see additional logging, set log level to :debug')
+        end
+
+        @logger.level = level
       end
 
       #
@@ -80,27 +92,64 @@ module Selenium
       #
       # Will not log the provided ID.
       #
-      # @param [Array, Symbol] id
+      # @param [Array, Symbol] ids
       #
-      def ignore(id)
-        Array(id).each { |ignore| @ignored << ignore }
+      def ignore(*ids)
+        @ignored += Array(ids).flatten
       end
 
       #
-      # Overrides default #warn to skip ignored messages by provided id
+      # Will only log the provided ID.
+      #
+      # @param [Array, Symbol] ids
+      #
+      def allow(*ids)
+        @allowed += Array(ids).flatten
+      end
+
+      #
+      # Used to supply information of interest for debugging a problem
+      # Overrides default #debug to skip ignored messages by provided id
       #
       # @param [String] message
-      # @param [Symbol, Array<Sybmol>] id
+      # @param [Symbol, Array<Symbol>] id
       # @yield see #deprecate
       #
-      def warn(message, id: [])
-        id = Array(id)
-        return if (@ignored & id).any?
+      def debug(message, id: [], &block)
+        discard_or_log(:debug, message, id, &block)
+      end
 
-        msg = id.empty? ? message : "[#{id.map(&:inspect).join(', ')}] #{message} "
-        msg += " #{yield}" if block_given?
+      #
+      # Used to supply information of general interest
+      #
+      # @param [String] message
+      # @param [Symbol, Array<Symbol>] id
+      # @yield see #deprecate
+      #
+      def info(message, id: [], &block)
+        discard_or_log(:info, message, id, &block)
+      end
 
-        @logger.warn { msg }
+      #
+      # Used to supply information that suggests an error occurred
+      #
+      # @param [String] message
+      # @param [Symbol, Array<Symbol>] id
+      # @yield see #deprecate
+      #
+      def error(message, id: [], &block)
+        discard_or_log(:error, message, id, &block)
+      end
+
+      #
+      # Used to supply information that suggests action be taken by user
+      #
+      # @param [String] message
+      # @param [Symbol, Array<Symbol>] id
+      # @yield see #deprecate
+      #
+      def warn(message, id: [], &block)
+        discard_or_log(:warn, message, id, &block)
       end
 
       #
@@ -114,11 +163,11 @@ module Selenium
       #
       def deprecate(old, new = nil, id: [], reference: '', &block)
         id = Array(id)
-        return if @ignored.include?(:deprecations) || (@ignored & id).any?
+        return if @ignored.include?(:deprecations)
 
-        ids = id.empty? ? '' : "[#{id.map(&:inspect).join(', ')}] "
+        id << :deprecations if @allowed.include?(:deprecations)
 
-        message = +"[DEPRECATION] #{ids}#{old} is deprecated"
+        message = "[DEPRECATION] #{old} is deprecated"
         message << if new
                      ". Use #{new} instead."
                    else
@@ -126,24 +175,40 @@ module Selenium
                    end
         message << " See explanation for this deprecation: #{reference}." unless reference.empty?
 
-        warn message, &block
+        discard_or_log(:warn, message, id, &block)
       end
 
       private
 
-      def create_logger(name)
-        logger = ::Logger.new($stdout)
+      def create_logger(name, level:)
+        logger = ::Logger.new($stderr)
         logger.progname = name
-        logger.level = default_level
+        logger.level = level
         logger.formatter = proc do |severity, time, progname, msg|
-          "#{time.strftime('%F %T')} #{severity} #{progname} #{msg}\n"
+          "#{time.strftime('%F %T')} #{severity} #{progname} #{msg}\n".force_encoding('UTF-8')
         end
 
         logger
       end
 
-      def default_level
-        $DEBUG || ENV.key?('DEBUG') ? :debug : :warn
+      def discard_or_log(level, message, id)
+        id = Array(id)
+        return if @ignored.intersect?(id)
+        return if @allowed.any? && !@allowed.intersect?(id)
+
+        return if ::Logger::Severity.const_get(level.upcase) < @logger.level
+
+        unless @first_warning
+          @first_warning = true
+          info("Details on how to use and modify Selenium logger:\n", id: [:logger_info]) do
+            "https://selenium.dev/documentation/webdriver/troubleshooting/logging\n"
+          end
+        end
+
+        msg = id.empty? ? message : "[#{id.map(&:inspect).join(', ')}] #{message} "
+        msg += " #{yield}" if block_given?
+
+        @logger.send(level) { msg }
       end
     end # Logger
   end # WebDriver
diff -pruN 4.4.0-1/lib/selenium/webdriver/common/manager.rb 4.38.0-1/lib/selenium/webdriver/common/manager.rb
--- 4.4.0-1/lib/selenium/webdriver/common/manager.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/common/manager.rb	2025-11-02 08:23:03.000000000 +0000
@@ -56,7 +56,7 @@ module Selenium
         opts[:httpOnly] = http_only if http_only
 
         obj = opts.delete(:expires)
-        opts[:expiry] = seconds_from(obj).to_i if obj
+        opts[:expiry] = seconds_from(obj).to_int if obj
 
         @bridge.add_cookie opts
       end
@@ -65,7 +65,7 @@ module Selenium
       # Get the cookie with the given name
       #
       # @param [String] name the name of the cookie
-      # @return [Hash, nil] the cookie, or nil if it wasn't found.
+      # @return [Hash] the cookie, or throws a NoSuchCookieError if it wasn't found.
       #
 
       def cookie_named(name)
@@ -79,6 +79,8 @@ module Selenium
       #
 
       def delete_cookie(name)
+        raise ArgumentError, 'Cookie name cannot be null or empty' if name.nil? || name.to_s.strip.empty?
+
         @bridge.delete_cookie name
       end
 
diff -pruN 4.4.0-1/lib/selenium/webdriver/common/network.rb 4.38.0-1/lib/selenium/webdriver/common/network.rb
--- 4.4.0-1/lib/selenium/webdriver/common/network.rb	1970-01-01 00:00:00.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/common/network.rb	2025-11-02 08:23:03.000000000 +0000
@@ -0,0 +1,102 @@
+# frozen_string_literal: true
+
+# Licensed to the Software Freedom Conservancy (SFC) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The SFC licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+require 'forwardable'
+
+module Selenium
+  module WebDriver
+    class Network
+      extend Forwardable
+
+      attr_reader :callbacks, :network
+      alias bidi network
+
+      def_delegators :network, :continue_with_auth, :continue_with_request, :continue_with_response
+
+      def initialize(bridge)
+        @network = BiDi::Network.new(bridge.bidi)
+        @callbacks = {}
+      end
+
+      def remove_handler(id)
+        intercept = callbacks[id]
+        network.remove_intercept(intercept['intercept'])
+        callbacks.delete(id)
+      end
+
+      def clear_handlers
+        callbacks.each_key { |id| remove_handler(id) }
+      end
+
+      def add_authentication_handler(username = nil, password = nil, *filter, pattern_type: nil, &block)
+        selected_block =
+          if username && password
+            proc { |auth| auth.authenticate(username, password) }
+          else
+            block
+          end
+
+        add_handler(
+          :auth_required,
+          BiDi::Network::PHASES[:auth_required],
+          BiDi::InterceptedAuth,
+          filter,
+          pattern_type: pattern_type,
+          &selected_block
+        )
+      end
+
+      def add_request_handler(*filter, pattern_type: nil, &block)
+        add_handler(
+          :before_request,
+          BiDi::Network::PHASES[:before_request],
+          BiDi::InterceptedRequest,
+          filter,
+          pattern_type: pattern_type,
+          &block
+        )
+      end
+
+      def add_response_handler(*filter, pattern_type: nil, &block)
+        add_handler(
+          :response_started,
+          BiDi::Network::PHASES[:response_started],
+          BiDi::InterceptedResponse,
+          filter,
+          pattern_type: pattern_type,
+          &block
+        )
+      end
+
+      private
+
+      def add_handler(event_type, phase, intercept_type, filter, pattern_type: nil)
+        intercept = network.add_intercept(phases: [phase], url_patterns: [filter].flatten, pattern_type: pattern_type)
+        callback_id = network.on(event_type) do |event|
+          request = event['request']
+          intercepted_item = intercept_type.new(network, request)
+          yield(intercepted_item)
+        end
+
+        callbacks[callback_id] = intercept
+        callback_id
+      end
+    end # Network
+  end # WebDriver
+end # Selenium
diff -pruN 4.4.0-1/lib/selenium/webdriver/common/options.rb 4.38.0-1/lib/selenium/webdriver/common/options.rb
--- 4.4.0-1/lib/selenium/webdriver/common/options.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/common/options.rb	2025-11-02 08:23:03.000000000 +0000
@@ -24,40 +24,42 @@ module Selenium
                        set_window_rect timeouts unhandled_prompt_behavior strict_file_interactability
                        web_socket_url].freeze
 
+      GRID_OPTIONS = %i[enable_downloads].freeze
+
       class << self
         attr_reader :driver_path
 
-        def chrome(**opts)
-          Chrome::Options.new(**opts)
+        def chrome(**)
+          Chrome::Options.new(**)
         end
 
-        def firefox(**opts)
-          Firefox::Options.new(**opts)
+        def firefox(**)
+          Firefox::Options.new(**)
         end
 
-        def ie(**opts)
-          IE::Options.new(**opts)
+        def ie(**)
+          IE::Options.new(**)
         end
-        alias_method :internet_explorer, :ie
+        alias internet_explorer ie
 
-        def edge(**opts)
-          Edge::Options.new(**opts)
+        def edge(**)
+          Edge::Options.new(**)
         end
-        alias_method :microsoftedge, :edge
+        alias microsoftedge edge
 
-        def safari(**opts)
-          Safari::Options.new(**opts)
+        def safari(**)
+          Safari::Options.new(**)
         end
 
         def set_capabilities
-          (W3C_OPTIONS + self::CAPABILITIES.keys).each do |key|
+          (W3C_OPTIONS + GRID_OPTIONS + self::CAPABILITIES.keys).each do |key|
             next if method_defined? key
 
             define_method key do
               @options[key]
             end
 
-            define_method "#{key}=" do |value|
+            define_method :"#{key}=" do |value|
               @options[key] = value
             end
           end
@@ -85,7 +87,7 @@ module Selenium
       #
 
       def add_option(name, value = nil)
-        @options[name.keys.first] = name.values.first if value.nil? && name.is_a?(Hash)
+        name, value = name.first if value.nil? && name.is_a?(Hash)
         @options[name] = value
       end
 
@@ -95,7 +97,7 @@ module Selenium
         as_json == other.as_json
       end
 
-      alias_method :eql?, :==
+      alias eql? ==
 
       #
       # @api private
@@ -104,13 +106,18 @@ module Selenium
       def as_json(*)
         options = @options.dup
 
+        downloads = options.delete(:enable_downloads)
+        options['se:downloadsEnabled'] = downloads unless downloads.nil?
         w3c_options = process_w3c_options(options)
 
-        self.class::CAPABILITIES.each do |capability_alias, capability_name|
+        browser_options = self.class::CAPABILITIES.each_with_object({}) do |(capability_alias, capability_name), hash|
           capability_value = options.delete(capability_alias)
-          options[capability_name] = capability_value if !capability_value.nil? && !options.key?(capability_name)
+          hash[capability_name] = capability_value unless capability_value.nil?
         end
-        browser_options = defined?(self.class::KEY) ? {self.class::KEY => options} : options
+
+        raise Error::WebDriverError, "These options are not w3c compliant: #{options}" unless options.empty?
+
+        browser_options = {self.class::KEY => browser_options} if defined?(self.class::KEY)
 
         process_browser_options(browser_options)
         generate_as_json(w3c_options.merge(browser_options))
@@ -123,12 +130,21 @@ module Selenium
       end
 
       def process_w3c_options(options)
-        w3c_options = options.select { |key, _val| w3c?(key) }
-        w3c_options[:unhandled_prompt_behavior] &&= w3c_options[:unhandled_prompt_behavior]&.to_s&.tr('_', ' ')
+        w3c_options = options.select { |key, val| w3c?(key) && !val.nil? }
+        w3c_options[:unhandled_prompt_behavior] &&=
+          process_unhandled_prompt_behavior_value(w3c_options[:unhandled_prompt_behavior])
         options.delete_if { |key, _val| w3c?(key) }
         w3c_options
       end
 
+      def process_unhandled_prompt_behavior_value(value)
+        if value.is_a?(Hash)
+          value.transform_values { |v| process_unhandled_prompt_behavior_value(v) }
+        else
+          value&.to_s&.tr('_', ' ')
+        end
+      end
+
       def process_browser_options(_browser_options)
         nil
       end
@@ -170,7 +186,7 @@ module Selenium
       end
 
       def camel_case(str)
-        str.gsub(/_([a-z])/) { Regexp.last_match(1).upcase }
+        str.gsub(/_([a-z])/) { Regexp.last_match(1)&.upcase }
       end
     end # Options
   end # WebDriver
diff -pruN 4.4.0-1/lib/selenium/webdriver/common/platform.rb 4.38.0-1/lib/selenium/webdriver/common/platform.rb
--- 4.4.0-1/lib/selenium/webdriver/common/platform.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/common/platform.rb	2025-11-02 08:23:03.000000000 +0000
@@ -51,9 +51,7 @@ module Selenium
       end
 
       def ci
-        if ENV['TRAVIS']
-          :travis
-        elsif ENV['JENKINS']
+        if ENV['JENKINS']
           :jenkins
         elsif ENV['APPVEYOR']
           :appveyor
@@ -62,22 +60,14 @@ module Selenium
         end
       end
 
-      def bitsize
-        @bitsize ||= if defined?(FFI::Platform::ADDRESS_SIZE)
-                       FFI::Platform::ADDRESS_SIZE
-                     elsif defined?(FFI)
-                       FFI.type_size(:pointer) == 4 ? 32 : 64
-                     elsif jruby?
-                       Integer(ENV_JAVA['sun.arch.data.model'])
-                     else
-                       1.size == 4 ? 32 : 64
-                     end
-      end
-
       def jruby?
         engine == :jruby
       end
 
+      def truffleruby?
+        engine == :truffleruby
+      end
+
       def ruby_version
         RUBY_VERSION
       end
@@ -94,6 +84,10 @@ module Selenium
         os == :linux
       end
 
+      def unix?
+        os == :unix
+      end
+
       def wsl?
         return false unless linux?
 
@@ -105,7 +99,6 @@ module Selenium
 
       def cygwin?
         RUBY_PLATFORM.include?('cygwin')
-        !Regexp.last_match.nil?
       end
 
       def null_device
@@ -116,7 +109,9 @@ module Selenium
         windows? && !cygwin? ? %("#{str}") : str
       end
 
-      def cygwin_path(path, **opts)
+      def cygwin_path(path, only_cygwin: false, **opts)
+        return path if only_cygwin && !cygwin?
+
         flags = []
         opts.each { |k, v| flags << "--#{k}" if v }
 
@@ -155,43 +150,6 @@ module Selenium
         at_exit { yield if Process.pid == pid }
       end
 
-      def find_binary(*binary_names)
-        paths = ENV['PATH'].split(File::PATH_SEPARATOR)
-
-        if windows?
-          binary_names.map! { |n| "#{n}.exe" }
-          binary_names.dup.each { |n| binary_names << n.gsub('exe', 'bat') }
-        end
-
-        binary_names.each do |binary_name|
-          paths.each do |path|
-            full_path = File.join(path, binary_name)
-            full_path = unix_path(full_path) if windows?
-            exe = Dir.glob(full_path).find { |f| File.executable?(f) }
-            return exe if exe
-          end
-        end
-
-        nil
-      end
-
-      def find_in_program_files(*binary_names)
-        paths = [
-          ENV.fetch('PROGRAMFILES', '\\Program Files'),
-          ENV.fetch('ProgramFiles(x86)', '\\Program Files (x86)'),
-          ENV.fetch('ProgramW6432', '\\Program Files')
-        ]
-
-        paths.each do |root|
-          binary_names.each do |name|
-            exe = File.join(root, name)
-            return exe if File.executable?(exe)
-          end
-        end
-
-        nil
-      end
-
       def localhost
         info = Socket.getaddrinfo 'localhost', 80, Socket::AF_INET, Socket::SOCK_STREAM
 
diff -pruN 4.4.0-1/lib/selenium/webdriver/common/port_prober.rb 4.38.0-1/lib/selenium/webdriver/common/port_prober.rb
--- 4.4.0-1/lib/selenium/webdriver/common/port_prober.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/common/port_prober.rb	2025-11-02 08:23:03.000000000 +0000
@@ -34,7 +34,7 @@ module Selenium
         Platform.interfaces.each do |host|
           TCPServer.new(host, port).close
         rescue *IGNORED_ERRORS => e
-          WebDriver.logger.debug("port prober could not bind to #{host}:#{port} (#{e.message})")
+          WebDriver.logger.debug("port prober could not bind to #{host}:#{port} (#{e.message})", id: :driver_service)
           # ignored - some machines appear unable to bind to some of their interfaces
         end
 
diff -pruN 4.4.0-1/lib/selenium/webdriver/common/print_options.rb 4.38.0-1/lib/selenium/webdriver/common/print_options.rb
--- 4.4.0-1/lib/selenium/webdriver/common/print_options.rb	1970-01-01 00:00:00.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/common/print_options.rb	2025-11-02 08:23:03.000000000 +0000
@@ -0,0 +1,93 @@
+# frozen_string_literal: true
+
+# Licensed to the Software Freedom Conservancy (SFC) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The SFC licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+module Selenium
+  module WebDriver
+    # Represents options for printing a page.
+    class PrintOptions
+      DEFAULT_SCALE = 1.0
+      DEFAULT_ORIENTATION = 'portrait'
+      DEFAULT_PAGE_SIZE = {width: 21.0, height: 29.7}.freeze # A4 size in cm
+      DEFAULT_MARGINS = {top: 1.0, bottom: 1.0, left: 1.0, right: 1.0}.freeze
+
+      attr_accessor :orientation, :scale, :background, :page_ranges, :margins
+
+      def initialize
+        @orientation = DEFAULT_ORIENTATION
+        @scale = DEFAULT_SCALE
+        @background = false
+        @page_ranges = nil
+        @page_size = DEFAULT_PAGE_SIZE
+        @margins = DEFAULT_MARGINS
+      end
+
+      # Converts the options to a hash format to be used by WebDriver.
+      #
+      # @return [Hash]
+      def to_h
+        options = {
+          orientation: @orientation,
+          scale: @scale,
+          background: @background,
+          pageRanges: @page_ranges,
+          paperWidth: @page_size[:width],
+          paperHeight: @page_size[:height],
+          marginTop: @margins[:top],
+          marginBottom: @margins[:bottom],
+          marginLeft: @margins[:left],
+          marginRight: @margins[:right]
+        }
+
+        options.compact
+      end
+
+      # Gets the current page size.
+      #
+      # @return [Hash] The current page size hash with :width and :height.
+      attr_reader :page_size
+
+      # Sets the page size. Can be a predefined symbol or custom size hash.
+      #
+      # @param [Symbol, Hash] value The predefined size (:letter, :legal, :a4, :tabloid) or a custom hash.
+      def page_size=(value)
+        predefined_sizes = {
+          letter: {width: 21.59, height: 27.94},
+          legal: {width: 21.59, height: 35.56},
+          a4: {width: 21.0, height: 29.7},
+          tabloid: {width: 27.94, height: 43.18}
+        }
+
+        case value
+        when Symbol
+          raise ArgumentError, "Invalid page size: #{value}" unless predefined_sizes.key?(value)
+
+          @page_size = predefined_sizes[value]
+        when Hash
+          unless value.key?(:width) && value.key?(:height)
+            raise ArgumentError, 'Custom page size must include :width and :height'
+          end
+
+          @page_size = value
+        else
+          raise ArgumentError, 'Page size must be a Symbol or a Hash'
+        end
+      end
+    end
+  end
+end
diff -pruN 4.4.0-1/lib/selenium/webdriver/common/profile_helper.rb 4.38.0-1/lib/selenium/webdriver/common/profile_helper.rb
--- 4.4.0-1/lib/selenium/webdriver/common/profile_helper.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/common/profile_helper.rb	2025-11-02 08:23:03.000000000 +0000
@@ -40,7 +40,7 @@ module Selenium
       end
 
       def as_json(*)
-        {"zip" => encoded}
+        {'zip' => encoded}
       end
 
       def to_json(*)
diff -pruN 4.4.0-1/lib/selenium/webdriver/common/proxy.rb 4.38.0-1/lib/selenium/webdriver/common/proxy.rb
--- 4.4.0-1/lib/selenium/webdriver/common/proxy.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/common/proxy.rb	2025-11-02 08:23:03.000000000 +0000
@@ -49,7 +49,7 @@ module Selenium
         proxy = new
 
         ALLOWED.each do |k, v|
-          proxy.send("#{k}=", data[v]) if data.key?(v)
+          proxy.send(:"#{k}=", data[v]) if data.key?(v)
         end
 
         proxy
@@ -60,7 +60,7 @@ module Selenium
 
         opts.each do |k, v|
           if ALLOWED.key?(k)
-            send("#{k}=", v)
+            send(:"#{k}=", v)
           else
             not_allowed << k
           end
@@ -74,9 +74,10 @@ module Selenium
       def ==(other)
         other.is_a?(self.class) && as_json == other.as_json
       end
-      alias_method :eql?, :==
+      alias eql? ==
 
       def ftp=(value)
+        WebDriver.logger.deprecate('FTP proxy support', nil, id: :ftp_proxy)
         self.type = :manual
         @ftp = value
       end
@@ -152,7 +153,7 @@ module Selenium
           'socksUsername' => socks_username,
           'socksPassword' => socks_password,
           'socksVersion' => socks_version
-        }.delete_if { |_k, v| v.nil? }
+        }.compact
 
         json_result if json_result.length > 1
       end
diff -pruN 4.4.0-1/lib/selenium/webdriver/common/script.rb 4.38.0-1/lib/selenium/webdriver/common/script.rb
--- 4.4.0-1/lib/selenium/webdriver/common/script.rb	1970-01-01 00:00:00.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/common/script.rb	2025-11-02 08:23:03.000000000 +0000
@@ -0,0 +1,45 @@
+# frozen_string_literal: true
+
+# Licensed to the Software Freedom Conservancy (SFC) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The SFC licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+module Selenium
+  module WebDriver
+    class Script
+      def initialize(bridge)
+        @log_handler = BiDi::LogHandler.new(bridge.bidi)
+      end
+
+      # @return [int] id of the handler
+      def add_console_message_handler(&block)
+        @log_handler.add_message_handler('console', &block)
+      end
+
+      # @return [int] id of the handler
+      def add_javascript_error_handler(&block)
+        @log_handler.add_message_handler('javascript', &block)
+      end
+
+      # @param [int] id of the handler previously added
+      def remove_console_message_handler(id)
+        @log_handler.remove_message_handler(id)
+      end
+
+      alias remove_javascript_error_handler remove_console_message_handler
+    end # Script
+  end # WebDriver
+end # Selenium
diff -pruN 4.4.0-1/lib/selenium/webdriver/common/search_context.rb 4.38.0-1/lib/selenium/webdriver/common/search_context.rb
--- 4.4.0-1/lib/selenium/webdriver/common/search_context.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/common/search_context.rb	2025-11-02 08:23:03.000000000 +0000
@@ -35,6 +35,14 @@ module Selenium
         xpath: 'xpath'
       }.freeze
 
+      class << self
+        attr_accessor :extra_finders
+
+        def finders
+          FINDERS.merge(extra_finders || {})
+        end
+      end
+
       #
       # Find the first element matching the given arguments
       #
@@ -57,7 +65,7 @@ module Selenium
       def find_element(*args)
         how, what = extract_args(args)
 
-        by = FINDERS[how.to_sym]
+        by = SearchContext.finders[how.to_sym]
         raise ArgumentError, "cannot find element by #{how.inspect}" unless by
 
         bridge.find_element_by by, what, ref
@@ -72,7 +80,7 @@ module Selenium
       def find_elements(*args)
         how, what = extract_args(args)
 
-        by = FINDERS[how.to_sym]
+        by = SearchContext.finders[how.to_sym]
         raise ArgumentError, "cannot find elements by #{how.inspect}" unless by
 
         bridge.find_elements_by by, what, ref
diff -pruN 4.4.0-1/lib/selenium/webdriver/common/selenium_manager.rb 4.38.0-1/lib/selenium/webdriver/common/selenium_manager.rb
--- 4.4.0-1/lib/selenium/webdriver/common/selenium_manager.rb	1970-01-01 00:00:00.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/common/selenium_manager.rb	2025-11-02 08:23:03.000000000 +0000
@@ -0,0 +1,123 @@
+# frozen_string_literal: true
+
+# Licensed to the Software Freedom Conservancy (SFC) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The SFC licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+require 'open3'
+
+module Selenium
+  module WebDriver
+    #
+    # Wrapper for getting information from the Selenium Manager binaries.
+    # This implementation is still in beta, and may change.
+    # @api private
+    #
+    class SeleniumManager
+      class << self
+        attr_writer :bin_path
+
+        def bin_path
+          @bin_path ||= '../../../../../bin'
+        end
+
+        # @param [Array] arguments what gets sent to to Selenium Manager binary.
+        # @return [Hash] paths to the requested assets.
+        def binary_paths(*arguments)
+          arguments += %w[--language-binding ruby]
+          arguments += %w[--output json]
+          arguments << '--debug' if WebDriver.logger.debug?
+
+          run(binary, *arguments)
+        end
+
+        private
+
+        # @return [String] the path to the correct selenium manager
+        def binary
+          @binary ||= begin
+            if (location = ENV.fetch('SE_MANAGER_PATH', nil))
+              WebDriver.logger.debug("Selenium Manager set by ENV['SE_MANAGER_PATH']: #{location}")
+            end
+            location ||= platform_location
+
+            Platform.assert_executable(location)
+            WebDriver.logger.debug("Selenium Manager binary found at #{location}", id: :selenium_manager)
+            location
+          end
+        end
+
+        def run(*command)
+          stdout, stderr, status = execute_command(*command)
+          result = parse_result_and_log(stdout)
+
+          validate_command_result(command, status, result, stderr)
+
+          result
+        end
+
+        def platform_location
+          directory = File.expand_path(bin_path, __FILE__)
+          if Platform.windows?
+            "#{directory}/windows/selenium-manager.exe"
+          elsif Platform.mac?
+            "#{directory}/macos/selenium-manager"
+          elsif Platform.linux?
+            "#{directory}/linux/selenium-manager"
+          elsif Platform.unix?
+            WebDriver.logger.warn('Selenium Manager binary may not be compatible with Unix',
+                                  id: %i[selenium_manager unix_binary])
+            "#{directory}/linux/selenium-manager"
+          else
+            raise Error::WebDriverError, "unsupported platform: #{Platform.os}"
+          end
+        end
+
+        def execute_command(*command)
+          WebDriver.logger.debug("Executing Process #{command}", id: :selenium_manager)
+
+          Open3.capture3(*command)
+        rescue StandardError => e
+          raise Error::WebDriverError, "Unsuccessful command executed: #{command}; #{e.message}"
+        end
+
+        def parse_result_and_log(stdout)
+          json_output = stdout.empty? ? {'logs' => [], 'result' => {}} : JSON.parse(stdout)
+
+          json_output['logs'].each do |log|
+            level = log['level'].casecmp('info').zero? ? 'debug' : log['level'].downcase
+            WebDriver.logger.send(level, log['message'], id: :selenium_manager)
+          end
+
+          json_output['result']
+        end
+
+        def validate_command_result(command, status, result, stderr)
+          if status.nil? || status.exitstatus.nil?
+            WebDriver.logger.info("No exit status for: #{command}. Assuming success if result is present.",
+                                  id: :selenium_manager)
+          end
+
+          return unless status&.exitstatus&.positive? || result.nil?
+
+          code = status&.exitstatus || 'exit status not available'
+          raise Error::WebDriverError,
+                "Unsuccessful command executed: #{command} - Code #{code}\n#{result}\n#{stderr}"
+        end
+      end
+    end # SeleniumManager
+  end # WebDriver
+end # Selenium
diff -pruN 4.4.0-1/lib/selenium/webdriver/common/service.rb 4.38.0-1/lib/selenium/webdriver/common/service.rb
--- 4.4.0-1/lib/selenium/webdriver/common/service.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/common/service.rb	2025-11-02 08:23:03.000000000 +0000
@@ -28,26 +28,27 @@ module Selenium
       class << self
         attr_reader :driver_path
 
-        def chrome(**opts)
-          Chrome::Service.new(**opts)
+        def chrome(**)
+          Chrome::Service.new(**)
         end
 
-        def firefox(**opts)
-          Firefox::Service.new(**opts)
+        def firefox(**)
+          Firefox::Service.new(**)
         end
 
-        def ie(**opts)
-          IE::Service.new(**opts)
+        def ie(**)
+          IE::Service.new(**)
         end
-        alias_method :internet_explorer, :ie
+        alias internet_explorer ie
 
-        def edge(**opts)
-          Edge::Service.new(**opts)
+        def edge(**)
+          Edge::Service.new(**)
         end
-        alias_method :microsoftedge, :edge
+        alias microsoftedge edge
+        alias msedge edge
 
-        def safari(**opts)
-          Safari::Service.new(**opts)
+        def safari(**)
+          Safari::Service.new(**)
         end
 
         def driver_path=(path)
@@ -56,8 +57,8 @@ module Selenium
         end
       end
 
-      attr_accessor :host
-      attr_reader :executable_path, :port, :extra_args
+      attr_accessor :host, :executable_path, :port, :log, :args
+      alias extra_args args
 
       #
       # End users should use a class method for the desired driver, rather than using this directly.
@@ -65,46 +66,43 @@ module Selenium
       # @api private
       #
 
-      def initialize(path: nil, port: nil, args: nil)
-        path ||= self.class.driver_path
+      def initialize(path: nil, port: nil, log: nil, args: nil)
         port ||= self.class::DEFAULT_PORT
         args ||= []
+        path ||= env_path
 
-        @executable_path = binary_path(path)
+        @executable_path = path
         @host = Platform.localhost
         @port = Integer(port)
-
-        @extra_args = args.is_a?(Hash) ? extract_service_args(args) : args
+        @log = case log
+               when :stdout
+                 $stdout
+               when :stderr
+                 $stderr
+               else
+                 log
+               end
+        @args = args
 
         raise Error::WebDriverError, "invalid port: #{@port}" if @port < 1
       end
 
       def launch
-        sm = ServiceManager.new(self)
-        sm.start
-        sm
+        @executable_path ||= env_path || find_driver_path
+        ServiceManager.new(self).tap(&:start)
       end
 
       def shutdown_supported
         self.class::SHUTDOWN_SUPPORTED
       end
 
-      protected
-
-      def extract_service_args(driver_opts)
-        driver_opts.key?(:args) ? driver_opts.delete(:args) : []
+      def find_driver_path
+        default_options = WebDriver.const_get("#{self.class.name&.split('::')&.[](2)}::Options").new
+        DriverFinder.new(default_options, self).driver_path
       end
 
-      private
-
-      def binary_path(path = nil)
-        path = path.call if path.is_a?(Proc)
-        path ||= Platform.find_binary(self.class::EXECUTABLE)
-
-        raise Error::WebDriverError, self.class::MISSING_TEXT unless path
-
-        Platform.assert_executable path
-        path
+      def env_path
+        ENV.fetch(self.class::DRIVER_PATH_ENV_KEY, nil)
       end
     end # Service
   end # WebDriver
diff -pruN 4.4.0-1/lib/selenium/webdriver/common/service_manager.rb 4.38.0-1/lib/selenium/webdriver/common/service_manager.rb
--- 4.4.0-1/lib/selenium/webdriver/common/service_manager.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/common/service_manager.rb	2025-11-02 08:23:03.000000000 +0000
@@ -40,7 +40,8 @@ module Selenium
         @executable_path = config.executable_path
         @host = Platform.localhost
         @port = config.port
-        @extra_args = config.extra_args
+        @io = config.log
+        @extra_args = config.args
         @shutdown_supported = config.shutdown_supported
 
         raise Error::WebDriverError, "invalid port: #{@port}" if @port < 1
@@ -64,7 +65,7 @@ module Selenium
 
         stop_server
         @process.poll_for_exit STOP_TIMEOUT
-      rescue ChildProcess::TimeoutError
+      rescue ChildProcess::TimeoutError, Errno::ECONNREFUSED
         nil # noop
       ensure
         stop_process
@@ -77,14 +78,10 @@ module Selenium
       private
 
       def build_process(*command)
-        WebDriver.logger.debug("Executing Process #{command}")
+        WebDriver.logger.debug("Executing Process #{command}", id: :driver_service)
         @process = ChildProcess.build(*command)
-        if WebDriver.logger.debug?
-          @process.io.stdout = @process.io.stderr = WebDriver.logger.io
-        elsif Platform.jruby?
-          # Apparently we need to read the output of drivers on JRuby.
-          @process.io.stdout = @process.io.stderr = File.new(Platform.null_device, 'w')
-        end
+        @io ||= WebDriver.logger.io if WebDriver.logger.debug?
+        @process.io = @io if @io
 
         @process
       end
@@ -104,8 +101,6 @@ module Selenium
 
       def start_process
         @process = build_process(@executable_path, "--port=#{@port}", *@extra_args)
-        # NOTE: this is a bug only in Windows 7
-        @process.leader = true unless Platform.windows?
         @process.start
       end
 
@@ -113,12 +108,12 @@ module Selenium
         return if process_exited?
 
         @process.stop STOP_TIMEOUT
-        @process.io.stdout.close if Platform.jruby? && !WebDriver.logger.debug?
       end
 
       def stop_server
         connect_to_server do |http|
           headers = WebDriver::Remote::Http::Common::DEFAULT_HEADERS.dup
+          WebDriver.logger.debug('Sending shutdown request to server', id: :driver_service)
           http.get('/shutdown', headers)
         end
       end
diff -pruN 4.4.0-1/lib/selenium/webdriver/common/shadow_root.rb 4.38.0-1/lib/selenium/webdriver/common/shadow_root.rb
--- 4.4.0-1/lib/selenium/webdriver/common/shadow_root.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/common/shadow_root.rb	2025-11-02 08:23:03.000000000 +0000
@@ -42,7 +42,7 @@ module Selenium
       def ==(other)
         other.is_a?(self.class) && ref == other.ref
       end
-      alias_method :eql?, :==
+      alias eql? ==
 
       def hash
         [@id, @bridge].hash
@@ -81,7 +81,6 @@ module Selenium
       private
 
       attr_reader :bridge
-
     end # ShadowRoot
   end # WebDriver
 end # Selenium
diff -pruN 4.4.0-1/lib/selenium/webdriver/common/socket_lock.rb 4.38.0-1/lib/selenium/webdriver/common/socket_lock.rb
--- 4.4.0-1/lib/selenium/webdriver/common/socket_lock.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/common/socket_lock.rb	2025-11-02 08:23:03.000000000 +0000
@@ -26,6 +26,7 @@ module Selenium
     class SocketLock
       def initialize(port, timeout)
         @port    = port
+        @server  = nil
         @timeout = timeout
       end
 
@@ -66,11 +67,10 @@ module Selenium
 
       def can_lock?
         @server = TCPServer.new(Platform.localhost, @port)
-        ChildProcess.close_on_exec @server
-
+        @server.close_on_exec = true
         true
       rescue SocketError, Errno::EADDRINUSE, Errno::EBADF => e
-        WebDriver.logger.debug("#{self}: #{e.message}")
+        WebDriver.logger.debug("#{self}: #{e.message}", id: :driver_service)
         false
       end
 
diff -pruN 4.4.0-1/lib/selenium/webdriver/common/socket_poller.rb 4.38.0-1/lib/selenium/webdriver/common/socket_poller.rb
--- 4.4.0-1/lib/selenium/webdriver/common/socket_poller.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/common/socket_poller.rb	2025-11-02 08:23:03.000000000 +0000
@@ -78,7 +78,7 @@ module Selenium
         def listening?
           addr     = Socket.getaddrinfo(@host, @port, Socket::AF_INET, Socket::SOCK_STREAM)
           sock     = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
-          sockaddr = Socket.pack_sockaddr_in(@port, addr[0][3])
+          sockaddr = Socket.pack_sockaddr_in(@port, addr[0][3].to_s)
 
           begin
             sock.connect_nonblock sockaddr
@@ -93,7 +93,7 @@ module Selenium
           true
         rescue *NOT_CONNECTED_ERRORS
           sock&.close
-          WebDriver.logger.debug("polling for socket on #{[@host, @port].inspect}")
+          WebDriver.logger.debug("polling for socket on #{[@host, @port].inspect}", id: :driver_service)
           false
         end
       end
diff -pruN 4.4.0-1/lib/selenium/webdriver/common/takes_screenshot.rb 4.38.0-1/lib/selenium/webdriver/common/takes_screenshot.rb
--- 4.4.0-1/lib/selenium/webdriver/common/takes_screenshot.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/common/takes_screenshot.rb	2025-11-02 08:23:03.000000000 +0000
@@ -32,10 +32,11 @@ module Selenium
       def save_screenshot(png_path, full_page: false)
         extension = File.extname(png_path).downcase
         if extension != '.png'
-          WebDriver.logger.warn "name used for saved screenshot does not match file type. " \
-                                "It should end with .png extension",
+          WebDriver.logger.warn 'name used for saved screenshot does not match file type. ' \
+                                'It should end with .png extension',
                                 id: :screenshot
         end
+        WebDriver.logger.debug("Saving screenshot to #{Dir.pwd}/#{png_path}")
         File.open(png_path, 'wb') { |f| f << screenshot_as(:png, full_page: full_page) }
       end
 
@@ -49,6 +50,10 @@ module Selenium
       # @api public
 
       def screenshot_as(format, full_page: false)
+        if full_page && !respond_to?(:save_full_page_screenshot)
+          raise Error::UnsupportedOperationError, "Full Page Screenshots are not supported for #{inspect}"
+        end
+
         case format
         when :base64
           full_page ? full_screenshot : screenshot
@@ -57,10 +62,7 @@ module Selenium
         else
           raise Error::UnsupportedOperationError, "unsupported format: #{format.inspect}"
         end
-      rescue NameError
-        raise Error::UnsupportedOperationError, "Full Page Screenshots are not supported for #{inspect}"
       end
-
     end # TakesScreenshot
   end # WebDriver
 end # Selenium
diff -pruN 4.4.0-1/lib/selenium/webdriver/common/target_locator.rb 4.38.0-1/lib/selenium/webdriver/common/target_locator.rb
--- 4.4.0-1/lib/selenium/webdriver/common/target_locator.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/common/target_locator.rb	2025-11-02 08:23:03.000000000 +0000
@@ -50,10 +50,10 @@ module Selenium
       # @param type either :tab or :window
       #
 
+      # steep:ignore:start
       def new_window(type = :window)
-        unless %i[window tab].include?(type)
-          raise ArgumentError, "Valid types are :tab and :window, received: #{type.inspect}"
-        end
+        raise ArgumentError, "Valid types are :tab and :window, received: #{type.inspect}" unless %i[window
+                                                                                                     tab].include?(type)
 
         handle = @bridge.new_window(type)['handle']
 
@@ -71,6 +71,7 @@ module Selenium
           window(handle)
         end
       end
+      # steep:ignore:end
 
       #
       # switch to the given window handle
@@ -97,12 +98,11 @@ module Selenium
           @bridge.switch_to_window id
 
           begin
-            returned = yield
+            yield
           ensure
             current_handles = @bridge.window_handles
             original = current_handles.first unless current_handles.include? original
             @bridge.switch_to_window original
-            returned
           end
         else
           @bridge.switch_to_window id
diff -pruN 4.4.0-1/lib/selenium/webdriver/common/timeouts.rb 4.38.0-1/lib/selenium/webdriver/common/timeouts.rb
--- 4.4.0-1/lib/selenium/webdriver/common/timeouts.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/common/timeouts.rb	2025-11-02 08:23:03.000000000 +0000
@@ -48,7 +48,7 @@ module Selenium
       def script
         Float(@bridge.timeouts['script']) / 1000
       end
-      alias_method :script_timeout, :script
+      alias script_timeout script
 
       #
       # Sets the amount of time to wait for an asynchronous script to finish
@@ -59,7 +59,7 @@ module Selenium
       def script=(seconds)
         @bridge.timeouts = {'script' => Integer(seconds * 1000)}
       end
-      alias_method :script_timeout=, :script=
+      alias script_timeout= script=
 
       #
       # Gets the amount of time to wait for a page load to complete before throwing an error.
diff -pruN 4.4.0-1/lib/selenium/webdriver/common/virtual_authenticator/credential.rb 4.38.0-1/lib/selenium/webdriver/common/virtual_authenticator/credential.rb
--- 4.4.0-1/lib/selenium/webdriver/common/virtual_authenticator/credential.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/common/virtual_authenticator/credential.rb	2025-11-02 08:23:03.000000000 +0000
@@ -26,12 +26,12 @@ module Selenium
   module WebDriver
     class Credential
       class << self
-        def resident(**opts)
-          Credential.new(resident_credential: true, **opts)
+        def resident(**)
+          Credential.new(resident_credential: true, **)
         end
 
-        def non_resident(**opts)
-          Credential.new(resident_credential: false, **opts)
+        def non_resident(**)
+          Credential.new(resident_credential: false, **)
         end
 
         def encode(byte_array)
@@ -44,8 +44,8 @@ module Selenium
 
         def from_json(opts)
           user_handle = opts['userHandle'] ? decode(opts['userHandle']) : nil
-          new(id: decode(opts["credentialId"]),
-              resident_credential: opts["isResidentCredential"],
+          new(id: decode(opts['credentialId']),
+              resident_credential: opts['isResidentCredential'],
               rp_id: opts['rpId'],
               private_key: opts['privateKey'],
               sign_count: opts['signCount'],
@@ -54,15 +54,17 @@ module Selenium
       end
 
       attr_reader :id, :resident_credential, :rp_id, :user_handle, :private_key, :sign_count
-      alias_method :resident_credential?, :resident_credential
+      alias resident_credential? resident_credential
 
-      def initialize(id:, resident_credential:, rp_id:, private_key:, user_handle: nil, sign_count: 0)
+      def initialize(id:, resident_credential:, rp_id:, private_key:, **opts)
         @id = id
         @resident_credential = resident_credential
         @rp_id = rp_id
-        @user_handle = user_handle
+        @user_handle = opts.delete(:user_handle) { nil }
         @private_key = private_key
-        @sign_count = sign_count
+        @sign_count = opts.delete(:sign_count) { 0 }
+
+        raise ArgumentError, "Invalid arguments: #{opts.keys}" unless opts.empty?
       end
 
       #
diff -pruN 4.4.0-1/lib/selenium/webdriver/common/virtual_authenticator/virtual_authenticator.rb 4.38.0-1/lib/selenium/webdriver/common/virtual_authenticator/virtual_authenticator.rb
--- 4.4.0-1/lib/selenium/webdriver/common/virtual_authenticator/virtual_authenticator.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/common/virtual_authenticator/virtual_authenticator.rb	2025-11-02 08:23:03.000000000 +0000
@@ -20,7 +20,6 @@
 module Selenium
   module WebDriver
     class VirtualAuthenticator
-
       attr_reader :options
 
       #
diff -pruN 4.4.0-1/lib/selenium/webdriver/common/virtual_authenticator/virtual_authenticator_options.rb 4.38.0-1/lib/selenium/webdriver/common/virtual_authenticator/virtual_authenticator_options.rb
--- 4.4.0-1/lib/selenium/webdriver/common/virtual_authenticator/virtual_authenticator_options.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/common/virtual_authenticator/virtual_authenticator_options.rb	2025-11-02 08:23:03.000000000 +0000
@@ -25,24 +25,24 @@
 module Selenium
   module WebDriver
     class VirtualAuthenticatorOptions
-
-      PROTOCOL = {ctap2: "ctap2", u2f: "ctap1/u2f"}.freeze
-      TRANSPORT = {ble: "ble", usb: "usb", nfc: "nfc", internal: "internal"}.freeze
+      PROTOCOL = {ctap2: 'ctap2', u2f: 'ctap1/u2f'}.freeze
+      TRANSPORT = {ble: 'ble', usb: 'usb', nfc: 'nfc', internal: 'internal'}.freeze
 
       attr_accessor :protocol, :transport, :resident_key, :user_verification, :user_consenting, :user_verified
-      alias_method :resident_key?, :resident_key
-      alias_method :user_verification?, :user_verification
-      alias_method :user_consenting?, :user_consenting
-      alias_method :user_verified?, :user_verified
+      alias resident_key? resident_key
+      alias user_verification? user_verification
+      alias user_consenting? user_consenting
+      alias user_verified? user_verified
+
+      def initialize(**opts)
+        @protocol = opts.delete(:protocol) { :ctap2 }
+        @transport = opts.delete(:transport) { :usb }
+        @resident_key = opts.delete(:resident_key) { false }
+        @user_verification = opts.delete(:user_verification) { false }
+        @user_consenting = opts.delete(:user_consenting) { true }
+        @user_verified = opts.delete(:user_verified) { false }
 
-      def initialize(protocol: :ctap2, transport: :usb, resident_key: false,
-                     user_verification: false, user_consenting: true, user_verified: false)
-        @protocol = protocol
-        @transport = transport
-        @resident_key = resident_key
-        @user_verification = user_verification
-        @user_consenting = user_consenting
-        @user_verified = user_verified
+        raise ArgumentError, "Invalid arguments: #{opts.keys}" unless opts.empty?
       end
 
       #
diff -pruN 4.4.0-1/lib/selenium/webdriver/common/wait.rb 4.38.0-1/lib/selenium/webdriver/common/wait.rb
--- 4.4.0-1/lib/selenium/webdriver/common/wait.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/common/wait.rb	2025-11-02 08:23:03.000000000 +0000
@@ -29,7 +29,7 @@ module Selenium
       # @param [Hash] opts Options for this instance
       # @option opts [Numeric] :timeout (5) Seconds to wait before timing out.
       # @option opts [Numeric] :interval (0.2) Seconds to sleep between polls.
-      # @option opts [String] :message Exception mesage if timed out.
+      # @option opts [String] :message Exception message if timed out.
       # @option opts [Array, Exception] :ignore Exceptions to ignore while polling (default: Error::NoSuchElementError)
       #
 
@@ -65,7 +65,7 @@ module Selenium
         msg = if @message
                 @message.dup
               else
-                +"timed out after #{@timeout} seconds"
+                "timed out after #{@timeout} seconds"
               end
 
         msg << " (#{last_error.message})" if last_error
diff -pruN 4.4.0-1/lib/selenium/webdriver/common/websocket_connection.rb 4.38.0-1/lib/selenium/webdriver/common/websocket_connection.rb
--- 4.4.0-1/lib/selenium/webdriver/common/websocket_connection.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/common/websocket_connection.rb	2025-11-02 08:23:03.000000000 +0000
@@ -22,6 +22,11 @@ require 'websocket'
 module Selenium
   module WebDriver
     class WebSocketConnection
+      CONNECTION_ERRORS = [
+        Errno::ECONNRESET, # connection is aborted (browser process was killed)
+        Errno::EPIPE # broken pipe (browser process was killed)
+      ].freeze
+
       RESPONSE_WAIT_TIMEOUT = 30
       RESPONSE_WAIT_INTERVAL = 0.1
 
@@ -47,10 +52,22 @@ module Selenium
         @callbacks ||= Hash.new { |callbacks, event| callbacks[event] = [] }
       end
 
+      def add_callback(event, &block)
+        callbacks[event] << block
+        block.object_id
+      end
+
+      def remove_callback(event, id)
+        return if callbacks[event].reject! { |callback| callback.object_id == id }
+
+        ids = callbacks[event]&.map(&:object_id)
+        raise Error::WebDriverError, "Callback with ID #{id} does not exist for event #{event}: #{ids}"
+      end
+
       def send_cmd(**payload)
         id = next_id
         data = payload.merge(id: id)
-        WebDriver.logger.debug "WebSocket -> #{data}"[...MAX_LOG_MESSAGE_SIZE]
+        WebDriver.logger.debug "WebSocket -> #{data}"[...MAX_LOG_MESSAGE_SIZE], id: :bidi
         data = JSON.generate(data)
         out_frame = WebSocket::Frame::Outgoing::Client.new(version: ws.version, data: data, type: 'text')
         socket.write(out_frame.to_s)
@@ -90,6 +107,8 @@ module Selenium
               end
             end
           end
+        rescue *CONNECTION_ERRORS
+          Thread.stop
         end
       end
 
@@ -104,8 +123,8 @@ module Selenium
         return {} if message.empty?
 
         message = JSON.parse(message)
-        messages[message["id"]] = message
-        WebDriver.logger.debug "WebSocket <- #{message}"[...MAX_LOG_MESSAGE_SIZE]
+        messages[message['id']] = message
+        WebDriver.logger.debug "WebSocket <- #{message}"[...MAX_LOG_MESSAGE_SIZE], id: :bidi
 
         message
       end
@@ -122,6 +141,8 @@ module Selenium
           Thread.current.report_on_exception = true
 
           yield params
+        rescue Error::WebDriverError, *CONNECTION_ERRORS
+          Thread.stop
         end
       end
 
@@ -150,7 +171,6 @@ module Selenium
         @id ||= 0
         @id += 1
       end
-
     end # BiDi
   end # WebDriver
 end # Selenium
diff -pruN 4.4.0-1/lib/selenium/webdriver/common/zipper.rb 4.38.0-1/lib/selenium/webdriver/common/zipper.rb
--- 4.4.0-1/lib/selenium/webdriver/common/zipper.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/common/zipper.rb	2025-11-02 08:23:03.000000000 +0000
@@ -18,6 +18,7 @@
 # under the License.
 
 require 'zip'
+require 'zip/version' # Not required automatically
 require 'tempfile'
 require 'find'
 require 'base64'
@@ -30,6 +31,7 @@ module Selenium
 
     module Zipper
       EXTENSIONS = %w[.zip .xpi].freeze
+      RUBYZIP_V3 = Zip::VERSION >= '3.0.0'
 
       class << self
         def unzip(path)
@@ -42,7 +44,11 @@ module Selenium
               dirname = File.dirname(to)
 
               FileUtils.mkdir_p dirname
-              zip.extract(entry, to)
+              if RUBYZIP_V3
+                zip.extract(entry, entry.name, destination_directory: destination)
+              else
+                zip.extract(entry, to)
+              end
             end
           end
 
@@ -75,7 +81,11 @@ module Selenium
           # Don't use Tempfile since it lacks rb_file_s_rename permission on Windows.
           Dir.mktmpdir do |tmp_dir|
             zip_path = File.join(tmp_dir, 'webdriver-zip')
-            Zip::File.open(zip_path, Zip::File::CREATE, &blk)
+            if RUBYZIP_V3
+              Zip::File.open(zip_path, create: true, &blk)
+            else
+              Zip::File.open(zip_path, Zip::File::CREATE, &blk)
+            end
           end
         end
 
diff -pruN 4.4.0-1/lib/selenium/webdriver/common.rb 4.38.0-1/lib/selenium/webdriver/common.rb
--- 4.4.0-1/lib/selenium/webdriver/common.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/common.rb	2025-11-02 08:23:03.000000000 +0000
@@ -18,10 +18,13 @@
 # under the License.
 
 require 'selenium/webdriver/common/error'
+require 'selenium/webdriver/common/local_driver'
+require 'selenium/webdriver/common/driver_finder'
 require 'selenium/webdriver/common/platform'
 require 'selenium/webdriver/common/proxy'
 require 'selenium/webdriver/common/log_entry'
 require 'selenium/webdriver/common/file_reaper'
+require 'selenium/webdriver/common/selenium_manager'
 require 'selenium/webdriver/common/service'
 require 'selenium/webdriver/common/service_manager'
 require 'selenium/webdriver/common/socket_lock'
@@ -60,15 +63,9 @@ require 'selenium/webdriver/common/actio
 require 'selenium/webdriver/common/virtual_authenticator/credential'
 require 'selenium/webdriver/common/virtual_authenticator/virtual_authenticator_options'
 require 'selenium/webdriver/common/virtual_authenticator/virtual_authenticator'
-require 'selenium/webdriver/common/html5/shared_web_storage'
-require 'selenium/webdriver/common/html5/local_storage'
-require 'selenium/webdriver/common/html5/session_storage'
-require 'selenium/webdriver/common/driver_extensions/has_web_storage'
 require 'selenium/webdriver/common/driver_extensions/downloads_files'
-require 'selenium/webdriver/common/driver_extensions/has_location'
 require 'selenium/webdriver/common/driver_extensions/has_session_id'
 require 'selenium/webdriver/common/driver_extensions/has_network_conditions'
-require 'selenium/webdriver/common/driver_extensions/has_network_connection'
 require 'selenium/webdriver/common/driver_extensions/has_network_interception'
 require 'selenium/webdriver/common/driver_extensions/has_apple_permissions'
 require 'selenium/webdriver/common/driver_extensions/has_permissions'
@@ -80,6 +77,7 @@ require 'selenium/webdriver/common/drive
 require 'selenium/webdriver/common/driver_extensions/has_addons'
 require 'selenium/webdriver/common/driver_extensions/has_bidi'
 require 'selenium/webdriver/common/driver_extensions/has_devtools'
+require 'selenium/webdriver/common/driver_extensions/has_file_downloads'
 require 'selenium/webdriver/common/driver_extensions/has_authentication'
 require 'selenium/webdriver/common/driver_extensions/has_logs'
 require 'selenium/webdriver/common/driver_extensions/has_log_events'
@@ -87,7 +85,9 @@ require 'selenium/webdriver/common/drive
 require 'selenium/webdriver/common/driver_extensions/has_cdp'
 require 'selenium/webdriver/common/driver_extensions/has_casting'
 require 'selenium/webdriver/common/driver_extensions/has_launching'
+require 'selenium/webdriver/common/driver_extensions/has_fedcm_dialog'
 require 'selenium/webdriver/common/keys'
+require 'selenium/webdriver/common/print_options'
 require 'selenium/webdriver/common/profile_helper'
 require 'selenium/webdriver/common/options'
 require 'selenium/webdriver/common/takes_screenshot'
@@ -95,3 +95,8 @@ require 'selenium/webdriver/common/drive
 require 'selenium/webdriver/common/element'
 require 'selenium/webdriver/common/shadow_root'
 require 'selenium/webdriver/common/websocket_connection'
+require 'selenium/webdriver/common/child_process'
+require 'selenium/webdriver/common/script'
+require 'selenium/webdriver/common/fedcm/account'
+require 'selenium/webdriver/common/fedcm/dialog'
+require 'selenium/webdriver/common/network'
diff -pruN 4.4.0-1/lib/selenium/webdriver/devtools/console_event.rb 4.38.0-1/lib/selenium/webdriver/devtools/console_event.rb
--- 4.4.0-1/lib/selenium/webdriver/devtools/console_event.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/devtools/console_event.rb	2025-11-02 08:23:03.000000000 +0000
@@ -21,7 +21,6 @@ module Selenium
   module WebDriver
     class DevTools
       class ConsoleEvent
-
         attr_accessor :type, :timestamp, :args
 
         def initialize(type:, timestamp:, args:)
@@ -31,7 +30,6 @@ module Selenium
             arg.key?('value') ? arg['value'] : arg
           end
         end
-
       end # ConsoleEvent
     end # DevTools
   end # WebDriver
diff -pruN 4.4.0-1/lib/selenium/webdriver/devtools/exception_event.rb 4.38.0-1/lib/selenium/webdriver/devtools/exception_event.rb
--- 4.4.0-1/lib/selenium/webdriver/devtools/exception_event.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/devtools/exception_event.rb	2025-11-02 08:23:03.000000000 +0000
@@ -21,7 +21,6 @@ module Selenium
   module WebDriver
     class DevTools
       class ExceptionEvent
-
         attr_accessor :description, :timestamp, :stacktrace
 
         def initialize(description:, timestamp:, stacktrace:)
@@ -29,7 +28,6 @@ module Selenium
           @timestamp = Time.at(timestamp / 1000)
           @stacktrace = stacktrace
         end
-
       end # ExceptionEvent
     end # DevTools
   end # WebDriver
diff -pruN 4.4.0-1/lib/selenium/webdriver/devtools/mutation_event.rb 4.38.0-1/lib/selenium/webdriver/devtools/mutation_event.rb
--- 4.4.0-1/lib/selenium/webdriver/devtools/mutation_event.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/devtools/mutation_event.rb	2025-11-02 08:23:03.000000000 +0000
@@ -21,7 +21,6 @@ module Selenium
   module WebDriver
     class DevTools
       class MutationEvent
-
         attr_accessor :element, :attribute_name, :current_value, :old_value
 
         def initialize(element:, attribute_name:, current_value:, old_value:)
@@ -30,7 +29,6 @@ module Selenium
           @current_value = current_value
           @old_value = old_value
         end
-
       end # MutationEvent
     end # DevTools
   end # WebDriver
diff -pruN 4.4.0-1/lib/selenium/webdriver/devtools/network_interceptor.rb 4.38.0-1/lib/selenium/webdriver/devtools/network_interceptor.rb
--- 4.4.0-1/lib/selenium/webdriver/devtools/network_interceptor.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/devtools/network_interceptor.rb	2025-11-02 08:23:03.000000000 +0000
@@ -20,7 +20,6 @@
 module Selenium
   module WebDriver
     class DevTools
-
       #
       # Wraps the network request/response interception, providing
       # thread-safety guarantees and handling special cases such as browser
@@ -31,14 +30,13 @@ module Selenium
       #
 
       class NetworkInterceptor
-
         # CDP fails to get body on certain responses (301) and raises:
         # "Can only get response body on requests captured after headers received."
-        CANNOT_GET_BODY_ON_REDIRECT_ERROR_CODE = "-32000"
+        CANNOT_GET_BODY_ON_REDIRECT_ERROR_CODE = '-32000'
 
         # CDP fails to operate with intercepted requests.
         # Typical reason is browser cancelling intercepted requests/responses.
-        INVALID_INTERCEPTION_ID_ERROR_CODE = "-32602"
+        INVALID_INTERCEPTION_ID_ERROR_CODE = '-32602'
 
         def initialize(devtools)
           @devtools = devtools
@@ -100,7 +98,7 @@ module Selenium
           original = DevTools::Request.from(id, params)
           mutable = DevTools::Request.from(id, params)
 
-          block.call(mutable) do |&continue| # rubocop:disable Performance/RedundantBlockCall
+          block.call(mutable) do |&continue|
             pending_response_requests[id] = continue
 
             if original == mutable
@@ -129,14 +127,14 @@ module Selenium
         def continue_request(id)
           devtools.fetch.continue_request(request_id: id)
         end
-        alias_method :continue_response, :continue_request
+        alias continue_response continue_request
 
         def mutate_request(request)
           devtools.fetch.continue_request(
             request_id: request.id,
             url: request.url,
             method: request.method,
-            post_data: request.post_data,
+            post_data: (Base64.strict_encode64(request.post_data) if request.post_data),
             headers: request.headers.map do |k, v|
               {name: k, value: v}
             end
@@ -169,7 +167,6 @@ module Selenium
         def cancelled?(network_id)
           lock.synchronize { !!cancelled_requests.delete(network_id) }
         end
-
       end # NetworkInterceptor
     end # DevTools
   end # WebDriver
diff -pruN 4.4.0-1/lib/selenium/webdriver/devtools/pinned_script.rb 4.38.0-1/lib/selenium/webdriver/devtools/pinned_script.rb
--- 4.4.0-1/lib/selenium/webdriver/devtools/pinned_script.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/devtools/pinned_script.rb	2025-11-02 08:23:03.000000000 +0000
@@ -21,7 +21,6 @@ module Selenium
   module WebDriver
     class DevTools
       class PinnedScript
-
         attr_accessor :key, :devtools_identifier, :script
 
         def initialize(script)
@@ -52,7 +51,6 @@ module Selenium
         def remove
           "__webdriver_#{key} = undefined"
         end
-
       end # PinnedScript
     end # DevTools
   end # WebDriver
diff -pruN 4.4.0-1/lib/selenium/webdriver/devtools/request.rb 4.38.0-1/lib/selenium/webdriver/devtools/request.rb
--- 4.4.0-1/lib/selenium/webdriver/devtools/request.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/devtools/request.rb	2025-11-02 08:23:03.000000000 +0000
@@ -21,7 +21,6 @@ module Selenium
   module WebDriver
     class DevTools
       class Request
-
         attr_accessor :url, :method, :headers, :post_data
         attr_reader :id
 
@@ -60,7 +59,6 @@ module Selenium
         def inspect
           %(#<#{self.class.name} @id="#{id}" @method="#{method}" @url="#{url}")
         end
-
       end # Request
     end # DevTools
   end # WebDriver
diff -pruN 4.4.0-1/lib/selenium/webdriver/devtools/response.rb 4.38.0-1/lib/selenium/webdriver/devtools/response.rb
--- 4.4.0-1/lib/selenium/webdriver/devtools/response.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/devtools/response.rb	2025-11-02 08:23:03.000000000 +0000
@@ -21,7 +21,6 @@ module Selenium
   module WebDriver
     class DevTools
       class Response
-
         attr_accessor :code, :body, :headers
         attr_reader :id
 
@@ -59,7 +58,6 @@ module Selenium
         def inspect
           %(#<#{self.class.name} @id="#{id}" @code="#{code}")
         end
-
       end # Response
     end # DevTools
   end # WebDriver
diff -pruN 4.4.0-1/lib/selenium/webdriver/devtools.rb 4.38.0-1/lib/selenium/webdriver/devtools.rb
--- 4.4.0-1/lib/selenium/webdriver/devtools.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/devtools.rb	2025-11-02 08:23:03.000000000 +0000
@@ -28,10 +28,10 @@ module Selenium
       autoload :Request, 'selenium/webdriver/devtools/request'
       autoload :Response, 'selenium/webdriver/devtools/response'
 
-      def initialize(url:)
+      def initialize(url:, target_type:)
         @ws = WebSocketConnection.new(url: url)
         @session_id = nil
-        start_session
+        start_session(target_type: target_type)
       end
 
       def close
@@ -52,7 +52,17 @@ module Selenium
       end
 
       def method_missing(method, *_args)
-        desired_class = "Selenium::DevTools::V#{Selenium::DevTools.version}::#{method.capitalize}"
+        namespace = "Selenium::DevTools::V#{Selenium::DevTools.version}"
+        methods_to_classes = "#{namespace}::METHODS_TO_CLASSES"
+
+        desired_class = if Object.const_defined?(methods_to_classes)
+                          # selenium-devtools 0.113 and newer
+                          "#{namespace}::#{Object.const_get(methods_to_classes)[method]}"
+                        else
+                          # selenium-devtools 0.112 and older
+                          "#{namespace}::#{method.capitalize}"
+                        end
+
         return unless Object.const_defined?(desired_class)
 
         self.class.class_eval do
@@ -71,17 +81,18 @@ module Selenium
 
       private
 
-      def start_session
+      def start_session(target_type:)
         targets = target.get_targets.dig('result', 'targetInfos')
-        page_target = targets.find { |target| target['type'] == 'page' }
-        session = target.attach_to_target(target_id: page_target['targetId'], flatten: true)
+        found_target = targets.find { |target| target['type'] == target_type }
+        raise Error::WebDriverError, "Target type '#{target_type}' not found" unless found_target
+
+        session = target.attach_to_target(target_id: found_target['targetId'], flatten: true)
         @session_id = session.dig('result', 'sessionId')
       end
 
       def error_message(error)
         [error['code'], error['message'], error['data']].join(': ')
       end
-
     end # DevTools
   end # WebDriver
 end # Selenium
diff -pruN 4.4.0-1/lib/selenium/webdriver/edge/driver.rb 4.38.0-1/lib/selenium/webdriver/edge/driver.rb
--- 4.4.0-1/lib/selenium/webdriver/edge/driver.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/edge/driver.rb	2025-11-02 08:23:03.000000000 +0000
@@ -17,18 +17,24 @@
 # specific language governing permissions and limitations
 # under the License.
 
-require 'selenium/webdriver/chrome/driver'
+require 'selenium/webdriver/chromium/driver'
 
 module Selenium
   module WebDriver
     module Edge
-
       #
       # Driver implementation for Microsoft Edge.
       # @api private
       #
 
-      class Driver < Selenium::WebDriver::Chrome::Driver
+      class Driver < Chromium::Driver
+        include LocalDriver
+
+        def initialize(options: nil, service: nil, url: nil, **)
+          caps, url = initialize_local_driver(options, service, url)
+          super(caps: caps, url: url, **)
+        end
+
         def browser
           :edge
         end
diff -pruN 4.4.0-1/lib/selenium/webdriver/edge/features.rb 4.38.0-1/lib/selenium/webdriver/edge/features.rb
--- 4.4.0-1/lib/selenium/webdriver/edge/features.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/edge/features.rb	2025-11-02 08:23:03.000000000 +0000
@@ -17,14 +17,13 @@
 # specific language governing permissions and limitations
 # under the License.
 
-require 'selenium/webdriver/chrome/features'
+require 'selenium/webdriver/chromium/features'
 
 module Selenium
   module WebDriver
     module Edge
       module Features
-
-        include WebDriver::Chrome::Features
+        include WebDriver::Chromium::Features
 
         EDGE_COMMANDS = {
           get_cast_sinks: [:get, 'session/:session_id/ms/cast/get_sinks'],
@@ -36,8 +35,12 @@ module Selenium
           send_command: [:post, 'session/:session_id/ms/cdp/execute']
         }.freeze
 
+        def command_list
+          EDGE_COMMANDS.merge(CHROMIUM_COMMANDS).merge(self.class::COMMANDS)
+        end
+
         def commands(command)
-          EDGE_COMMANDS[command] || Chrome::Features::CHROME_COMMANDS[command] || self.class::COMMANDS[command]
+          command_list[command]
         end
       end # Bridge
     end # Edge
diff -pruN 4.4.0-1/lib/selenium/webdriver/edge/options.rb 4.38.0-1/lib/selenium/webdriver/edge/options.rb
--- 4.4.0-1/lib/selenium/webdriver/edge/options.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/edge/options.rb	2025-11-02 08:23:03.000000000 +0000
@@ -17,23 +17,35 @@
 # specific language governing permissions and limitations
 # under the License.
 
-require 'selenium/webdriver/chrome/options'
+require 'selenium/webdriver/chromium/options'
 
 module Selenium
   module WebDriver
     module Edge
-      class Options < Selenium::WebDriver::Chrome::Options
+      class Options < Chromium::Options
         KEY = 'ms:edgeOptions'
         BROWSER = 'MicrosoftEdge'
 
-        protected
+        #
+        # Changes the browser name enable webview2
+        # see: https://learn.microsoft.com/en-us/microsoft-edge/webview2/how-to/webdriver
+        # Automation of WebView2 apps with Microsoft Edge WebDriver
+        #
+        # @example Enable webview2
+        #   options = Selenium::WebDriver::Edge::Options.new
+        #   options.webview2!
+        #
 
-        def enable_logging(browser_options)
-          browser_options['ms:loggingPrefs'] = @logging_prefs
+        def webview2!
+          @options[:browser_name] = 'webview2'
         end
 
         private
 
+        def enable_logging(browser_options)
+          browser_options['ms:loggingPrefs'] = @logging_prefs
+        end
+
         def binary_path
           Edge.path
         end
diff -pruN 4.4.0-1/lib/selenium/webdriver/edge/profile.rb 4.38.0-1/lib/selenium/webdriver/edge/profile.rb
--- 4.4.0-1/lib/selenium/webdriver/edge/profile.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/edge/profile.rb	2025-11-02 08:23:03.000000000 +0000
@@ -17,7 +17,7 @@
 # specific language governing permissions and limitations
 # under the License.
 
-require 'selenium/webdriver/chrome/profile'
+require 'selenium/webdriver/chromium/profile'
 
 module Selenium
   module WebDriver
@@ -26,7 +26,7 @@ module Selenium
       # @private
       #
 
-      class Profile < Selenium::WebDriver::Chrome::Profile
+      class Profile < Chromium::Profile
       end # Profile
     end # Edge
   end # WebDriver
diff -pruN 4.4.0-1/lib/selenium/webdriver/edge/service.rb 4.38.0-1/lib/selenium/webdriver/edge/service.rb
--- 4.4.0-1/lib/selenium/webdriver/edge/service.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/edge/service.rb	2025-11-02 08:23:03.000000000 +0000
@@ -17,19 +17,20 @@
 # specific language governing permissions and limitations
 # under the License.
 
-require 'selenium/webdriver/chrome/service'
-
 module Selenium
   module WebDriver
     module Edge
-      class Service < Selenium::WebDriver::Chrome::Service
+      class Service < WebDriver::Service
         DEFAULT_PORT = 9515
         EXECUTABLE = 'msedgedriver'
-        MISSING_TEXT = <<~ERROR
-          Unable to find msedgedriver. Please download the server from
-          https://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver/ and place it somewhere on your PATH.
-        ERROR
         SHUTDOWN_SUPPORTED = true
+        DRIVER_PATH_ENV_KEY = 'SE_EDGEDRIVER'
+        def log
+          return @log unless @log.is_a? String
+
+          @args << "--log-path=#{@log}"
+          @log = nil
+        end
       end # Service
     end # Edge
   end # WebDriver
diff -pruN 4.4.0-1/lib/selenium/webdriver/edge.rb 4.38.0-1/lib/selenium/webdriver/edge.rb
--- 4.4.0-1/lib/selenium/webdriver/edge.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/edge.rb	2025-11-02 08:23:03.000000000 +0000
@@ -17,8 +17,6 @@
 # specific language governing permissions and limitations
 # under the License.
 
-require 'net/http'
-
 module Selenium
   module WebDriver
     module Edge
diff -pruN 4.4.0-1/lib/selenium/webdriver/firefox/driver.rb 4.38.0-1/lib/selenium/webdriver/firefox/driver.rb
--- 4.4.0-1/lib/selenium/webdriver/firefox/driver.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/firefox/driver.rb	2025-11-02 08:23:03.000000000 +0000
@@ -20,7 +20,6 @@
 module Selenium
   module WebDriver
     module Firefox
-
       #
       # Driver implementation for Firefox using GeckoDriver.
       # @api private
@@ -31,31 +30,19 @@ module Selenium
                       DriverExtensions::FullPageScreenshot,
                       DriverExtensions::HasContext,
                       DriverExtensions::HasBiDi,
-                      DriverExtensions::HasDevTools,
                       DriverExtensions::HasLogEvents,
                       DriverExtensions::HasNetworkInterception,
-                      DriverExtensions::HasWebStorage,
                       DriverExtensions::PrintsPage].freeze
 
-        def browser
-          :firefox
-        end
-
-        private
+        include LocalDriver
 
-        def devtools_url
-          if capabilities['moz:debuggerAddress'].nil?
-            raise(Error::WebDriverError, "DevTools is not supported by this version of Firefox; use v85 or higher")
-          end
-
-          uri = URI("http://#{capabilities['moz:debuggerAddress']}")
-          response = Net::HTTP.get(uri.hostname, '/json/version', uri.port)
-
-          JSON.parse(response)['webSocketDebuggerUrl']
+        def initialize(options: nil, service: nil, url: nil, **)
+          caps, url = initialize_local_driver(options, service, url)
+          super(caps: caps, url: url, **)
         end
 
-        def devtools_version
-          Firefox::DEVTOOLS_VERSION
+        def browser
+          :firefox
         end
       end # Driver
     end # Firefox
diff -pruN 4.4.0-1/lib/selenium/webdriver/firefox/features.rb 4.38.0-1/lib/selenium/webdriver/firefox/features.rb
--- 4.4.0-1/lib/selenium/webdriver/firefox/features.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/firefox/features.rb	2025-11-02 08:23:03.000000000 +0000
@@ -21,7 +21,6 @@ module Selenium
   module WebDriver
     module Firefox
       module Features
-
         FIREFOX_COMMANDS = {
           get_context: [:get, 'session/:session_id/moz/context'],
           set_context: [:post, 'session/:session_id/moz/context'],
@@ -30,12 +29,20 @@ module Selenium
           full_page_screenshot: [:get, 'session/:session_id/moz/screenshot/full']
         }.freeze
 
+        def command_list
+          FIREFOX_COMMANDS.merge(self.class::COMMANDS)
+        end
+
         def commands(command)
-          FIREFOX_COMMANDS[command] || self.class::COMMANDS[command]
+          command_list[command]
         end
 
         def install_addon(path, temporary)
-          addon = File.open(path, 'rb') { |crx_file| Base64.strict_encode64 crx_file.read }
+          addon = if File.directory?(path)
+                    Zipper.zip(path)
+                  else
+                    File.open(path, 'rb') { |crx_file| Base64.strict_encode64 crx_file.read }
+                  end
 
           payload = {addon: addon}
           payload[:temporary] = temporary unless temporary.nil?
diff -pruN 4.4.0-1/lib/selenium/webdriver/firefox/options.rb 4.38.0-1/lib/selenium/webdriver/firefox/options.rb
--- 4.4.0-1/lib/selenium/webdriver/firefox/options.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/firefox/options.rb	2025-11-02 08:23:03.000000000 +0000
@@ -45,7 +45,7 @@ module Selenium
         #
         # @example
         #   options = Selenium::WebDriver::Firefox::Options.new(args: ['--host=127.0.0.1'])
-        #   driver = Selenium::WebDriver.for :firefox, capabilities: options
+        #   driver = Selenium::WebDriver.for :firefox, options: options
         #
         # @param [Hash] opts the pre-defined options to create the Firefox::Options with
         # @option opts [String] :binary Path to the Firefox executable to use
@@ -57,12 +57,16 @@ module Selenium
         #
 
         def initialize(log_level: nil, **opts)
-          @debugger_address = opts.delete(:debugger_address)
+          @debugger_address = opts.delete(:debugger_address) { true }
+          opts[:accept_insecure_certs] = true unless opts.key?(:accept_insecure_certs)
 
           super(**opts)
 
           @options[:args] ||= []
           @options[:prefs] ||= {}
+          # https://fxdx.dev/deprecating-cdp-support-in-firefox-embracing-the-future-with-webdriver-bidi/.
+          # Enable BiDi only
+          @options[:prefs]['remote.active-protocols'] = 1
           @options[:env] ||= {}
           @options[:log] ||= {level: log_level} if log_level
 
@@ -99,18 +103,6 @@ module Selenium
         end
 
         #
-        # Run Firefox in headless mode.
-        #
-        # @example Enable headless mode
-        #   options = Selenium::WebDriver::Firefox::Options.new
-        #   options.headless!
-        #
-
-        def headless!
-          add_argument '-headless'
-        end
-
-        #
         # Sets Firefox profile.
         #
         # @example Set the custom profile
@@ -177,7 +169,7 @@ module Selenium
         end
 
         def camelize?(key)
-          key != "prefs"
+          key != 'prefs'
         end
       end # Options
     end # Firefox
diff -pruN 4.4.0-1/lib/selenium/webdriver/firefox/profile.rb 4.38.0-1/lib/selenium/webdriver/firefox/profile.rb
--- 4.4.0-1/lib/selenium/webdriver/firefox/profile.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/firefox/profile.rb	2025-11-02 08:23:03.000000000 +0000
@@ -24,17 +24,23 @@ module Selenium
         include ProfileHelper
 
         VALID_PREFERENCE_TYPES = [TrueClass, FalseClass, Integer, Float, String].freeze
+        WEBDRIVER_PREFS = {
+          port: 'webdriver_firefox_port',
+          log_file: 'webdriver.log.file'
+        }.freeze
 
         DEFAULT_PREFERENCES = {
-          "browser.newtabpage.enabled" => false,
-          "browser.startup.homepage" => "about:blank",
-          "browser.usedOnWindows10.introURL" => "about:blank",
-          "network.captive-portal-service.enabled" => false,
-          "security.csp.enable" => false
+          'browser.newtabpage.enabled' => false,
+          'browser.startup.homepage' => 'about:blank',
+          'browser.usedOnWindows10.introURL' => 'about:blank',
+          'network.captive-portal-service.enabled' => false,
+          'security.csp.enable' => false
         }.freeze
 
-        attr_reader   :name, :log_file
-        attr_writer   :secure_ssl, :load_no_focus_lib
+        LOCK_FILES = %w[.parentlock parent.lock lock].freeze
+
+        attr_reader :name, :log_file
+        attr_writer :secure_ssl, :load_no_focus_lib
 
         class << self
           def ini
@@ -143,7 +149,7 @@ module Selenium
           end
         end
 
-        alias_method :as_json, :encoded
+        alias as_json encoded
 
         private
 
@@ -160,7 +166,7 @@ module Selenium
           destination = File.join(directory, 'extensions')
 
           @extensions.each do |name, extension|
-            WebDriver.logger.debug({extenstion: name}.inspect)
+            WebDriver.logger.debug({extension: name}.inspect, id: :firefox_profile)
             extension.write_to(destination)
           end
         end
@@ -176,7 +182,7 @@ module Selenium
         end
 
         def delete_lock_files(directory)
-          %w[.parentlock parent.lock].each do |name|
+          LOCK_FILES.each do |name|
             FileUtils.rm_f File.join(directory, name)
           end
         end
@@ -204,8 +210,8 @@ module Selenium
           File.read(path).split("\n").each do |line|
             next unless line =~ /user_pref\("([^"]+)"\s*,\s*(.+?)\);/
 
-            key = Regexp.last_match(1).strip
-            value = Regexp.last_match(2).strip
+            key = Regexp.last_match(1)&.strip
+            value = Regexp.last_match(2)&.strip
 
             # wrap the value in an array to make it a valid JSON string.
             prefs[key] = JSON.parse("[#{value}]").first
@@ -221,7 +227,9 @@ module Selenium
             end
           end
         end
-      end # Profile
+      end
+
+      # Profile
     end # Firefox
   end # WebDriver
 end # Selenium
diff -pruN 4.4.0-1/lib/selenium/webdriver/firefox/profiles_ini.rb 4.38.0-1/lib/selenium/webdriver/firefox/profiles_ini.rb
--- 4.4.0-1/lib/selenium/webdriver/firefox/profiles_ini.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/firefox/profiles_ini.rb	2025-11-02 08:23:03.000000000 +0000
@@ -52,7 +52,7 @@ module Selenium
             when /^\[Profile/
               name, path = nil if path_for(name, is_relative, path)
             when /^Name=(.+)$/
-              name = Regexp.last_match(1).strip
+              name = Regexp.last_match(1)&.strip
             when /^IsRelative=(.+)$/
               is_relative = Regexp.last_match(1).strip == '1'
             when /^Path=(.+)$/
diff -pruN 4.4.0-1/lib/selenium/webdriver/firefox/service.rb 4.38.0-1/lib/selenium/webdriver/firefox/service.rb
--- 4.4.0-1/lib/selenium/webdriver/firefox/service.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/firefox/service.rb	2025-11-02 08:23:03.000000000 +0000
@@ -23,24 +23,16 @@ module Selenium
       class Service < WebDriver::Service
         DEFAULT_PORT = 4444
         EXECUTABLE = 'geckodriver'
-        MISSING_TEXT = <<~ERROR
-          Unable to find Mozilla geckodriver. Please download the server from
-          https://github.com/mozilla/geckodriver/releases and place it somewhere on your PATH.
-          More info at https://developer.mozilla.org/en-US/docs/Mozilla/QA/Marionette/WebDriver.
-        ERROR
         SHUTDOWN_SUPPORTED = false
+        DRIVER_PATH_ENV_KEY = 'SE_GECKODRIVER'
 
-        private
-
-        # NOTE: This processing is deprecated
-        def extract_service_args(driver_opts)
-          driver_args = super
-          driver_opts = driver_opts.dup
-          driver_args << "--binary=#{driver_opts[:binary]}" if driver_opts.key?(:binary)
-          driver_args << "--log=#{driver_opts[:log]}" if driver_opts.key?(:log)
-          driver_args << "--marionette-port=#{driver_opts[:marionette_port]}" if driver_opts.key?(:marionette_port)
-          driver_args << "--host=#{driver_opts[:host]}" if driver_opts.key?(:host)
-          driver_args
+        def initialize(path: nil, port: nil, log: nil, args: nil)
+          args ||= []
+          unless args.any? { |arg| arg.include?('--connect-existing') || arg.include?('--websocket-port') }
+            args << '--websocket-port'
+            args << '0'
+          end
+          super
         end
       end # Service
     end # Firefox
diff -pruN 4.4.0-1/lib/selenium/webdriver/ie/driver.rb 4.38.0-1/lib/selenium/webdriver/ie/driver.rb
--- 4.4.0-1/lib/selenium/webdriver/ie/driver.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/ie/driver.rb	2025-11-02 08:23:03.000000000 +0000
@@ -20,7 +20,6 @@
 module Selenium
   module WebDriver
     module IE
-
       #
       # Driver implementation for Internet Explorer supporting
       # both OSS and W3C dialects of JSON wire protocol.
@@ -28,7 +27,14 @@ module Selenium
       #
 
       class Driver < WebDriver::Driver
-        EXTENSIONS = [DriverExtensions::HasWebStorage].freeze
+        EXTENSIONS = [].freeze
+
+        include LocalDriver
+
+        def initialize(options: nil, service: nil, url: nil, **)
+          caps, url = initialize_local_driver(options, service, url)
+          super(caps: caps, url: url, **)
+        end
 
         def browser
           :internet_explorer
diff -pruN 4.4.0-1/lib/selenium/webdriver/ie/features.rb 4.38.0-1/lib/selenium/webdriver/ie/features.rb
--- 4.4.0-1/lib/selenium/webdriver/ie/features.rb	1970-01-01 00:00:00.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/ie/features.rb	2025-11-02 08:23:03.000000000 +0000
@@ -0,0 +1,34 @@
+# frozen_string_literal: true
+
+# Licensed to the Software Freedom Conservancy (SFC) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The SFC licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+module Selenium
+  module WebDriver
+    module IE
+      module Features
+        def command_list
+          self.class::COMMANDS
+        end
+
+        def commands(command)
+          command_list[command]
+        end
+      end # Bridge
+    end # Ie
+  end # WebDriver
+end # Selenium
diff -pruN 4.4.0-1/lib/selenium/webdriver/ie/options.rb 4.38.0-1/lib/selenium/webdriver/ie/options.rb
--- 4.4.0-1/lib/selenium/webdriver/ie/options.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/ie/options.rb	2025-11-02 08:23:03.000000000 +0000
@@ -41,7 +41,9 @@ module Selenium
           use_per_process_proxy: 'ie.usePerProcessProxy',
           use_legacy_file_upload_dialog_handling: 'ie.useLegacyFileUploadDialogHandling',
           attach_to_edge_chrome: 'ie.edgechromium',
-          edge_executable_path: 'ie.edgepath'
+          edge_executable_path: 'ie.edgepath',
+          ignore_process_match: 'ie.ignoreprocessmatch',
+          silent: 'silent'
         }.freeze
         BROWSER = 'internet explorer'
 
@@ -52,12 +54,12 @@ module Selenium
         #
         # @example
         #   options = Selenium::WebDriver::IE::Options.new(args: ['--host=127.0.0.1'])
-        #   driver = Selenium::WebDriver.for(:ie, capabilities: options)
+        #   driver = Selenium::WebDriver.for(:ie, options: options)
         #
         # @example
         #   options = Selenium::WebDriver::IE::Options.new
         #   options.element_scroll_behavior = Selenium::WebDriver::IE::Options::SCROLL_BOTTOM
-        #   driver = Selenium::WebDriver.for(:ie, capabilities: options)
+        #   driver = Selenium::WebDriver.for(:ie, options: options)
         #
         # @param [Hash] opts the pre-defined options
         # @option opts [Array<String>] args
@@ -80,7 +82,7 @@ module Selenium
 
         def initialize(**opts)
           @args = (opts.delete(:args) || []).to_set
-          super(**opts)
+          super
 
           @options[:native_events] = true if @options[:native_events].nil?
         end
diff -pruN 4.4.0-1/lib/selenium/webdriver/ie/service.rb 4.38.0-1/lib/selenium/webdriver/ie/service.rb
--- 4.4.0-1/lib/selenium/webdriver/ie/service.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/ie/service.rb	2025-11-02 08:23:03.000000000 +0000
@@ -23,29 +23,8 @@ module Selenium
       class Service < WebDriver::Service
         DEFAULT_PORT = 5555
         EXECUTABLE = 'IEDriverServer'
-        MISSING_TEXT = <<~ERROR
-          Unable to find IEDriverServer. Please download the server from
-          https://www.selenium.dev/downloads/ and place it somewhere on your PATH.
-          More info at https://github.com/SeleniumHQ/selenium/wiki/InternetExplorerDriver.
-        ERROR
         SHUTDOWN_SUPPORTED = true
-
-        private
-
-        # NOTE: This processing is deprecated
-        def extract_service_args(driver_opts)
-          driver_args = super
-          driver_opts = driver_opts.dup
-          driver_args << "--log-level=#{driver_opts[:log_level].to_s.upcase}" if driver_opts.key?(:log_level)
-          driver_args << "--log-file=#{driver_opts[:log_file]}" if driver_opts.key?(:log_file)
-          if driver_opts.key?(:implementation)
-            driver_args << "--implementation=#{driver_opts[:implementation].to_s.upcase}"
-          end
-          driver_args << "--host=#{driver_opts[:host]}" if driver_opts.key?(:host)
-          driver_args << "--extract_path=#{driver_opts[:extract_path]}" if driver_opts.key?(:extract_path)
-          driver_args << "--silent" if driver_opts[:silent] == true
-          driver_args
-        end
+        DRIVER_PATH_ENV_KEY = 'SE_IEDRIVER'
       end # Server
     end # IE
   end # WebDriver
diff -pruN 4.4.0-1/lib/selenium/webdriver/ie.rb 4.38.0-1/lib/selenium/webdriver/ie.rb
--- 4.4.0-1/lib/selenium/webdriver/ie.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/ie.rb	2025-11-02 08:23:03.000000000 +0000
@@ -20,9 +20,10 @@
 module Selenium
   module WebDriver
     module IE
-      autoload :Driver, 'selenium/webdriver/ie/driver'
-      autoload :Options, 'selenium/webdriver/ie/options'
-      autoload :Service, 'selenium/webdriver/ie/service'
+      autoload :Features, 'selenium/webdriver/ie/features'
+      autoload :Driver,   'selenium/webdriver/ie/driver'
+      autoload :Options,  'selenium/webdriver/ie/options'
+      autoload :Service,  'selenium/webdriver/ie/service'
     end # IE
   end # WebDriver
 end # Selenium
diff -pruN 4.4.0-1/lib/selenium/webdriver/remote/bidi_bridge.rb 4.38.0-1/lib/selenium/webdriver/remote/bidi_bridge.rb
--- 4.4.0-1/lib/selenium/webdriver/remote/bidi_bridge.rb	1970-01-01 00:00:00.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/remote/bidi_bridge.rb	2025-11-02 08:23:03.000000000 +0000
@@ -0,0 +1,66 @@
+# frozen_string_literal: true
+
+# Licensed to the Software Freedom Conservancy (SFC) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The SFC licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+module Selenium
+  module WebDriver
+    module Remote
+      class BiDiBridge < Bridge
+        attr_reader :bidi
+
+        def create_session(capabilities)
+          super
+          socket_url = @capabilities[:web_socket_url]
+          @bidi = Selenium::WebDriver::BiDi.new(url: socket_url)
+        end
+
+        def get(url)
+          browsing_context.navigate(url)
+        end
+
+        def go_back
+          browsing_context.traverse_history(-1)
+        end
+
+        def go_forward
+          browsing_context.traverse_history(1)
+        end
+
+        def refresh
+          browsing_context.reload
+        end
+
+        def quit
+          super
+        ensure
+          bidi.close
+        end
+
+        def close
+          execute(:close_window).tap { |handles| bidi.close if handles.empty? }
+        end
+
+        private
+
+        def browsing_context
+          @browsing_context ||= WebDriver::BiDi::BrowsingContext.new(self)
+        end
+      end # BiDiBridge
+    end # Remote
+  end # WebDriver
+end # Selenium
diff -pruN 4.4.0-1/lib/selenium/webdriver/remote/bridge/commands.rb 4.38.0-1/lib/selenium/webdriver/remote/bridge/commands.rb
--- 4.4.0-1/lib/selenium/webdriver/remote/bridge/commands.rb	1970-01-01 00:00:00.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/remote/bridge/commands.rb	2025-11-02 08:23:03.000000000 +0000
@@ -0,0 +1,176 @@
+# frozen_string_literal: true
+
+# Licensed to the Software Freedom Conservancy (SFC) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The SFC licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+module Selenium
+  module WebDriver
+    module Remote
+      #
+      # https://w3c.github.io/webdriver/#endpoints
+      # @api private
+      #
+
+      class Bridge
+        COMMANDS = {
+          status: [:get, 'status'],
+
+          #
+          # session handling
+          #
+
+          new_session: [:post, 'session'],
+          delete_session: [:delete, 'session/:session_id'],
+
+          #
+          # basic driver
+          #
+
+          get: [:post, 'session/:session_id/url'],
+          get_current_url: [:get, 'session/:session_id/url'],
+          back: [:post, 'session/:session_id/back'],
+          forward: [:post, 'session/:session_id/forward'],
+          refresh: [:post, 'session/:session_id/refresh'],
+          get_title: [:get, 'session/:session_id/title'],
+
+          #
+          # window and Frame handling
+          #
+
+          get_window_handle: [:get, 'session/:session_id/window'],
+          new_window: [:post, 'session/:session_id/window/new'],
+          close_window: [:delete, 'session/:session_id/window'],
+          switch_to_window: [:post, 'session/:session_id/window'],
+          get_window_handles: [:get, 'session/:session_id/window/handles'],
+          fullscreen_window: [:post, 'session/:session_id/window/fullscreen'],
+          minimize_window: [:post, 'session/:session_id/window/minimize'],
+          maximize_window: [:post, 'session/:session_id/window/maximize'],
+          set_window_rect: [:post, 'session/:session_id/window/rect'],
+          get_window_rect: [:get, 'session/:session_id/window/rect'],
+          switch_to_frame: [:post, 'session/:session_id/frame'],
+          switch_to_parent_frame: [:post, 'session/:session_id/frame/parent'],
+
+          #
+          # element
+          #
+
+          find_element: [:post, 'session/:session_id/element'],
+          find_elements: [:post, 'session/:session_id/elements'],
+          find_child_element: [:post, 'session/:session_id/element/:id/element'],
+          find_child_elements: [:post, 'session/:session_id/element/:id/elements'],
+          find_shadow_child_element: [:post, 'session/:session_id/shadow/:id/element'],
+          find_shadow_child_elements: [:post, 'session/:session_id/shadow/:id/elements'],
+          get_active_element: [:get, 'session/:session_id/element/active'],
+          get_element_shadow_root: [:get, 'session/:session_id/element/:id/shadow'],
+          is_element_selected: [:get, 'session/:session_id/element/:id/selected'],
+          get_element_attribute: [:get, 'session/:session_id/element/:id/attribute/:name'],
+          get_element_property: [:get, 'session/:session_id/element/:id/property/:name'],
+          get_element_css_value: [:get, 'session/:session_id/element/:id/css/:property_name'],
+          get_element_aria_role: [:get, 'session/:session_id/element/:id/computedrole'],
+          get_element_aria_label: [:get, 'session/:session_id/element/:id/computedlabel'],
+          get_element_text: [:get, 'session/:session_id/element/:id/text'],
+          get_element_tag_name: [:get, 'session/:session_id/element/:id/name'],
+          get_element_rect: [:get, 'session/:session_id/element/:id/rect'],
+          is_element_enabled: [:get, 'session/:session_id/element/:id/enabled'],
+
+          #
+          # document handling
+          #
+
+          get_page_source: [:get, 'session/:session_id/source'],
+          execute_script: [:post, 'session/:session_id/execute/sync'],
+          execute_async_script: [:post, 'session/:session_id/execute/async'],
+
+          #
+          # cookies
+          #
+
+          get_all_cookies: [:get, 'session/:session_id/cookie'],
+          get_cookie: [:get, 'session/:session_id/cookie/:name'],
+          add_cookie: [:post, 'session/:session_id/cookie'],
+          delete_cookie: [:delete, 'session/:session_id/cookie/:name'],
+          delete_all_cookies: [:delete, 'session/:session_id/cookie'],
+
+          #
+          # timeouts
+          #
+
+          get_timeouts: [:get, 'session/:session_id/timeouts'],
+          set_timeout: [:post, 'session/:session_id/timeouts'],
+
+          #
+          # actions
+          #
+
+          actions: [:post, 'session/:session_id/actions'],
+          release_actions: [:delete, 'session/:session_id/actions'],
+          print_page: [:post, 'session/:session_id/print'],
+
+          #
+          # Element Operations
+          #
+
+          element_click: [:post, 'session/:session_id/element/:id/click'],
+          element_clear: [:post, 'session/:session_id/element/:id/clear'],
+          element_send_keys: [:post, 'session/:session_id/element/:id/value'],
+
+          #
+          # alerts
+          #
+
+          dismiss_alert: [:post, 'session/:session_id/alert/dismiss'],
+          accept_alert: [:post, 'session/:session_id/alert/accept'],
+          get_alert_text: [:get, 'session/:session_id/alert/text'],
+          send_alert_text: [:post, 'session/:session_id/alert/text'],
+
+          #
+          # screenshot
+          #
+
+          take_screenshot: [:get, 'session/:session_id/screenshot'],
+          take_element_screenshot: [:get, 'session/:session_id/element/:id/screenshot'],
+
+          #
+          # virtual-authenticator
+          #
+
+          add_virtual_authenticator: [:post, 'session/:session_id/webauthn/authenticator'],
+          remove_virtual_authenticator: [:delete, 'session/:session_id/webauthn/authenticator/:authenticatorId'],
+          add_credential: [:post, 'session/:session_id/webauthn/authenticator/:authenticatorId/credential'],
+          get_credentials: [:get, 'session/:session_id/webauthn/authenticator/:authenticatorId/credentials'],
+          remove_credential: [:delete,
+                              'session/:session_id/webauthn/authenticator/:authenticatorId/credentials/:credentialId'],
+          remove_all_credentials: [:delete, 'session/:session_id/webauthn/authenticator/:authenticatorId/credentials'],
+          set_user_verified: [:post, 'session/:session_id/webauthn/authenticator/:authenticatorId/uv'],
+
+          #
+          # federated-credential management
+          #
+
+          get_fedcm_title: [:get, 'session/:session_id/fedcm/gettitle'],
+          get_fedcm_dialog_type: [:get, 'session/:session_id/fedcm/getdialogtype'],
+          get_fedcm_account_list: [:get, 'session/:session_id/fedcm/accountlist'],
+          click_fedcm_dialog_button: [:post, 'session/:session_id/fedcm/clickdialogbutton'],
+          cancel_fedcm_dialog: [:post, 'session/:session_id/fedcm/canceldialog'],
+          select_fedcm_account: [:post, 'session/:session_id/fedcm/selectaccount'],
+          set_fedcm_delay: [:post, 'session/:session_id/fedcm/setdelayenabled'],
+          reset_fedcm_cooldown: [:post, 'session/:session_id/fedcm/resetcooldown']
+        }.freeze
+      end # Bridge
+    end # Remote
+  end # WebDriver
+end # Selenium
diff -pruN 4.4.0-1/lib/selenium/webdriver/remote/bridge/locator_converter.rb 4.38.0-1/lib/selenium/webdriver/remote/bridge/locator_converter.rb
--- 4.4.0-1/lib/selenium/webdriver/remote/bridge/locator_converter.rb	1970-01-01 00:00:00.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/remote/bridge/locator_converter.rb	2025-11-02 08:23:03.000000000 +0000
@@ -0,0 +1,76 @@
+# frozen_string_literal: true
+
+# Licensed to the Software Freedom Conservancy (SFC) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The SFC licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+module Selenium
+  module WebDriver
+    module Remote
+      class Bridge
+        class LocatorConverter
+          ESCAPE_CSS_REGEXP = /(['"\\#.:;,!?+<>=~*^$|%&@`{}\-\[\]()])/
+          UNICODE_CODE_POINT = 30
+
+          #
+          # Converts a locator to a specification compatible one.
+          # @param [String, Symbol] how
+          # @param [String] what
+          #
+
+          def convert(how, what)
+            how = SearchContext.finders[how.to_sym] || how
+
+            case how
+            when 'class name'
+              how = 'css selector'
+              what = ".#{escape_css(what.to_s)}"
+            when 'id'
+              how = 'css selector'
+              what = "##{escape_css(what.to_s)}"
+            when 'name'
+              how = 'css selector'
+              what = "*[name='#{escape_css(what.to_s)}']"
+            end
+
+            if what.is_a?(Hash)
+              what = what.each_with_object({}) do |(h, w), hash|
+                h, w = convert(h.to_s, w)
+                hash[h] = w
+              end
+            end
+
+            [how, what]
+          end
+
+          private
+
+          #
+          # Escapes invalid characters in CSS selector.
+          # @see https://mathiasbynens.be/notes/css-escapes
+          #
+
+          def escape_css(string)
+            string = string.gsub(ESCAPE_CSS_REGEXP) { |match| "\\#{match}" }
+            string = "\\#{UNICODE_CODE_POINT + Integer(string[0])} #{string[1..]}" if string[0]&.match?(/[[:digit:]]/)
+
+            string
+          end
+        end # LocatorConverter
+      end # Bridge
+    end # Remote
+  end # WebDriver
+end # Selenium
diff -pruN 4.4.0-1/lib/selenium/webdriver/remote/bridge.rb 4.38.0-1/lib/selenium/webdriver/remote/bridge.rb
--- 4.4.0-1/lib/selenium/webdriver/remote/bridge.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/remote/bridge.rb	2025-11-02 08:23:03.000000000 +0000
@@ -21,6 +21,9 @@ module Selenium
   module WebDriver
     module Remote
       class Bridge
+        autoload :COMMANDS, 'selenium/webdriver/remote/bridge/commands'
+        autoload :LocatorConverter, 'selenium/webdriver/remote/bridge/locator_converter'
+
         include Atoms
 
         PORT = 4444
@@ -28,6 +31,25 @@ module Selenium
         attr_accessor :http, :file_detector
         attr_reader :capabilities
 
+        class << self
+          attr_reader :extra_commands
+          attr_writer :element_class, :locator_converter
+
+          def add_command(name, verb, url, &block)
+            @extra_commands ||= {}
+            @extra_commands[name] = [verb, url]
+            define_method(name, &block)
+          end
+
+          def locator_converter
+            @locator_converter ||= LocatorConverter.new
+          end
+
+          def element_class
+            @element_class ||= Element
+          end
+        end
+
         #
         # Initializes the bridge with the given server URL
         # @param [String, URI] url url for the remote server
@@ -42,6 +64,8 @@ module Selenium
           @http = http_client || Http::Default.new
           @http.server_url = uri
           @file_detector = nil
+
+          @locator_converter = self.class.locator_converter
         end
 
         #
@@ -59,14 +83,16 @@ module Selenium
           @capabilities = Capabilities.json_create(capabilities)
 
           case @capabilities[:browser_name]
-          when 'chrome'
+          when 'chrome', 'chrome-headless-shell'
             extend(WebDriver::Chrome::Features)
           when 'firefox'
             extend(WebDriver::Firefox::Features)
-          when 'msedge'
+          when 'msedge', 'MicrosoftEdge'
             extend(WebDriver::Edge::Features)
           when 'Safari', 'Safari Technology Preview'
             extend(WebDriver::Safari::Features)
+          when 'internet explorer'
+            extend(WebDriver::IE::Features)
           end
         end
 
@@ -81,7 +107,7 @@ module Selenium
         def browser
           @browser ||= begin
             name = @capabilities.browser_name
-            name ? name.tr(' ', '_').downcase.to_sym : 'unknown'
+            name ? name.tr(' -', '_').downcase.to_sym : 'unknown'
           end
         end
 
@@ -186,6 +212,7 @@ module Selenium
           execute :delete_session
           http.close
         rescue *QUIT_ERRORS
+          nil
         end
 
         def close
@@ -270,58 +297,6 @@ module Selenium
         end
 
         #
-        # HTML 5
-        #
-
-        def local_storage_item(key, value = nil)
-          if value
-            execute_script("localStorage.setItem('#{key}', '#{value}')")
-          else
-            execute_script("return localStorage.getItem('#{key}')")
-          end
-        end
-
-        def remove_local_storage_item(key)
-          execute_script("localStorage.removeItem('#{key}')")
-        end
-
-        def local_storage_keys
-          execute_script('return Object.keys(localStorage)')
-        end
-
-        def clear_local_storage
-          execute_script('localStorage.clear()')
-        end
-
-        def local_storage_size
-          execute_script('return localStorage.length')
-        end
-
-        def session_storage_item(key, value = nil)
-          if value
-            execute_script("sessionStorage.setItem('#{key}', '#{value}')")
-          else
-            execute_script("return sessionStorage.getItem('#{key}')")
-          end
-        end
-
-        def remove_session_storage_item(key)
-          execute_script("sessionStorage.removeItem('#{key}')")
-        end
-
-        def session_storage_keys
-          execute_script('return Object.keys(sessionStorage)')
-        end
-
-        def clear_session_storage
-          execute_script('sessionStorage.clear()')
-        end
-
-        def session_storage_size
-          execute_script('return sessionStorage.length')
-        end
-
-        #
         # javascript execution
         #
 
@@ -348,6 +323,8 @@ module Selenium
         end
 
         def delete_cookie(name)
+          raise ArgumentError, 'Cookie name cannot be null or empty' if name.nil? || name.to_s.strip.empty?
+
           execute :delete_cookie, name: name
         end
 
@@ -367,18 +344,10 @@ module Selenium
         # actions
         #
 
-        def action(deprecated_async = nil, async: false, devices: [], duration: 250)
-          ActionBuilder.new self, nil, nil, deprecated_async, async: async, devices: devices, duration: duration
-        end
-        alias_method :actions, :action
-
-        def mouse
-          raise Error::UnsupportedOperationError, '#mouse is no longer supported, use #action instead'
-        end
-
-        def keyboard
-          raise Error::UnsupportedOperationError, '#keyboard is no longer supported, use #action instead'
+        def action(async: false, devices: [], duration: 250)
+          ActionBuilder.new self, async: async, devices: devices, duration: duration
         end
+        alias actions action
 
         def send_actions(data)
           execute :actions, {}, {actions: data}
@@ -397,35 +366,17 @@ module Selenium
         end
 
         def send_keys_to_element(element, keys)
-          # TODO: rework file detectors before Selenium 4.0
-          if @file_detector
-            local_files = keys.first&.split("\n")&.map { |key| @file_detector.call(Array(key)) }&.compact
-            if local_files.any?
-              keys = local_files.map { |local_file| upload(local_file) }
-              keys = Array(keys.join("\n"))
-            end
-          end
-
-          # Keep .split(//) for backward compatibility for now
+          keys = upload_if_necessary(keys) if @file_detector
           text = keys.join
           execute :element_send_keys, {id: element}, {value: text.chars, text: text}
         end
 
-        def upload(local_file)
-          unless File.file?(local_file)
-            WebDriver.logger.debug("File detector only works with files. #{local_file.inspect} isn`t a file!")
-            raise Error::WebDriverError, "You are trying to work with something that isn't a file."
-          end
-
-          execute :upload_file, {}, {file: Zipper.zip_file(local_file)}
-        end
-
         def clear_element(element)
           execute :element_clear, id: element
         end
 
         def submit_element(element)
-          script = "var form = arguments[0];\n" \
+          script = "/* submitForm */ var form = arguments[0];\n" \
                    "while (form.nodeName != \"FORM\" && form.parentNode) {\n  " \
                    "form = form.parentNode;\n" \
                    "}\n" \
@@ -435,9 +386,9 @@ module Selenium
                    "e.initEvent('submit', true, true);\n" \
                    "if (form.dispatchEvent(e)) { HTMLFormElement.prototype.submit.call(form) }\n"
 
-          execute_script(script, Element::ELEMENT_KEY => element)
+          execute_script(script, Bridge.element_class::ELEMENT_KEY => element)
         rescue Error::JavascriptError
-          raise Error::UnsupportedOperationError, "To submit an element, it must be nested inside a form element"
+          raise Error::UnsupportedOperationError, 'To submit an element, it must be nested inside a form element'
         end
 
         #
@@ -449,7 +400,7 @@ module Selenium
         end
 
         def element_attribute(element, name)
-          WebDriver.logger.info "Using script for :getAttribute of #{name}"
+          WebDriver.logger.debug "Using script for :getAttribute of #{name}", id: :script
           execute_atom :getAttribute, element, name
         end
 
@@ -509,7 +460,7 @@ module Selenium
         end
 
         def element_displayed?(element)
-          WebDriver.logger.info 'Using script for :isDisplayed'
+          WebDriver.logger.debug 'Using script for :isDisplayed', id: :script
           execute_atom :isDisplayed, element
         end
 
@@ -522,13 +473,13 @@ module Selenium
         #
 
         def active_element
-          Element.new self, element_id_from(execute(:get_active_element))
+          Bridge.element_class.new self, element_id_from(execute(:get_active_element))
         end
 
-        alias_method :switch_to_active_element, :active_element
+        alias switch_to_active_element active_element
 
         def find_element_by(how, what, parent_ref = [])
-          how, what = convert_locator(how, what)
+          how, what = @locator_converter.convert(how, what)
 
           return execute_atom(:findElements, Support::RelativeLocator.new(what).as_json).first if how == 'relative'
 
@@ -542,11 +493,11 @@ module Selenium
                  execute :find_element, {}, {using: how, value: what.to_s}
                end
 
-          Element.new self, element_id_from(id)
+          Bridge.element_class.new self, element_id_from(id)
         end
 
         def find_elements_by(how, what, parent_ref = [])
-          how, what = convert_locator(how, what)
+          how, what = @locator_converter.convert(how, what)
 
           return execute_atom :findElements, Support::RelativeLocator.new(what).as_json if how == 'relative'
 
@@ -560,7 +511,7 @@ module Selenium
                   execute :find_elements, {}, {using: how, value: what.to_s}
                 end
 
-          ids.map { |id| Element.new self, element_id_from(id) }
+          ids.map { |id| Bridge.element_class.new self, element_id_from(id) }
         end
 
         def shadow_root(element)
@@ -601,6 +552,55 @@ module Selenium
           execute :set_user_verified, {authenticatorId: authenticator_id}, {isUserVerified: verified}
         end
 
+        #
+        # federated-credential management
+        #
+
+        def cancel_fedcm_dialog
+          execute :cancel_fedcm_dialog
+        end
+
+        def select_fedcm_account(index)
+          execute :select_fedcm_account, {}, {accountIndex: index}
+        end
+
+        def fedcm_dialog_type
+          execute :get_fedcm_dialog_type
+        end
+
+        def fedcm_title
+          execute(:get_fedcm_title).fetch('title')
+        end
+
+        def fedcm_subtitle
+          execute(:get_fedcm_title).fetch('subtitle', nil)
+        end
+
+        def fedcm_account_list
+          execute :get_fedcm_account_list
+        end
+
+        def fedcm_delay(enabled)
+          execute :set_fedcm_delay, {}, {enabled: enabled}
+        end
+
+        def reset_fedcm_cooldown
+          execute :reset_fedcm_cooldown
+        end
+
+        def click_fedcm_dialog_button
+          execute :click_fedcm_dialog_button, {}, {dialogButton: 'ConfirmIdpLoginContinue'}
+        end
+
+        def bidi
+          msg = 'BiDi must be enabled by setting #web_socket_url to true in options class'
+          raise(WebDriver::Error::WebDriverError, msg)
+        end
+
+        def command_list
+          COMMANDS
+        end
+
         private
 
         #
@@ -621,16 +621,16 @@ module Selenium
             raise ArgumentError, "#{opts.inspect} invalid for #{command.inspect}"
           end
 
-          WebDriver.logger.info("-> #{verb.to_s.upcase} #{path}")
+          WebDriver.logger.debug("-> #{verb.to_s.upcase} #{path}", id: :command)
           http.call(verb, path, command_hash)['value']
         end
 
         def escaper
-          @escaper ||= defined?(URI::Parser) ? URI::DEFAULT_PARSER : URI
+          @escaper ||= defined?(URI::RFC2396_PARSER) ? URI::RFC2396_PARSER : URI::DEFAULT_PARSER
         end
 
         def commands(command)
-          COMMANDS[command]
+          command_list[command] || Bridge.extra_commands[command]
         end
 
         def unwrap_script_result(arg)
@@ -639,7 +639,7 @@ module Selenium
             arg.map { |e| unwrap_script_result(e) }
           when Hash
             element_id = element_id_from(arg)
-            return Element.new(self, element_id) if element_id
+            return Bridge.element_class.new(self, element_id) if element_id
 
             shadow_root_id = shadow_root_id_from(arg)
             return ShadowRoot.new self, shadow_root_id if shadow_root_id
@@ -651,7 +651,7 @@ module Selenium
         end
 
         def element_id_from(id)
-          id['ELEMENT'] || id[Element::ELEMENT_KEY]
+          id['ELEMENT'] || id[Bridge.element_class::ELEMENT_KEY]
         end
 
         def shadow_root_id_from(id)
@@ -662,43 +662,6 @@ module Selenium
           capabilities = {alwaysMatch: capabilities} if !capabilities['alwaysMatch'] && !capabilities['firstMatch']
           {capabilities: capabilities}
         end
-
-        def convert_locator(how, what)
-          how = SearchContext::FINDERS[how.to_sym] || how
-
-          case how
-          when 'class name'
-            how = 'css selector'
-            what = ".#{escape_css(what.to_s)}"
-          when 'id'
-            how = 'css selector'
-            what = "##{escape_css(what.to_s)}"
-          when 'name'
-            how = 'css selector'
-            what = "*[name='#{escape_css(what.to_s)}']"
-          end
-
-          if what.is_a?(Hash)
-            what = what.each_with_object({}) do |(h, w), hash|
-              h, w = convert_locator(h.to_s, w)
-              hash[h] = w
-            end
-          end
-
-          [how, what]
-        end
-
-        ESCAPE_CSS_REGEXP = /(['"\\#.:;,!?+<>=~*^$|%&@`{}\-\[\]()])/.freeze
-        UNICODE_CODE_POINT = 30
-
-        # Escapes invalid characters in CSS selector.
-        # @see https://mathiasbynens.be/notes/css-escapes
-        def escape_css(string)
-          string = string.gsub(ESCAPE_CSS_REGEXP) { |match| "\\#{match}" }
-          string = "\\#{UNICODE_CODE_POINT + Integer(string[0])} #{string[1..]}" if string[0]&.match?(/[[:digit:]]/)
-
-          string
-        end
       end # Bridge
     end # Remote
   end # WebDriver
diff -pruN 4.4.0-1/lib/selenium/webdriver/remote/capabilities.rb 4.38.0-1/lib/selenium/webdriver/remote/capabilities.rb
--- 4.4.0-1/lib/selenium/webdriver/remote/capabilities.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/remote/capabilities.rb	2025-11-02 08:23:03.000000000 +0000
@@ -20,14 +20,12 @@
 module Selenium
   module WebDriver
     module Remote
-
       #
       # Specification of the desired and/or actual capabilities of the browser that the
       # server is being asked to create.
       #
 
       class Capabilities
-
         KNOWN = [
           :browser_name,
           :browser_version,
@@ -50,65 +48,16 @@ module Selenium
             @capabilities[key]
           end
 
-          define_method "#{key}=" do |value|
+          define_method :"#{key}=" do |value|
             @capabilities[key] = value
           end
         end
 
         #
-        # Backward compatibility
-        #
-
-        alias_method :version, :browser_version
-        alias_method :version=, :browser_version=
-        alias_method :platform, :platform_name
-        alias_method :platform=, :platform_name=
-
-        #
         # Convenience methods for the common choices.
         #
 
         class << self
-          def chrome(opts = {})
-            new({
-              browser_name: 'chrome'
-            }.merge(opts))
-          end
-
-          def edge(opts = {})
-            new({
-              browser_name: 'MicrosoftEdge'
-            }.merge(opts))
-          end
-          alias_method :microsoftedge, :edge
-
-          def firefox(opts = {})
-            new({
-              browser_name: 'firefox'
-            }.merge(opts))
-          end
-          alias_method :ff, :firefox
-
-          def safari(opts = {})
-            new({
-              browser_name: Selenium::WebDriver::Safari.technology_preview? ? "Safari Technology Preview" : 'safari'
-            }.merge(opts))
-          end
-
-          def htmlunit(opts = {})
-            new({
-              browser_name: 'htmlunit'
-            }.merge(opts))
-          end
-
-          def internet_explorer(opts = {})
-            new({
-              browser_name: 'internet explorer',
-              platform_name: :windows
-            }.merge(opts))
-          end
-          alias_method :ie, :internet_explorer
-
           def always_match(capabilities)
             new(always_match: capabilities)
           end
@@ -134,7 +83,8 @@ module Selenium
 
             # Remote Server Specific
             if data.key?('webdriver.remote.sessionid')
-              caps[:remote_session_id] = data.delete('webdriver.remote.sessionid')
+              caps[:remote_session_id] =
+                data.delete('webdriver.remote.sessionid')
             end
 
             KNOWN.each do |cap|
@@ -149,7 +99,7 @@ module Selenium
           end
 
           def camel_case(str_or_sym)
-            str_or_sym.to_s.gsub(/_([a-z])/) { Regexp.last_match(1).upcase }
+            str_or_sym.to_s.gsub(/_([a-z])/) { Regexp.last_match(1)&.upcase }
           end
 
           private
@@ -269,7 +219,7 @@ module Selenium
           as_json == other.as_json
         end
 
-        alias_method :eql?, :==
+        alias eql? ==
 
         protected
 
diff -pruN 4.4.0-1/lib/selenium/webdriver/remote/commands.rb 4.38.0-1/lib/selenium/webdriver/remote/commands.rb
--- 4.4.0-1/lib/selenium/webdriver/remote/commands.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/remote/commands.rb	1970-01-01 00:00:00.000000000 +0000
@@ -1,172 +0,0 @@
-# frozen_string_literal: true
-
-# Licensed to the Software Freedom Conservancy (SFC) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The SFC licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#   http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License.
-
-module Selenium
-  module WebDriver
-    module Remote
-
-      #
-      # https://w3c.github.io/webdriver/#endpoints
-      # @api private
-      #
-
-      class Bridge
-        COMMANDS = {
-          status: [:get, 'status'],
-
-          #
-          # session handling
-          #
-
-          new_session: [:post, 'session'],
-          delete_session: [:delete, 'session/:session_id'],
-
-          #
-          # basic driver
-          #
-
-          get: [:post, 'session/:session_id/url'],
-          get_current_url: [:get, 'session/:session_id/url'],
-          back: [:post, 'session/:session_id/back'],
-          forward: [:post, 'session/:session_id/forward'],
-          refresh: [:post, 'session/:session_id/refresh'],
-          get_title: [:get, 'session/:session_id/title'],
-
-          #
-          # window and Frame handling
-          #
-
-          get_window_handle: [:get, 'session/:session_id/window'],
-          new_window: [:post, 'session/:session_id/window/new'],
-          close_window: [:delete, 'session/:session_id/window'],
-          switch_to_window: [:post, 'session/:session_id/window'],
-          get_window_handles: [:get, 'session/:session_id/window/handles'],
-          fullscreen_window: [:post, 'session/:session_id/window/fullscreen'],
-          minimize_window: [:post, 'session/:session_id/window/minimize'],
-          maximize_window: [:post, 'session/:session_id/window/maximize'],
-          set_window_rect: [:post, 'session/:session_id/window/rect'],
-          get_window_rect: [:get, 'session/:session_id/window/rect'],
-          switch_to_frame: [:post, 'session/:session_id/frame'],
-          switch_to_parent_frame: [:post, 'session/:session_id/frame/parent'],
-
-          #
-          # element
-          #
-
-          find_element: [:post, 'session/:session_id/element'],
-          find_elements: [:post, 'session/:session_id/elements'],
-          find_child_element: [:post, 'session/:session_id/element/:id/element'],
-          find_child_elements: [:post, 'session/:session_id/element/:id/elements'],
-          find_shadow_child_element: [:post, 'session/:session_id/shadow/:id/element'],
-          find_shadow_child_elements: [:post, 'session/:session_id/shadow/:id/elements'],
-          get_active_element: [:get, 'session/:session_id/element/active'],
-          get_element_shadow_root: [:get, 'session/:session_id/element/:id/shadow'],
-          is_element_selected: [:get, 'session/:session_id/element/:id/selected'],
-          get_element_attribute: [:get, 'session/:session_id/element/:id/attribute/:name'],
-          get_element_property: [:get, 'session/:session_id/element/:id/property/:name'],
-          get_element_css_value: [:get, 'session/:session_id/element/:id/css/:property_name'],
-          get_element_aria_role: [:get, 'session/:session_id/element/:id/computedrole'],
-          get_element_aria_label: [:get, 'session/:session_id/element/:id/computedlabel'],
-          get_element_text: [:get, 'session/:session_id/element/:id/text'],
-          get_element_tag_name: [:get, 'session/:session_id/element/:id/name'],
-          get_element_rect: [:get, 'session/:session_id/element/:id/rect'],
-          is_element_enabled: [:get, 'session/:session_id/element/:id/enabled'],
-
-          #
-          # document handling
-          #
-
-          get_page_source: [:get, 'session/:session_id/source'],
-          execute_script: [:post, 'session/:session_id/execute/sync'],
-          execute_async_script: [:post, 'session/:session_id/execute/async'],
-
-          #
-          # cookies
-          #
-
-          get_all_cookies: [:get, 'session/:session_id/cookie'],
-          get_cookie: [:get, 'session/:session_id/cookie/:name'],
-          add_cookie: [:post, 'session/:session_id/cookie'],
-          delete_cookie: [:delete, 'session/:session_id/cookie/:name'],
-          delete_all_cookies: [:delete, 'session/:session_id/cookie'],
-
-          #
-          # timeouts
-          #
-
-          get_timeouts: [:get, 'session/:session_id/timeouts'],
-          set_timeout: [:post, 'session/:session_id/timeouts'],
-
-          #
-          # actions
-          #
-
-          actions: [:post, 'session/:session_id/actions'],
-          release_actions: [:delete, 'session/:session_id/actions'],
-          print_page: [:post, 'session/:session_id/print'],
-
-          #
-          # Element Operations
-          #
-
-          element_click: [:post, 'session/:session_id/element/:id/click'],
-          element_clear: [:post, 'session/:session_id/element/:id/clear'],
-          element_send_keys: [:post, 'session/:session_id/element/:id/value'],
-
-          #
-          # alerts
-          #
-
-          dismiss_alert: [:post, 'session/:session_id/alert/dismiss'],
-          accept_alert: [:post, 'session/:session_id/alert/accept'],
-          get_alert_text: [:get, 'session/:session_id/alert/text'],
-          send_alert_text: [:post, 'session/:session_id/alert/text'],
-
-          #
-          # screenshot
-          #
-
-          take_screenshot: [:get, 'session/:session_id/screenshot'],
-          take_element_screenshot: [:get, 'session/:session_id/element/:id/screenshot'],
-
-          #
-          # server extensions
-          #
-
-          upload_file: [:post, 'session/:session_id/se/file'],
-
-          #
-          # virtual-authenticator
-          #
-
-          add_virtual_authenticator: [:post, 'session/:session_id/webauthn/authenticator'],
-          remove_virtual_authenticator: [:delete, 'session/:session_id/webauthn/authenticator/:authenticatorId'],
-          add_credential: [:post, 'session/:session_id/webauthn/authenticator/:authenticatorId/credential'],
-          get_credentials: [:get, 'session/:session_id/webauthn/authenticator/:authenticatorId/credentials'],
-          remove_credential: [:delete,
-                              'session/:session_id/webauthn/authenticator/:authenticatorId/credentials/:credentialId'],
-          remove_all_credentials: [:delete, 'session/:session_id/webauthn/authenticator/:authenticatorId/credentials'],
-          set_user_verified: [:post, 'session/:session_id/webauthn/authenticator/:authenticatorId/uv']
-
-        }.freeze
-
-      end # Bridge
-    end # Remote
-  end # WebDriver
-end # Selenium
diff -pruN 4.4.0-1/lib/selenium/webdriver/remote/driver.rb 4.38.0-1/lib/selenium/webdriver/remote/driver.rb
--- 4.4.0-1/lib/selenium/webdriver/remote/driver.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/remote/driver.rb	2025-11-02 08:23:03.000000000 +0000
@@ -20,7 +20,6 @@
 module Selenium
   module WebDriver
     module Remote
-
       #
       # Driver implementation for remote server.
       # @api private
@@ -29,19 +28,18 @@ module Selenium
       class Driver < WebDriver::Driver
         include DriverExtensions::UploadsFiles
         include DriverExtensions::HasSessionId
+        include DriverExtensions::HasFileDownloads
 
-        def initialize(bridge: nil, listener: nil, **opts)
-          desired_capabilities = opts[:desired_capabilities]
-          if desired_capabilities.is_a?(Symbol)
-            unless Remote::Capabilities.respond_to?(desired_capabilities)
-              raise Error::WebDriverError, "invalid desired capability: #{desired_capabilities.inspect}"
-            end
+        def initialize(capabilities: nil, options: nil, service: nil, url: nil, **)
+          raise ArgumentError, "Can not set :service object on #{self.class}" if service
 
-            opts[:desired_capabilities] = Remote::Capabilities.__send__(desired_capabilities)
-          end
-          opts[:url] ||= "http://#{Platform.localhost}:4444/wd/hub"
-          super
+          url ||= "http://#{Platform.localhost}:4444/wd/hub"
+          caps = process_options(options, capabilities)
+          super(caps: caps, url: url, **)
           @bridge.file_detector = ->((filename, *)) { File.exist?(filename) && filename.to_s }
+          command_list = @bridge.command_list
+          @bridge.extend(WebDriver::Remote::Features)
+          @bridge.add_commands(command_list)
         end
 
         private
@@ -51,8 +49,32 @@ module Selenium
         end
 
         def devtools_version
-          capabilities['se:cdpVersion']&.split('.')&.first ||
-            raise(Error::WebDriverError, "DevTools is not supported by the Remote Server")
+          cdp_version = capabilities['se:cdpVersion']&.split('.')&.first
+          raise Error::WebDriverError, 'DevTools is not supported by the Remote Server' unless cdp_version
+
+          Integer(cdp_version)
+        end
+
+        def process_options(options, capabilities)
+          if options && capabilities
+            msg = "Don't use both :options and :capabilities when initializing #{self.class}, prefer :options"
+            raise ArgumentError, msg
+          elsif options.nil? && capabilities.nil?
+            raise ArgumentError, "#{self.class} needs :options to be set"
+          end
+          options ? options.as_json : generate_capabilities(capabilities)
+        end
+
+        def generate_capabilities(capabilities)
+          Array(capabilities).map { |cap|
+            if cap.is_a? Symbol
+              cap = WebDriver::Options.send(cap)
+            elsif !cap.respond_to? :as_json
+              msg = ":capabilities parameter only accepts objects responding to #as_json which #{cap.class} does not"
+              raise ArgumentError, msg
+            end
+            cap.as_json
+          }.inject(:merge)
         end
       end # Driver
     end # Remote
diff -pruN 4.4.0-1/lib/selenium/webdriver/remote/features.rb 4.38.0-1/lib/selenium/webdriver/remote/features.rb
--- 4.4.0-1/lib/selenium/webdriver/remote/features.rb	1970-01-01 00:00:00.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/remote/features.rb	2025-11-02 08:23:03.000000000 +0000
@@ -0,0 +1,75 @@
+# frozen_string_literal: true
+
+# Licensed to the Software Freedom Conservancy (SFC) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The SFC licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+module Selenium
+  module WebDriver
+    module Remote
+      module Features
+        REMOTE_COMMANDS = {
+          upload_file: [:post, 'session/:session_id/se/file'],
+          get_downloadable_files: [:get, 'session/:session_id/se/files'],
+          download_file: [:post, 'session/:session_id/se/files'],
+          delete_downloadable_files: [:delete, 'session/:session_id/se/files']
+        }.freeze
+
+        def add_commands(commands)
+          @command_list = command_list.merge(commands)
+        end
+
+        def command_list
+          @command_list ||= REMOTE_COMMANDS
+        end
+
+        def commands(command)
+          command_list[command]
+        end
+
+        def upload(local_file)
+          unless File.file?(local_file)
+            WebDriver.logger.error("File detector only works with files. #{local_file.inspect} isn`t a file!",
+                                   id: :file_detector)
+            raise Error::WebDriverError, "You are trying to upload something that isn't a file."
+          end
+
+          execute :upload_file, {}, {file: Zipper.zip_file(local_file)}
+        end
+
+        def upload_if_necessary(keys)
+          local_files = keys.first&.split("\n")&.filter_map { |key| @file_detector.call(Array(key)) }
+          return keys unless local_files&.any?
+
+          keys = local_files.map { |local_file| upload(local_file) }
+          Array(keys.join("\n"))
+        end
+
+        def downloadable_files
+          execute :get_downloadable_files
+        end
+
+        def download_file(name)
+          execute :download_file, {}, {name: name}
+        end
+
+        def delete_downloadable_files
+          execute :delete_downloadable_files
+        end
+      end
+    end # Remote
+  end # WebDriver
+end # Selenium
diff -pruN 4.4.0-1/lib/selenium/webdriver/remote/http/common.rb 4.38.0-1/lib/selenium/webdriver/remote/http/common.rb
--- 4.4.0-1/lib/selenium/webdriver/remote/http/common.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/remote/http/common.rb	2025-11-02 08:23:03.000000000 +0000
@@ -26,10 +26,18 @@ module Selenium
           CONTENT_TYPE    = 'application/json'
           DEFAULT_HEADERS = {
             'Accept' => CONTENT_TYPE,
-            'Content-Type' => "#{CONTENT_TYPE}; charset=UTF-8",
-            'User-Agent' => "selenium/#{WebDriver::VERSION} (ruby #{Platform.os})"
+            'Content-Type' => "#{CONTENT_TYPE}; charset=UTF-8"
           }.freeze
 
+          class << self
+            attr_accessor :extra_headers
+            attr_writer :user_agent
+
+            def user_agent
+              @user_agent ||= "selenium/#{WebDriver::VERSION} (ruby #{Platform.os})"
+            end
+          end
+
           attr_writer :server_url
 
           def quit_errors
@@ -40,17 +48,18 @@ module Selenium
             # hook for subclasses - will be called on Driver#quit
           end
 
+          # steep:ignore:start
           def call(verb, url, command_hash)
             url      = server_url.merge(url) unless url.is_a?(URI)
-            headers  = DEFAULT_HEADERS.dup
+            headers  = common_headers.dup
             headers['Cache-Control'] = 'no-cache' if verb == :get
 
             if command_hash
               payload                   = JSON.generate(command_hash)
               headers['Content-Length'] = payload.bytesize.to_s if %i[post put].include?(verb)
 
-              WebDriver.logger.info("   >>> #{url} | #{payload}")
-              WebDriver.logger.debug("     > #{headers.inspect}")
+              WebDriver.logger.debug("   >>> #{url} | #{payload}", id: :command)
+              WebDriver.logger.debug("     > #{headers.inspect}", id: :header)
             elsif verb == :post
               payload = '{}'
               headers['Content-Length'] = '2'
@@ -58,9 +67,20 @@ module Selenium
 
             request verb, url, headers, payload
           end
+          # steep:ignore:end
 
           private
 
+          def common_headers
+            @common_headers ||= begin
+              headers = DEFAULT_HEADERS.dup
+              headers['User-Agent'] = Common.user_agent
+              headers = headers.merge(Common.extra_headers || {})
+
+              headers
+            end
+          end
+
           def server_url
             return @server_url if @server_url
 
@@ -75,7 +95,7 @@ module Selenium
             code = code.to_i
             body = body.to_s.strip
             content_type = content_type.to_s
-            WebDriver.logger.info("<- #{body}")
+            WebDriver.logger.debug("<- #{body}", id: :command)
 
             if content_type.include? CONTENT_TYPE
               raise Error::WebDriverError, "empty body: #{content_type.inspect} (#{code})\n#{body}" if body.empty?
diff -pruN 4.4.0-1/lib/selenium/webdriver/remote/http/curb.rb 4.38.0-1/lib/selenium/webdriver/remote/http/curb.rb
--- 4.4.0-1/lib/selenium/webdriver/remote/http/curb.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/remote/http/curb.rb	2025-11-02 08:23:03.000000000 +0000
@@ -22,7 +22,6 @@ require 'curb'
 module Selenium
   module WebDriver
     module Remote
-
       module Http
         #
         # An alternative to the default Net::HTTP client.
@@ -38,6 +37,12 @@ module Selenium
         #
 
         class Curb < Common
+          attr_accessor :timeout
+
+          def initialize(timeout: nil)
+            @timeout = timeout
+            super()
+          end
 
           def quit_errors
             [Curl::Err::RecvError] + super
@@ -55,7 +60,7 @@ module Selenium
             client.headers = headers
 
             # http://github.com/taf2/curb/issues/issue/33
-            client.head   = false
+            client.head = false
             client.delete = false
 
             case verb
@@ -82,11 +87,10 @@ module Selenium
             @client ||= begin
               c = Curl::Easy.new
 
-              c.max_redirects   = MAX_REDIRECTS
+              c.max_redirects = MAX_REDIRECTS
               c.follow_location = true
-              c.timeout         = @timeout if @timeout
-              c.verbose         = WebDriver.logger.info?
-
+              c.timeout = timeout if timeout
+              c.verbose = WebDriver.logger.debug?
               c
             end
           end
diff -pruN 4.4.0-1/lib/selenium/webdriver/remote/http/default.rb 4.38.0-1/lib/selenium/webdriver/remote/http/default.rb
--- 4.4.0-1/lib/selenium/webdriver/remote/http/default.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/remote/http/default.rb	2025-11-02 08:23:03.000000000 +0000
@@ -16,8 +16,6 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-
-require 'net/https'
 require 'ipaddr'
 
 module Selenium
@@ -96,10 +94,12 @@ module Selenium
             end
 
             if response.is_a? Net::HTTPRedirection
+              WebDriver.logger.debug("Redirect to #{response['Location']}; times: #{redirects}")
               raise Error::WebDriverError, 'too many redirects' if redirects >= MAX_REDIRECTS
 
               request(:get, URI.parse(response['Location']), DEFAULT_HEADERS.dup, nil, redirects + 1)
             else
+              WebDriver.logger.debug("   <<<  #{response.instance_variable_get(:@header).inspect}", id: :header)
               create_response response.code, response.body, response.content_type
             end
           end
diff -pruN 4.4.0-1/lib/selenium/webdriver/remote/response.rb 4.38.0-1/lib/selenium/webdriver/remote/response.rb
--- 4.4.0-1/lib/selenium/webdriver/remote/response.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/remote/response.rb	2025-11-02 08:23:03.000000000 +0000
@@ -20,7 +20,6 @@
 module Selenium
   module WebDriver
     module Remote
-
       #
       # @api private
       #
@@ -29,7 +28,7 @@ module Selenium
         attr_reader :code, :payload
 
         def initialize(code, payload = nil)
-          @code    = code
+          @code = code
           @payload = payload || {}
 
           assert_ok
@@ -38,11 +37,8 @@ module Selenium
         def error
           error, message, backtrace = process_error
           klass = Error.for_error(error) || return
-
           ex = klass.new(message)
-          ex.set_backtrace(caller)
-          add_backtrace ex, backtrace
-
+          add_cause(ex, error, backtrace)
           ex
         end
 
@@ -60,17 +56,13 @@ module Selenium
           raise Error::ServerError, self
         end
 
-        def add_backtrace(ex, server_trace)
-          return unless server_trace
-
-          backtrace = case server_trace
-                      when Array
-                        backtrace_from_remote(server_trace)
-                      when String
-                        server_trace.split("\n")
-                      end
-
-          ex.set_backtrace(backtrace + ex.backtrace)
+        def add_cause(ex, error, backtrace)
+          cause = Error::WebDriverError.new
+          backtrace = backtrace_from_remote(backtrace) if backtrace.is_a?(Array)
+          cause.set_backtrace(backtrace)
+          raise ex, cause: cause
+        rescue Error.for_error(error)
+          ex
         end
 
         def backtrace_from_remote(server_trace)
@@ -79,14 +71,14 @@ module Selenium
 
             file = frame['fileName']
             line = frame['lineNumber']
-            meth = frame['methodName']
+            method = frame['methodName']
 
             class_name = frame['className']
             file = "#{class_name}(#{file})" if class_name
 
-            meth = 'unknown' if meth.nil? || meth.empty?
+            method = 'unknown' if method.nil? || method.empty?
 
-            "[remote server] #{file}:#{line}:in `#{meth}'"
+            "[remote server] #{file}:#{line}:in `#{method}'"
           end
         end
 
diff -pruN 4.4.0-1/lib/selenium/webdriver/remote/server_error.rb 4.38.0-1/lib/selenium/webdriver/remote/server_error.rb
--- 4.4.0-1/lib/selenium/webdriver/remote/server_error.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/remote/server_error.rb	2025-11-02 08:23:03.000000000 +0000
@@ -23,9 +23,9 @@ module Selenium
       class ServerError < StandardError
         def initialize(response)
           if response.is_a? String
-            super(response)
+            super
           else
-            super("status code #{response.code}")
+            super("status code #{response.code}; payload #{response.payload}")
           end
         end
       end # ServerError
diff -pruN 4.4.0-1/lib/selenium/webdriver/remote.rb 4.38.0-1/lib/selenium/webdriver/remote.rb
--- 4.4.0-1/lib/selenium/webdriver/remote.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/remote.rb	2025-11-02 08:23:03.000000000 +0000
@@ -23,14 +23,15 @@ require 'selenium/webdriver/remote/serve
 module Selenium
   module WebDriver
     module Remote
+      autoload :Features,     'selenium/webdriver/remote/features'
       autoload :Bridge,       'selenium/webdriver/remote/bridge'
+      autoload :BiDiBridge,   'selenium/webdriver/remote/bidi_bridge'
       autoload :Driver,       'selenium/webdriver/remote/driver'
       autoload :Response,     'selenium/webdriver/remote/response'
       autoload :Capabilities, 'selenium/webdriver/remote/capabilities'
-      autoload :COMMANDS,     'selenium/webdriver/remote/commands'
 
       module Http
-        autoload :Common,  'selenium/webdriver/remote/http/common'
+        autoload :Common, 'selenium/webdriver/remote/http/common'
         autoload :Default, 'selenium/webdriver/remote/http/default'
       end
     end
diff -pruN 4.4.0-1/lib/selenium/webdriver/safari/driver.rb 4.38.0-1/lib/selenium/webdriver/safari/driver.rb
--- 4.4.0-1/lib/selenium/webdriver/safari/driver.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/safari/driver.rb	2025-11-02 08:23:03.000000000 +0000
@@ -20,7 +20,6 @@
 module Selenium
   module WebDriver
     module Safari
-
       #
       # Driver implementation for Safari.
       # @api private
@@ -28,8 +27,14 @@ module Selenium
 
       class Driver < WebDriver::Driver
         EXTENSIONS = [DriverExtensions::HasDebugger,
-                      DriverExtensions::HasApplePermissions,
-                      DriverExtensions::HasWebStorage].freeze
+                      DriverExtensions::HasApplePermissions].freeze
+
+        include LocalDriver
+
+        def initialize(options: nil, service: nil, url: nil, **)
+          caps, url = initialize_local_driver(options, service, url)
+          super(caps: caps, url: url, **)
+        end
 
         def browser
           :safari
diff -pruN 4.4.0-1/lib/selenium/webdriver/safari/features.rb 4.38.0-1/lib/selenium/webdriver/safari/features.rb
--- 4.4.0-1/lib/selenium/webdriver/safari/features.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/safari/features.rb	2025-11-02 08:23:03.000000000 +0000
@@ -21,7 +21,6 @@ module Selenium
   module WebDriver
     module Safari
       module Features
-
         # https://developer.apple.com/library/content/documentation/NetworkingInternetWeb/Conceptual/WebDriverEndpointDoc/Commands/Commands.html
         SAFARI_COMMANDS = {
           get_permissions: [:get, 'session/:session_id/apple/permissions'],
@@ -29,8 +28,12 @@ module Selenium
           attach_debugger: [:post, 'session/:session_id/apple/attach_debugger']
         }.freeze
 
+        def command_list
+          SAFARI_COMMANDS.merge(self.class::COMMANDS)
+        end
+
         def commands(command)
-          SAFARI_COMMANDS[command] || self.class::COMMANDS[command]
+          command_list[command]
         end
 
         def permissions
@@ -44,7 +47,6 @@ module Selenium
         def attach_debugger
           execute :attach_debugger, {}, {}
         end
-
       end # Bridge
     end # Safari
   end # WebDriver
diff -pruN 4.4.0-1/lib/selenium/webdriver/safari/options.rb 4.38.0-1/lib/selenium/webdriver/safari/options.rb
--- 4.4.0-1/lib/selenium/webdriver/safari/options.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/safari/options.rb	2025-11-02 08:23:03.000000000 +0000
@@ -26,7 +26,7 @@ module Selenium
         # @see https://developer.apple.com/documentation/webkit/about_webdriver_for_safari
         CAPABILITIES = {automatic_inspection: 'safari:automaticInspection',
                         automatic_profiling: 'safari:automaticProfiling'}.freeze
-        BROWSER = 'safari'
+        BROWSER = Selenium::WebDriver::Safari.technology_preview? ? 'Safari Technology Preview' : 'safari'
 
         def add_option(name, value = nil)
           key = name.is_a?(Hash) ? name.keys.first : name
@@ -35,6 +35,10 @@ module Selenium
           super
         end
 
+        def as_json(*)
+          @options[:browser_name] = Safari.technology_preview? ? 'Safari Technology Preview' : 'safari'
+          super
+        end
       end # Options
     end # Safari
   end # WebDriver
diff -pruN 4.4.0-1/lib/selenium/webdriver/safari/service.rb 4.38.0-1/lib/selenium/webdriver/safari/service.rb
--- 4.4.0-1/lib/selenium/webdriver/safari/service.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/safari/service.rb	2025-11-02 08:23:03.000000000 +0000
@@ -23,11 +23,17 @@ module Selenium
       class Service < WebDriver::Service
         DEFAULT_PORT = 7050
         EXECUTABLE = 'safaridriver'
-        MISSING_TEXT = <<~ERROR
-          Unable to find Apple's safaridriver which comes with Safari 10.
-          More info at https://webkit.org/blog/6900/webdriver-support-in-safari-10/
-        ERROR
         SHUTDOWN_SUPPORTED = false
+        DRIVER_PATH_ENV_KEY = 'SE_SAFARIDRIVER'
+        def initialize(path: nil, port: nil, log: nil, args: nil)
+          raise Error::WebDriverError, 'Safari Service does not support setting log output' if log
+
+          super
+        end
+
+        def log=(*)
+          raise Error::WebDriverError, 'Safari Service does not support setting log output'
+        end
       end # Service
     end # Safari
   end # WebDriver
diff -pruN 4.4.0-1/lib/selenium/webdriver/safari.rb 4.38.0-1/lib/selenium/webdriver/safari.rb
--- 4.4.0-1/lib/selenium/webdriver/safari.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/safari.rb	2025-11-02 08:23:03.000000000 +0000
@@ -29,7 +29,7 @@ module Selenium
         attr_accessor :use_technology_preview
 
         def technology_preview
-          "/Applications/Safari\ Technology\ Preview.app/Contents/MacOS/safaridriver"
+          '/Applications/Safari Technology Preview.app/Contents/MacOS/safaridriver'
         end
 
         def technology_preview!
diff -pruN 4.4.0-1/lib/selenium/webdriver/support/block_event_listener.rb 4.38.0-1/lib/selenium/webdriver/support/block_event_listener.rb
--- 4.4.0-1/lib/selenium/webdriver/support/block_event_listener.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/support/block_event_listener.rb	2025-11-02 08:23:03.000000000 +0000
@@ -25,8 +25,8 @@ module Selenium
           @callback = callback
         end
 
-        def method_missing(meth, *args) # rubocop:disable Style/MissingRespondToMissing
-          @callback.call meth, *args
+        def method_missing(meth, *) # rubocop:disable Style/MissingRespondToMissing
+          @callback.call(meth, *)
         end
       end # BlockEventListener
     end # Support
diff -pruN 4.4.0-1/lib/selenium/webdriver/support/cdp/domain.rb.erb 4.38.0-1/lib/selenium/webdriver/support/cdp/domain.rb.erb
--- 4.4.0-1/lib/selenium/webdriver/support/cdp/domain.rb.erb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/support/cdp/domain.rb.erb	1970-01-01 00:00:00.000000000 +0000
@@ -1,63 +0,0 @@
-# frozen_string_literal: true
-
-# Licensed to the Software Freedom Conservancy (SFC) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The SFC licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#   http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License.
-
-# This file is automatically generated. Any changes will be lost!
-module Selenium
-  module DevTools
-    module <%= version %>
-      class <%= domain[:domain] %>
-        <% if domain[:events] %>
-        EVENTS = {
-          <% domain[:events].each do |event| %>
-          <%= h.snake_case(event[:name]) %>: '<%= event[:name] %>',
-          <% end %>
-        }.freeze
-        <% end %>
-
-        def initialize(devtools)
-          @devtools = devtools
-        end
-
-        def on(event, &block)
-          event = EVENTS[event] if event.is_a?(Symbol)
-          @devtools.callbacks["<%= domain[:domain] %>.#{event}"] << block
-        end
-
-        <% domain[:commands].each do |command| %>
-        <% if command[:parameters] %>
-        def <%= h.snake_case(command[:name]) %>(<%= h.kwargs(command[:parameters]) %>)
-        <% else %>
-        def <%= h.snake_case(command[:name]) %>
-        <% end %>
-          <% if command[:parameters] %>
-          @devtools.send_cmd('<%= domain[:domain] %>.<%= command[:name] %>',
-            <% until command[:parameters].empty? %>
-              <% parameter = command[:parameters].shift %>
-                             <%= parameter[:name] %>: <%= h.snake_case(parameter[:name]) %><%= command[:parameters].empty? ? ')' : ',' %>
-            <% end %>
-          <% else %>
-          @devtools.send_cmd('<%= domain[:domain] %>.<%= command[:name] %>')
-          <% end %>
-        end
-
-        <% end %>
-      end # <%= domain[:domain] %>
-    end # <%= version %>
-  end # DevTools
-end # Selenium
diff -pruN 4.4.0-1/lib/selenium/webdriver/support/cdp_client_generator.rb 4.38.0-1/lib/selenium/webdriver/support/cdp_client_generator.rb
--- 4.4.0-1/lib/selenium/webdriver/support/cdp_client_generator.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/support/cdp_client_generator.rb	1970-01-01 00:00:00.000000000 +0000
@@ -1,108 +0,0 @@
-# frozen_string_literal: true
-
-# Licensed to the Software Freedom Conservancy (SFC) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The SFC licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-#
-#   http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License.
-
-require 'erb'
-require 'fileutils'
-require 'json'
-
-module Selenium
-  module WebDriver
-    module Support
-      class CDPClientGenerator
-        # Input JSON files are generated from PDL tasks.
-        TEMPLATE_PATH = File.expand_path('cdp/domain.rb.erb', __dir__)
-
-        RESERVED_KEYWORDS = %w[end].freeze
-
-        def call(output_dir:, version:, browser_protocol_path: nil, js_protocol_path: nil, loader_path: nil, **)
-          @template = ERB.new(File.read(TEMPLATE_PATH))
-          @output_dir = output_dir
-          @loader_path = loader_path || "#{@output_dir}.rb"
-          @version = version
-
-          browser_protocol_path ||= File.expand_path('cdp/browser_protocol.json', __dir__)
-          js_protocol_path ||= File.expand_path('cdp/js_protocol.json', __dir__)
-
-          browser_protocol = JSON.parse(File.read(browser_protocol_path), symbolize_names: true)
-          js_protocol = JSON.parse(File.read(js_protocol_path), symbolize_names: true)
-
-          FileUtils.mkdir_p(@output_dir)
-
-          browser_protocol[:domains].each { |domain| process_domain(domain) }
-          js_protocol[:domains].each { |domain| process_domain(domain) }
-          require_file
-        end
-
-        def process_domain(domain)
-          result = @template.result_with_hash(domain: domain, version: @version.upcase, h: self)
-          filename = File.join(@output_dir, "#{snake_case(domain[:domain])}.rb")
-          File.write(filename, remove_empty_lines(result))
-        end
-
-        def snake_case(string)
-          name = string.gsub('JavaScript', 'Javascript')
-                       .gsub(/([A-Z]+)([A-Z][a-z]{2,})/, '\1_\2')
-                       .gsub(/([a-z\d])([A-Z])/, '\1_\2')
-                       .downcase
-          # Certain CDP parameters conflict with Ruby keywords
-          # so we prefix the name with underscore.
-          name = "_#{name}" if RESERVED_KEYWORDS.include?(name)
-
-          name
-        end
-
-        def kwargs(parameters)
-          parameters = parameters.map do |parameter|
-            if parameter[:optional]
-              "#{snake_case(parameter[:name])}: nil"
-            else
-              "#{snake_case(parameter[:name])}:"
-            end
-          end
-          parameters.join(', ')
-        end
-
-        def remove_empty_lines(string)
-          string.split("\n").grep_v(/^\s+$/).join("\n")
-        end
-
-        def require_file
-          # rubocop:disable Lint/InterpolationCheck
-          dynamic_location = '#{File.dirname(File.absolute_path(__FILE__))}'
-          # rubocop:enable Lint/InterpolationCheck
-
-          require_all = "Dir.glob(\"#{dynamic_location}/#{@version}/*\", &method(:require))"
-          File.write(@loader_path, require_all)
-        end
-      end
-    end
-  end
-end
-
-if $PROGRAM_NAME == __FILE__
-  browser_protocol_path, js_protocol_path, output_dir, loader_path, version = *ARGV
-
-  Selenium::WebDriver::Support::CDPClientGenerator.new.call(
-    browser_protocol_path: browser_protocol_path,
-    js_protocol_path: js_protocol_path,
-    output_dir: output_dir,
-    loader_path: loader_path,
-    version: version
-  )
-end
diff -pruN 4.4.0-1/lib/selenium/webdriver/support/color.rb 4.38.0-1/lib/selenium/webdriver/support/color.rb
--- 4.4.0-1/lib/selenium/webdriver/support/color.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/support/color.rb	2025-11-02 08:23:03.000000000 +0000
@@ -21,29 +21,29 @@ module Selenium
   module WebDriver
     module Support
       class Color
-        RGB_PATTERN = %r{^\s*rgb\(\s*(\d{1,3})\s*,
+        RGB_PATTERN = /^\s*rgb\(\s*(\d{1,3})\s*,
                           \s*(\d{1,3})\s*,
-                          \s*(\d{1,3})\s*\)\s*$}x.freeze
-        RGB_PCT_PATTERN = %r{^\s*rgb\(\s*(\d{1,3}|\d{1,2}\.\d+)%\s*,
+                          \s*(\d{1,3})\s*\)\s*$/x
+        RGB_PCT_PATTERN = /^\s*rgb\(\s*(\d{1,3}|\d{1,2}\.\d+)%\s*,
                               \s*(\d{1,3}|\d{1,2}\.\d+)%\s*,
-                              \s*(\d{1,3}|\d{1,2}\.\d+)%\s*\)\s*$}x.freeze
-        RGBA_PATTERN = %r{^\s*rgba\(\s*(\d{1,3})\s*,
+                              \s*(\d{1,3}|\d{1,2}\.\d+)%\s*\)\s*$/x
+        RGBA_PATTERN = /^\s*rgba\(\s*(\d{1,3})\s*,
                           \s*(\d{1,3})\s*,
                           \s*(\d{1,3})\s*,
-                          \s*(0|1|0\.\d+)\s*\)\s*$}x.freeze
-        RGBA_PCT_PATTERN = %r{^\s*rgba\(\s*(\d{1,3}|\d{1,2}\.\d+)
+                          \s*(0|1|0\.\d+)\s*\)\s*$/x
+        RGBA_PCT_PATTERN = /^\s*rgba\(\s*(\d{1,3}|\d{1,2}\.\d+)
                               %\s*,\s*(\d{1,3}|\d{1,2}\.\d+)
                               %\s*,\s*(\d{1,3}|\d{1,2}\.\d+)
-                              %\s*,\s*(0|1|0\.\d+)\s*\)\s*$}x.freeze
-        HEX_PATTERN = /#(\h{2})(\h{2})(\h{2})/.freeze
-        HEX3_PATTERN = /#(\h)(\h)(\h)/.freeze
-        HSL_PATTERN = %r{^\s*hsl\(\s*(\d{1,3})\s*,
+                              %\s*,\s*(0|1|0\.\d+)\s*\)\s*$/x
+        HEX_PATTERN = /#(\h{2})(\h{2})(\h{2})/
+        HEX3_PATTERN = /#(\h)(\h)(\h)/
+        HSL_PATTERN = /^\s*hsl\(\s*(\d{1,3})\s*,
                          \s*(\d{1,3})%\s*,
-                         \s*(\d{1,3})%\s*\)\s*$}x.freeze
-        HSLA_PATTERN = %r{^\s*hsla\(\s*(\d{1,3})\s*,
+                         \s*(\d{1,3})%\s*\)\s*$/x
+        HSLA_PATTERN = /^\s*hsla\(\s*(\d{1,3})\s*,
                           \s*(\d{1,3})%\s*,
                           \s*(\d{1,3})%\s*,
-                          \s*(0|1|0\.\d+)\s*\)\s*$}x.freeze
+                          \s*(0|1|0\.\d+)\s*\)\s*$/x
 
         attr_reader :red, :green, :blue, :alpha
 
@@ -83,8 +83,8 @@ module Selenium
             g = r
             b = r
           else
-            luminocity2 = l < 0.5 ? l * (1 + s) : l + s - (l * s)
-            luminocity1 = (2 * l) - luminocity2
+            luminocity2 = l < 0.5 ? l * (s + 1) : l + s - (l * s)
+            luminocity1 = (l * 2) - luminocity2
 
             r = hue_to_rgb(luminocity1, luminocity2, h + (1.0 / 3.0))
             g = hue_to_rgb(luminocity1, luminocity2, h)
@@ -122,7 +122,7 @@ module Selenium
 
           [red, green, blue, alpha] == [other.red, other.green, other.blue, other.alpha]
         end
-        alias_method :eql?, :==
+        alias eql? ==
 
         def hash
           [red, green, blue, alpha, self.class].hash
diff -pruN 4.4.0-1/lib/selenium/webdriver/support/event_firing_bridge.rb 4.38.0-1/lib/selenium/webdriver/support/event_firing_bridge.rb
--- 4.4.0-1/lib/selenium/webdriver/support/event_firing_bridge.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/support/event_firing_bridge.rb	2025-11-02 08:23:03.000000000 +0000
@@ -112,16 +112,16 @@ module Selenium
           @driver ||= Driver.new(bridge: self)
         end
 
-        def dispatch(name, *args)
-          @listener.__send__("before_#{name}", *args)
+        def dispatch(name, *)
+          @listener.__send__(:"before_#{name}", *)
           returned = yield
-          @listener.__send__("after_#{name}", *args)
+          @listener.__send__(:"after_#{name}", *)
 
           returned
         end
 
-        def method_missing(meth, *args, &blk) # rubocop:disable Style/MissingRespondToMissing
-          @delegate.__send__(meth, *args, &blk)
+        def method_missing(meth, ...) # rubocop:disable Style/MissingRespondToMissing
+          @delegate.__send__(meth, ...)
         end
       end # EventFiringBridge
     end # Support
diff -pruN 4.4.0-1/lib/selenium/webdriver/support/guards/guard.rb 4.38.0-1/lib/selenium/webdriver/support/guards/guard.rb
--- 4.4.0-1/lib/selenium/webdriver/support/guards/guard.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/support/guards/guard.rb	2025-11-02 08:23:03.000000000 +0000
@@ -21,15 +21,13 @@ module Selenium
   module WebDriver
     module Support
       class Guards
-
         #
         # Guard derived from RSpec example metadata.
         # @api private
         #
 
         class Guard
-
-          attr_reader :guarded, :type, :messages, :reason
+          attr_reader :guarded, :type, :messages, :reason, :tracker
 
           def initialize(guarded, type, guards = nil)
             @guarded = guarded
@@ -38,24 +36,25 @@ module Selenium
             @messages[:unknown] = 'TODO: Investigate why this is failing and file a bug report'
             @type = type
 
-            @reason = @guarded.delete(:reason)
+            @reason = @guarded[:reason] || 'No reason given'
+            @guarded[:reason] = @reason
           end
 
           def message
-            details = case @reason
+            details = case reason
                       when Integer
-                        "Bug Filed: #{@tracker}/#{@reason}"
+                        "Bug Filed: #{tracker}/#{reason}"
                       when Symbol
-                        @messages[@reason]
-                      when String
-                        @reason
+                        messages[reason]
                       else
-                        'no reason given'
+                        "Guarded by #{guarded};"
                       end
 
-            case @type
+            case type
             when :exclude
-              "Test not guarded because it breaks test run; #{details}"
+              "Test skipped because it breaks test run; #{details}"
+            when :flaky
+              "Test skipped because it is unreliable in this configuration; #{details}"
             when :exclusive
               "Test does not apply to this configuration; #{details}"
             else
@@ -73,9 +72,10 @@ module Selenium
             @type == :only
           end
 
-          # Bug is present on all configurations specified, but test can not be run because it breaks other tests
+          # Bug is present on all configurations specified, but test can not be run because it breaks other tests,
+          # or it is flaky and unreliable
           def exclude?
-            @type == :exclude
+            @type == :exclude || @type == :flaky
           end
 
           # Test only applies to configurations specified
diff -pruN 4.4.0-1/lib/selenium/webdriver/support/guards/guard_condition.rb 4.38.0-1/lib/selenium/webdriver/support/guards/guard_condition.rb
--- 4.4.0-1/lib/selenium/webdriver/support/guards/guard_condition.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/support/guards/guard_condition.rb	2025-11-02 08:23:03.000000000 +0000
@@ -21,7 +21,6 @@ module Selenium
   module WebDriver
     module Support
       class Guards
-
         #
         # Guard derived from RSpec example metadata.
         # @api private
@@ -44,7 +43,6 @@ module Selenium
 
             list.empty? || @execution.call(list)
           end
-
         end # GuardCondition
       end # Guards
     end # Support
diff -pruN 4.4.0-1/lib/selenium/webdriver/support/guards.rb 4.38.0-1/lib/selenium/webdriver/support/guards.rb
--- 4.4.0-1/lib/selenium/webdriver/support/guards.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/support/guards.rb	2025-11-02 08:23:03.000000000 +0000
@@ -24,7 +24,7 @@ module Selenium
   module WebDriver
     module Support
       class Guards
-        GUARD_TYPES = %i[except only exclude exclusive].freeze
+        GUARD_TYPES = %i[except only exclude exclusive flaky].freeze
 
         attr_reader :messages
         attr_accessor :bug_tracker
@@ -37,8 +37,10 @@ module Selenium
           @messages = {}
         end
 
-        def add_condition(name, condition = nil, &blk)
-          @guard_conditions << GuardCondition.new(name, condition, &blk)
+        def add_condition(name, condition = false, &block)
+          condition = false if condition.nil?
+          @guard_conditions << GuardCondition.new(name, condition, &block)
+          WebDriver.logger.debug "Running with Guard '#{name}' set to: #{condition}"
         end
 
         def add_message(name, message)
diff -pruN 4.4.0-1/lib/selenium/webdriver/support/relative_locator.rb 4.38.0-1/lib/selenium/webdriver/support/relative_locator.rb
--- 4.4.0-1/lib/selenium/webdriver/support/relative_locator.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/support/relative_locator.rb	2025-11-02 08:23:03.000000000 +0000
@@ -20,7 +20,6 @@
 module Selenium
   module WebDriver
     module Support
-
       #
       # @api private
       #
diff -pruN 4.4.0-1/lib/selenium/webdriver/support/select.rb 4.38.0-1/lib/selenium/webdriver/support/select.rb
--- 4.4.0-1/lib/selenium/webdriver/support/select.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/support/select.rb	2025-11-02 08:23:03.000000000 +0000
@@ -86,7 +86,7 @@ module Selenium
         #
         #     <option value="foo">Bar</option>
         #
-        # When slecting by :value, selects all options that have a value matching the argument. That is, when given "foo" this
+        # When selecting by :value, selects all options that have a value matching the argument. That is, when given "foo" this
         # would select an option like:
         #
         #     <option value="foo">Bar</option>
@@ -215,6 +215,8 @@ module Selenium
         end
 
         def select_option(option)
+          raise Error::UnsupportedOperationError, 'You may not select a disabled option' unless option.enabled?
+
           option.click unless option.selected?
         end
 
diff -pruN 4.4.0-1/lib/selenium/webdriver/version.rb 4.38.0-1/lib/selenium/webdriver/version.rb
--- 4.4.0-1/lib/selenium/webdriver/version.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver/version.rb	2025-11-02 08:23:03.000000000 +0000
@@ -19,6 +19,6 @@
 
 module Selenium
   module WebDriver
-    VERSION = '4.4.0'
+    VERSION = '4.38.0'
   end # WebDriver
 end # Selenium
diff -pruN 4.4.0-1/lib/selenium/webdriver.rb 4.38.0-1/lib/selenium/webdriver.rb
--- 4.4.0-1/lib/selenium/webdriver.rb	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/lib/selenium/webdriver.rb	2025-11-02 08:23:03.000000000 +0000
@@ -17,13 +17,12 @@
 # specific language governing permissions and limitations
 # under the License.
 
-require 'childprocess'
 require 'tmpdir'
 require 'fileutils'
 require 'date'
 require 'json'
-require 'set'
 require 'uri'
+require 'net/http'
 
 require 'selenium/webdriver/atoms'
 require 'selenium/webdriver/common'
@@ -34,9 +33,9 @@ module Selenium
     Point     = Struct.new(:x, :y)
     Dimension = Struct.new(:width, :height)
     Rectangle = Struct.new(:x, :y, :width, :height)
-    Location  = Struct.new(:latitude, :longitude, :altitude)
 
     autoload :BiDi,       'selenium/webdriver/bidi'
+    autoload :Chromium,   'selenium/webdriver/chromium'
     autoload :Chrome,     'selenium/webdriver/chrome'
     autoload :DevTools,   'selenium/webdriver/devtools'
     autoload :Edge,       'selenium/webdriver/edge'
@@ -49,7 +48,7 @@ module Selenium
     # @api private
 
     def self.root
-      @root ||= File.expand_path('..', __dir__)
+      @root ||= File.expand_path('..', __dir__.to_s)
     end
 
     #
@@ -85,8 +84,8 @@ module Selenium
     # @see Selenium::WebDriver::Support::AbstractEventListener
     #
 
-    def self.for(*args)
-      WebDriver::Driver.for(*args)
+    def self.for(*)
+      WebDriver::Driver.for(*)
     end
 
     #
@@ -95,8 +94,9 @@ module Selenium
     # @return [Logger]
     #
 
-    def self.logger
-      @logger ||= WebDriver::Logger.new
+    def self.logger(**)
+      level = $DEBUG || ENV.key?('DEBUG') ? :debug : :info
+      @logger ||= WebDriver::Logger.new('Selenium', default_level: level, **)
     end
   end # WebDriver
 end # Selenium
diff -pruN 4.4.0-1/selenium-webdriver.gemspec 4.38.0-1/selenium-webdriver.gemspec
--- 4.4.0-1/selenium-webdriver.gemspec	2022-08-19 20:44:45.000000000 +0000
+++ 4.38.0-1/selenium-webdriver.gemspec	2025-11-02 08:23:03.000000000 +0000
@@ -1,8 +1,6 @@
 # frozen_string_literal: true
 
 root = File.expand_path(File.dirname(__FILE__))
-raise "cwd must be #{root} when reading gemspec" if root != Dir.pwd
-
 $LOAD_PATH.push(File.expand_path('lib', root))
 require 'selenium/webdriver/version'
 
@@ -24,12 +22,15 @@ Gem::Specification.new do |s|
   s.homepage = 'https://selenium.dev'
   s.metadata = {
     'changelog_uri' => 'https://github.com/SeleniumHQ/selenium/blob/trunk/rb/CHANGES',
+    'documentation_uri' => 'https://www.selenium.dev/documentation/?tab=ruby',
+    'github_repo' => 'ssh://github.com/SeleniumHQ/selenium',
     'source_code_uri' => 'https://github.com/SeleniumHQ/selenium/tree/trunk/rb',
-    'rubygems_mfa_required' => 'true'
+    'rubygems_mfa_required' => 'true',
+    'funding_uri' => 'https://github.com/sponsors/SeleniumHQ'
   }
 
   s.required_rubygems_version = Gem::Requirement.new('> 1.3.1') if s.respond_to? :required_rubygems_version=
-  s.required_ruby_version = Gem::Requirement.new('>= 2.7')
+  s.required_ruby_version = Gem::Requirement.new('>= 3.2')
 
   s.files = [
     'CHANGES',
@@ -41,26 +42,28 @@ Gem::Specification.new do |s|
     'lib/selenium-webdriver.rb',
     'lib/selenium/server.rb',
     'lib/selenium/webdriver.rb'
-  ] + Dir['lib/selenium/webdriver/**/*']
+  ]
+  s.files += Dir['bin/**/*']
+  s.files += Dir['lib/selenium/webdriver/**/*']
 
+  s.bindir = 'bin'
   s.require_paths = ['lib']
 
-  s.add_runtime_dependency 'childprocess', ['>= 0.5', '< 5.0']
-  s.add_runtime_dependency 'rexml', ['~> 3.2', '>= 3.2.5']
-  s.add_runtime_dependency 'rubyzip', ['>= 1.2.2', '< 3.0']
-  s.add_runtime_dependency 'websocket', ['~> 1.0']
-
-  # childprocess requires ffi on windows but doesn't declare it in its dependencies
-  s.add_development_dependency 'ffi'
-  s.add_development_dependency 'pry', ['~> 0.14']
+  s.add_dependency 'base64', ['~> 0.2']
+  s.add_dependency 'logger', ['~> 1.4']
+  s.add_dependency 'rexml', ['~> 3.2', '>= 3.2.5']
+  s.add_dependency 'rubyzip', ['>= 1.2.2', '< 4.0']
+  s.add_dependency 'websocket', ['~> 1.0']
+
+  s.add_development_dependency 'git', ['~> 1.19']
   s.add_development_dependency 'rack', ['~> 2.0']
-  s.add_development_dependency 'rake'
+  s.add_development_dependency 'rake', ['~> 13.0']
   s.add_development_dependency 'rspec', ['~> 3.0']
-  s.add_development_dependency 'rubocop', ['~> 1.31']
-  s.add_development_dependency 'rubocop-performance', ['~> 1.13']
-  s.add_development_dependency 'rubocop-rake'
-  s.add_development_dependency 'rubocop-rspec', ['~> 2.12']
+  s.add_development_dependency 'rubocop', ['~> 1.75']
+  s.add_development_dependency 'rubocop-performance', ['~> 1.25']
+  s.add_development_dependency 'rubocop-rake', ['~> 0.7']
+  s.add_development_dependency 'rubocop-rspec', ['~> 3.5']
   s.add_development_dependency 'webmock', ['~> 3.5']
   s.add_development_dependency 'webrick', ['~> 1.7']
-  s.add_development_dependency 'yard', ['~> 0.9.11']
+  s.add_development_dependency 'yard', ['~> 0.9.11', '>= 0.9.36']
 end
